taiko-geth

+12837
-7854

This is an overview of the changes between taiko-geth (taiko branch) and go-ethereum (v1.12.2 tag).

This show modifications to beacon files.

diff --git ethereum/go-ethereum/beacon/engine/types.go taikoxyz/taiko-geth/beacon/engine/types.go index f1801edd1a93c548936c7db378e0905db9b155cd..ad18c66e212e85ad04cf86467a670e1e53a0e77f 100644 --- ethereum/go-ethereum/beacon/engine/types.go +++ taikoxyz/taiko-geth/beacon/engine/types.go @@ -22,8 +22,8 @@ "math/big"   "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common/hexutil" + "github.com/ethereum/go-ethereum/core/rawdb" "github.com/ethereum/go-ethereum/core/types" - "github.com/ethereum/go-ethereum/crypto/kzg4844" "github.com/ethereum/go-ethereum/trie" )   @@ -36,6 +36,12 @@ Timestamp uint64 `json:"timestamp" gencodec:"required"` Random common.Hash `json:"prevRandao" gencodec:"required"` SuggestedFeeRecipient common.Address `json:"suggestedFeeRecipient" gencodec:"required"` Withdrawals []*types.Withdrawal `json:"withdrawals"` + BeaconRoot *common.Hash `json:"parentBeaconBlockRoot"` + + // CHANGE(taiko): extra fields. + BaseFeePerGas *big.Int `json:"baseFeePerGas" gencodec:"required"` + BlockMetadata *BlockMetadata `json:"blockMetadata" gencodec:"required"` + L1Origin *rawdb.L1Origin `json:"l1Origin" gencodec:"required"` }   // JSON type overrides for PayloadAttributes. @@ -43,6 +49,29 @@ type payloadAttributesMarshaling struct { Timestamp hexutil.Uint64 }   +//go:generate go run github.com/fjl/gencodec -type BlockMetadata -field-override blockMetadataMarshaling -out gen_blockmetadata.go + +// CHANGE(taiko): BlockMetadata represents a `BlockMetadata` struct defined in +// protocol. +type BlockMetadata struct { + // Fields defined in `LibData.blockMetadata`. + Beneficiary common.Address `json:"beneficiary" gencodec:"required"` + GasLimit uint64 `json:"gasLimit" gencodec:"required"` + Timestamp uint64 `json:"timestamp" gencodec:"required"` + MixHash common.Hash `json:"mixHash" gencodec:"required"` + + // Extra fields required in taiko-geth. + TxList []byte `json:"txList" gencodec:"required"` + HighestBlockID *big.Int `json:"highestBlockID" gencodec:"required"` + ExtraData []byte `json:"extraData" gencodec:"required"` +} + +// CHANGE(taiko): JSON type overrides for BlockMetadata. +type blockMetadataMarshaling struct { + Timestamp hexutil.Uint64 + TxList hexutil.Bytes +} + //go:generate go run github.com/fjl/gencodec -type ExecutableData -field-override executableDataMarshaling -out gen_ed.go   // ExecutableData is the data necessary to execute an EL payload. @@ -60,10 +89,14 @@ Timestamp uint64 `json:"timestamp" gencodec:"required"` ExtraData []byte `json:"extraData" gencodec:"required"` BaseFeePerGas *big.Int `json:"baseFeePerGas" gencodec:"required"` BlockHash common.Hash `json:"blockHash" gencodec:"required"` - Transactions [][]byte `json:"transactions" gencodec:"required"` + Transactions [][]byte `json:"transactions"` Withdrawals []*types.Withdrawal `json:"withdrawals"` BlobGasUsed *uint64 `json:"blobGasUsed"` ExcessBlobGas *uint64 `json:"excessBlobGas"` + + TxHash common.Hash `json:"txHash"` // CHANGE(taiko): allow passing txHash directly instead of transactions list + WithdrawalsHash common.Hash `json:"withdrawalsHash"` // CHANGE(taiko): allow passing WithdrawalsHash directly instead of withdrawals + TaikoBlock bool // CHANGE(taiko): whether this is a Taiko L2 block, only used by ExecutableDataToBlock }   // JSON type overrides for executableData. @@ -86,6 +119,7 @@ type ExecutionPayloadEnvelope struct { ExecutionPayload *ExecutableData `json:"executionPayload" gencodec:"required"` BlockValue *big.Int `json:"blockValue" gencodec:"required"` BlobsBundle *BlobsBundleV1 `json:"blobsBundle"` + Override bool `json:"shouldOverrideBuilder"` }   type BlobsBundleV1 struct { @@ -172,7 +206,7 @@ // // and that the blockhash of the constructed block matches the parameters. Nil // Withdrawals value will propagate through the returned block. Empty // Withdrawals value must be passed via non-nil, length 0 value in params. -func ExecutableDataToBlock(params ExecutableData, versionedHashes []common.Hash) (*types.Block, error) { +func ExecutableDataToBlock(params ExecutableData, versionedHashes []common.Hash, beaconRoot *common.Hash) (*types.Block, error) { txs, err := decodeTransactions(params.Transactions) if err != nil { return nil, err @@ -208,24 +242,25 @@ h := types.DeriveSha(types.Withdrawals(params.Withdrawals), trie.NewStackTrie(nil)) withdrawalsRoot = &h } header := &types.Header{ - ParentHash: params.ParentHash, - UncleHash: types.EmptyUncleHash, - Coinbase: params.FeeRecipient, - Root: params.StateRoot, - TxHash: types.DeriveSha(types.Transactions(txs), trie.NewStackTrie(nil)), - ReceiptHash: params.ReceiptsRoot, - Bloom: types.BytesToBloom(params.LogsBloom), - Difficulty: common.Big0, - Number: new(big.Int).SetUint64(params.Number), - GasLimit: params.GasLimit, - GasUsed: params.GasUsed, - Time: params.Timestamp, - BaseFee: params.BaseFeePerGas, - Extra: params.ExtraData, - MixDigest: params.Random, - WithdrawalsHash: withdrawalsRoot, - ExcessBlobGas: params.ExcessBlobGas, - BlobGasUsed: params.BlobGasUsed, + ParentHash: params.ParentHash, + UncleHash: types.EmptyUncleHash, + Coinbase: params.FeeRecipient, + Root: params.StateRoot, + TxHash: types.DeriveSha(types.Transactions(txs), trie.NewStackTrie(nil)), + ReceiptHash: params.ReceiptsRoot, + Bloom: types.BytesToBloom(params.LogsBloom), + Difficulty: common.Big0, + Number: new(big.Int).SetUint64(params.Number), + GasLimit: params.GasLimit, + GasUsed: params.GasUsed, + Time: params.Timestamp, + BaseFee: params.BaseFeePerGas, + Extra: params.ExtraData, + MixDigest: params.Random, + WithdrawalsHash: withdrawalsRoot, + ExcessBlobGas: params.ExcessBlobGas, + BlobGasUsed: params.BlobGasUsed, + ParentBeaconRoot: beaconRoot, } block := types.NewBlockWithHeader(header).WithBody(txs, nil /* uncles */).WithWithdrawals(params.Withdrawals) if block.Hash() != params.BlockHash { @@ -236,7 +271,7 @@ }   // BlockToExecutableData constructs the ExecutableData structure by filling the // fields from the given block. It assumes the given block is post-merge block. -func BlockToExecutableData(block *types.Block, fees *big.Int, blobs []kzg4844.Blob, commitments []kzg4844.Commitment, proofs []kzg4844.Proof) *ExecutionPayloadEnvelope { +func BlockToExecutableData(block *types.Block, fees *big.Int, sidecars []*types.BlobTxSidecar) *ExecutionPayloadEnvelope { data := &ExecutableData{ BlockHash: block.Hash(), ParentHash: block.ParentHash(), @@ -256,17 +291,19 @@ Withdrawals: block.Withdrawals(), BlobGasUsed: block.BlobGasUsed(), ExcessBlobGas: block.ExcessBlobGas(), } - blobsBundle := BlobsBundleV1{ + bundle := BlobsBundleV1{ Commitments: make([]hexutil.Bytes, 0), Blobs: make([]hexutil.Bytes, 0), Proofs: make([]hexutil.Bytes, 0), } - for i := range blobs { - blobsBundle.Blobs = append(blobsBundle.Blobs, hexutil.Bytes(blobs[i][:])) - blobsBundle.Commitments = append(blobsBundle.Commitments, hexutil.Bytes(commitments[i][:])) - blobsBundle.Proofs = append(blobsBundle.Proofs, hexutil.Bytes(proofs[i][:])) + for _, sidecar := range sidecars { + for j := range sidecar.Blobs { + bundle.Blobs = append(bundle.Blobs, hexutil.Bytes(sidecar.Blobs[j][:])) + bundle.Commitments = append(bundle.Commitments, hexutil.Bytes(sidecar.Commitments[j][:])) + bundle.Proofs = append(bundle.Proofs, hexutil.Bytes(sidecar.Proofs[j][:])) + } } - return &ExecutionPayloadEnvelope{ExecutionPayload: data, BlockValue: fees, BlobsBundle: &blobsBundle} + return &ExecutionPayloadEnvelope{ExecutionPayload: data, BlockValue: fees, BlobsBundle: &bundle, Override: false} }   // ExecutionPayloadBodyV1 is used in the response to GetPayloadBodiesByHashV1 and GetPayloadBodiesByRangeV1
diff --git ethereum/go-ethereum/beacon/engine/errors.go taikoxyz/taiko-geth/beacon/engine/errors.go index 769001b9e3d760a3cda772e9e280cd9b4505fa35..62773a0ea9f60a1e87e14746628472784d6eda65 100644 --- ethereum/go-ethereum/beacon/engine/errors.go +++ taikoxyz/taiko-geth/beacon/engine/errors.go @@ -80,6 +80,7 @@ InvalidForkChoiceState = &EngineAPIError{code: -38002, msg: "Invalid forkchoice state"} InvalidPayloadAttributes = &EngineAPIError{code: -38003, msg: "Invalid payload attributes"} TooLargeRequest = &EngineAPIError{code: -38004, msg: "Too large request"} InvalidParams = &EngineAPIError{code: -32602, msg: "Invalid parameters"} + UnsupportedFork = &EngineAPIError{code: -38005, msg: "Unsupported fork"}   STATUS_INVALID = ForkChoiceResponse{PayloadStatus: PayloadStatusV1{Status: INVALID}, PayloadID: nil} STATUS_SYNCING = ForkChoiceResponse{PayloadStatus: PayloadStatusV1{Status: SYNCING}, PayloadID: nil}

This shows modifications to cmd files.

These changes are for registering our RPC APIs and custom genesis settings.

diff --git ethereum/go-ethereum/cmd/clef/main.go taikoxyz/taiko-geth/cmd/clef/main.go index a8b0bf816a3871da63ad42b62496662f48196b3d..06a8cd7ab7b0f87f82375f024b878e33aee49e2d 100644 --- ethereum/go-ethereum/cmd/clef/main.go +++ taikoxyz/taiko-geth/cmd/clef/main.go @@ -1206,7 +1206,7 @@ Address: common.HexToAddress("0xcowbeef000000cowbeef00000000000000000c0w"), URL: accounts.URL{Path: ".. ignored .."}, }, { - Address: common.HexToAddress("0xffffffffffffffffffffffffffffffffffffffff"), + Address: common.MaxAddress, }, }}) }
diff --git ethereum/go-ethereum/cmd/evm/blockrunner.go taikoxyz/taiko-geth/cmd/evm/blockrunner.go index ffd3165f55694c9b709f4ea3747be5e26131ed44..42be6726b5914ee73885a3931557352e960fc96b 100644 --- ethereum/go-ethereum/cmd/evm/blockrunner.go +++ taikoxyz/taiko-geth/cmd/evm/blockrunner.go @@ -21,10 +21,11 @@ "encoding/json" "errors" "fmt" "os" + "sort"   + "github.com/ethereum/go-ethereum/core/rawdb" "github.com/ethereum/go-ethereum/core/vm" "github.com/ethereum/go-ethereum/eth/tracers/logger" - "github.com/ethereum/go-ethereum/log" "github.com/ethereum/go-ethereum/tests" "github.com/urfave/cli/v2" ) @@ -40,10 +41,7 @@ func blockTestCmd(ctx *cli.Context) error { if len(ctx.Args().First()) == 0 { return errors.New("path-to-test argument required") } - // Configure the go-ethereum logger - glogger := log.NewGlogHandler(log.StreamHandler(os.Stderr, log.TerminalFormat(false))) - glogger.Verbosity(log.Lvl(ctx.Int(VerbosityFlag.Name))) - log.Root().SetHandler(glogger) + var tracer vm.EVMLogger // Configure the EVM logger if ctx.Bool(MachineFlag.Name) { @@ -63,9 +61,16 @@ var tests map[string]tests.BlockTest if err = json.Unmarshal(src, &tests); err != nil { return err } - for i, test := range tests { - if err := test.Run(false, tracer); err != nil { - return fmt.Errorf("test %v: %w", i, err) + // run them in order + var keys []string + for key := range tests { + keys = append(keys, key) + } + sort.Strings(keys) + for _, name := range keys { + test := tests[name] + if err := test.Run(false, rawdb.HashScheme, tracer); err != nil { + return fmt.Errorf("test %v: %w", name, err) } } return nil
diff --git ethereum/go-ethereum/cmd/devp2p/discv5cmd.go taikoxyz/taiko-geth/cmd/devp2p/discv5cmd.go index c5e226f0d1fa5ee543d39475a7d41f7479d25f32..0dac94526971f9e230fb7a909a1418667a3e200b 100644 --- ethereum/go-ethereum/cmd/devp2p/discv5cmd.go +++ taikoxyz/taiko-geth/cmd/devp2p/discv5cmd.go @@ -81,7 +81,7 @@ )   func discv5Ping(ctx *cli.Context) error { n := getNodeArg(ctx) - disc := startV5(ctx) + disc, _ := startV5(ctx) defer disc.Close()   fmt.Println(disc.Ping(n)) @@ -90,7 +90,7 @@ }   func discv5Resolve(ctx *cli.Context) error { n := getNodeArg(ctx) - disc := startV5(ctx) + disc, _ := startV5(ctx) defer disc.Close()   fmt.Println(disc.Resolve(n)) @@ -102,14 +102,18 @@ if ctx.NArg() < 1 { return errors.New("need nodes file as argument") } nodesFile := ctx.Args().First() - var inputSet nodeSet + inputSet := make(nodeSet) if common.FileExist(nodesFile) { inputSet = loadNodesJSON(nodesFile) }   - disc := startV5(ctx) + disc, config := startV5(ctx) defer disc.Close() - c := newCrawler(inputSet, disc, disc.RandomNodes()) + + c, err := newCrawler(inputSet, config.Bootnodes, disc, disc.RandomNodes()) + if err != nil { + return err + } c.revalidateInterval = 10 * time.Minute output := c.run(ctx.Duration(crawlTimeoutFlag.Name), ctx.Int(crawlParallelismFlag.Name)) writeNodesJSON(nodesFile, output) @@ -127,7 +131,7 @@ return runTests(ctx, suite.AllTests()) }   func discv5Listen(ctx *cli.Context) error { - disc := startV5(ctx) + disc, _ := startV5(ctx) defer disc.Close()   fmt.Println(disc.Self()) @@ -135,12 +139,12 @@ select {} }   // startV5 starts an ephemeral discovery v5 node. -func startV5(ctx *cli.Context) *discover.UDPv5 { +func startV5(ctx *cli.Context) (*discover.UDPv5, discover.Config) { ln, config := makeDiscoveryConfig(ctx) socket := listen(ctx, ln) disc, err := discover.ListenV5(socket, ln, config) if err != nil { exit(err) } - return disc + return disc, config }
diff --git ethereum/go-ethereum/cmd/devp2p/dns_cloudflare.go taikoxyz/taiko-geth/cmd/devp2p/dns_cloudflare.go index 903d754dd74c365f8837f18dad37dbf3ce6e1ee7..a3cc69cf1925450c9df7c10415a64e1c16287a5d 100644 --- ethereum/go-ethereum/cmd/devp2p/dns_cloudflare.go +++ taikoxyz/taiko-geth/cmd/devp2p/dns_cloudflare.go @@ -114,7 +114,7 @@ } records = lrecords   log.Info(fmt.Sprintf("Retrieving existing TXT records on %s", name)) - entries, err := c.DNSRecords(context.Background(), c.zoneID, cloudflare.DNSRecord{Type: "TXT"}) + entries, _, err := c.ListDNSRecords(context.Background(), cloudflare.ZoneIdentifier(c.zoneID), cloudflare.ListDNSRecordsParams{Type: "TXT"}) if err != nil { return err } @@ -141,14 +141,25 @@ ttl := rootTTL if path != name { ttl = treeNodeTTLCloudflare // Max TTL permitted by Cloudflare } - record := cloudflare.DNSRecord{Type: "TXT", Name: path, Content: val, TTL: ttl} - _, err = c.CreateDNSRecord(context.Background(), c.zoneID, record) + record := cloudflare.CreateDNSRecordParams{Type: "TXT", Name: path, Content: val, TTL: ttl} + _, err = c.CreateDNSRecord(context.Background(), cloudflare.ZoneIdentifier(c.zoneID), record) } else if old.Content != val { // Entry already exists, only change its content. log.Info(fmt.Sprintf("Updating %s from %q to %q", path, old.Content, val)) updated++ - old.Content = val - err = c.UpdateDNSRecord(context.Background(), c.zoneID, old.ID, old) + + record := cloudflare.UpdateDNSRecordParams{ + Type: old.Type, + Name: old.Name, + Content: val, + Data: old.Data, + ID: old.ID, + Priority: old.Priority, + TTL: old.TTL, + Proxied: old.Proxied, + Tags: old.Tags, + } + _, err = c.UpdateDNSRecord(context.Background(), cloudflare.ZoneIdentifier(c.zoneID), record) } else { skipped++ log.Debug(fmt.Sprintf("Skipping %s = %q", path, val)) @@ -168,7 +179,7 @@ } // Stale entry, nuke it. log.Debug(fmt.Sprintf("Deleting %s = %q", path, entry.Content)) deleted++ - if err := c.DeleteDNSRecord(context.Background(), c.zoneID, entry.ID); err != nil { + if err := c.DeleteDNSRecord(context.Background(), cloudflare.ZoneIdentifier(c.zoneID), entry.ID); err != nil { return fmt.Errorf("failed to delete %s: %v", path, err) } }
diff --git ethereum/go-ethereum/cmd/evm/main.go taikoxyz/taiko-geth/cmd/evm/main.go index 024be62b9c5419db53e0f20c0ad333c6c252ba54..1f6500b78c6cfd73f29a2984eedc97bef0820e0d 100644 --- ethereum/go-ethereum/cmd/evm/main.go +++ taikoxyz/taiko-geth/cmd/evm/main.go @@ -23,107 +23,116 @@ "math/big" "os"   "github.com/ethereum/go-ethereum/cmd/evm/internal/t8ntool" + "github.com/ethereum/go-ethereum/internal/debug" "github.com/ethereum/go-ethereum/internal/flags" "github.com/urfave/cli/v2" )   var ( DebugFlag = &cli.BoolFlag{ - Name: "debug", - Usage: "output full trace logs", - } - MemProfileFlag = &cli.StringFlag{ - Name: "memprofile", - Usage: "creates a memory profile at the given path", - } - CPUProfileFlag = &cli.StringFlag{ - Name: "cpuprofile", - Usage: "creates a CPU profile at the given path", + Name: "debug", + Usage: "output full trace logs", + Category: flags.VMCategory, } StatDumpFlag = &cli.BoolFlag{ - Name: "statdump", - Usage: "displays stack and heap memory information", + Name: "statdump", + Usage: "displays stack and heap memory information", + Category: flags.VMCategory, } CodeFlag = &cli.StringFlag{ - Name: "code", - Usage: "EVM code", + Name: "code", + Usage: "EVM code", + Category: flags.VMCategory, } CodeFileFlag = &cli.StringFlag{ - Name: "codefile", - Usage: "File containing EVM code. If '-' is specified, code is read from stdin ", + Name: "codefile", + Usage: "File containing EVM code. If '-' is specified, code is read from stdin ", + Category: flags.VMCategory, } GasFlag = &cli.Uint64Flag{ - Name: "gas", - Usage: "gas limit for the evm", - Value: 10000000000, + Name: "gas", + Usage: "gas limit for the evm", + Value: 10000000000, + Category: flags.VMCategory, } PriceFlag = &flags.BigFlag{ - Name: "price", - Usage: "price set for the evm", - Value: new(big.Int), + Name: "price", + Usage: "price set for the evm", + Value: new(big.Int), + Category: flags.VMCategory, } ValueFlag = &flags.BigFlag{ - Name: "value", - Usage: "value set for the evm", - Value: new(big.Int), + Name: "value", + Usage: "value set for the evm", + Value: new(big.Int), + Category: flags.VMCategory, } DumpFlag = &cli.BoolFlag{ - Name: "dump", - Usage: "dumps the state after the run", + Name: "dump", + Usage: "dumps the state after the run", + Category: flags.VMCategory, } InputFlag = &cli.StringFlag{ - Name: "input", - Usage: "input for the EVM", + Name: "input", + Usage: "input for the EVM", + Category: flags.VMCategory, } InputFileFlag = &cli.StringFlag{ - Name: "inputfile", - Usage: "file containing input for the EVM", - } - VerbosityFlag = &cli.IntFlag{ - Name: "verbosity", - Usage: "sets the verbosity level", + Name: "inputfile", + Usage: "file containing input for the EVM", + Category: flags.VMCategory, } BenchFlag = &cli.BoolFlag{ - Name: "bench", - Usage: "benchmark the execution", + Name: "bench", + Usage: "benchmark the execution", + Category: flags.VMCategory, } CreateFlag = &cli.BoolFlag{ - Name: "create", - Usage: "indicates the action should be create rather than call", + Name: "create", + Usage: "indicates the action should be create rather than call", + Category: flags.VMCategory, } GenesisFlag = &cli.StringFlag{ - Name: "prestate", - Usage: "JSON file with prestate (genesis) config", + Name: "prestate", + Usage: "JSON file with prestate (genesis) config", + Category: flags.VMCategory, } MachineFlag = &cli.BoolFlag{ - Name: "json", - Usage: "output trace logs in machine readable format (json)", + Name: "json", + Usage: "output trace logs in machine readable format (json)", + Category: flags.VMCategory, } SenderFlag = &cli.StringFlag{ - Name: "sender", - Usage: "The transaction origin", + Name: "sender", + Usage: "The transaction origin", + Category: flags.VMCategory, } ReceiverFlag = &cli.StringFlag{ - Name: "receiver", - Usage: "The transaction receiver (execution context)", + Name: "receiver", + Usage: "The transaction receiver (execution context)", + Category: flags.VMCategory, } DisableMemoryFlag = &cli.BoolFlag{ - Name: "nomemory", - Value: true, - Usage: "disable memory output", + Name: "nomemory", + Value: true, + Usage: "disable memory output", + Category: flags.VMCategory, } DisableStackFlag = &cli.BoolFlag{ - Name: "nostack", - Usage: "disable stack output", + Name: "nostack", + Usage: "disable stack output", + Category: flags.VMCategory, } DisableStorageFlag = &cli.BoolFlag{ - Name: "nostorage", - Usage: "disable storage output", + Name: "nostorage", + Usage: "disable storage output", + Category: flags.VMCategory, } DisableReturnDataFlag = &cli.BoolFlag{ - Name: "noreturndata", - Value: true, - Usage: "enable return data output", + Name: "noreturndata", + Value: true, + Usage: "enable return data output", + Category: flags.VMCategory, } )   @@ -183,34 +192,38 @@ t8ntool.VerbosityFlag, }, }   +// vmFlags contains flags related to running the EVM. +var vmFlags = []cli.Flag{ + CodeFlag, + CodeFileFlag, + CreateFlag, + GasFlag, + PriceFlag, + ValueFlag, + InputFlag, + InputFileFlag, + GenesisFlag, + SenderFlag, + ReceiverFlag, +} + +// traceFlags contains flags that configure tracing output. +var traceFlags = []cli.Flag{ + BenchFlag, + DebugFlag, + DumpFlag, + MachineFlag, + StatDumpFlag, + DisableMemoryFlag, + DisableStackFlag, + DisableStorageFlag, + DisableReturnDataFlag, +} + var app = flags.NewApp("the evm command line interface")   func init() { - app.Flags = []cli.Flag{ - BenchFlag, - CreateFlag, - DebugFlag, - VerbosityFlag, - CodeFlag, - CodeFileFlag, - GasFlag, - PriceFlag, - ValueFlag, - DumpFlag, - InputFlag, - InputFileFlag, - MemProfileFlag, - CPUProfileFlag, - StatDumpFlag, - GenesisFlag, - MachineFlag, - SenderFlag, - ReceiverFlag, - DisableMemoryFlag, - DisableStackFlag, - DisableStorageFlag, - DisableReturnDataFlag, - } + app.Flags = flags.Merge(vmFlags, traceFlags, debug.Flags) app.Commands = []*cli.Command{ compileCommand, disasmCommand, @@ -220,6 +233,14 @@ stateTestCommand, stateTransitionCommand, transactionCommand, blockBuilderCommand, + } + app.Before = func(ctx *cli.Context) error { + flags.MigrateGlobalFlags(ctx) + return debug.Setup(ctx) + } + app.After = func(ctx *cli.Context) error { + debug.Exit() + return nil } }
diff --git ethereum/go-ethereum/cmd/devp2p/crawl.go taikoxyz/taiko-geth/cmd/devp2p/crawl.go index 8c0defff6d544e022ad168b5d9dad4b960871f13..4288a5feb897ba725fac3d1789f4ce2b1c92d319 100644 --- ethereum/go-ethereum/cmd/devp2p/crawl.go +++ taikoxyz/taiko-geth/cmd/devp2p/crawl.go @@ -17,6 +17,7 @@ package main   import ( + "errors" "sync" "sync/atomic" "time" @@ -51,7 +52,14 @@ type resolver interface { RequestENR(*enode.Node) (*enode.Node, error) }   -func newCrawler(input nodeSet, disc resolver, iters ...enode.Iterator) *crawler { +func newCrawler(input nodeSet, bootnodes []*enode.Node, disc resolver, iters ...enode.Iterator) (*crawler, error) { + if len(input) == 0 { + input.add(bootnodes...) + } + if len(input) == 0 { + return nil, errors.New("no input nodes to start crawling") + } + c := &crawler{ input: input, output: make(nodeSet, len(input)), @@ -67,7 +75,7 @@ // will be dropped from output during the run. for id, n := range input { c.output[id] = n } - return c + return c, nil }   func (c *crawler) run(timeout time.Duration, nthreads int) nodeSet {
diff --git ethereum/go-ethereum/cmd/devp2p/discv4cmd.go taikoxyz/taiko-geth/cmd/devp2p/discv4cmd.go index 0117c7eb827f4c825555785bf08529ef3d8156cb..37b139dea2927aca353d9cc39b71f1cedfc39e7c 100644 --- ethereum/go-ethereum/cmd/devp2p/discv4cmd.go +++ taikoxyz/taiko-geth/cmd/devp2p/discv4cmd.go @@ -143,7 +143,7 @@ }   func discv4Ping(ctx *cli.Context) error { n := getNodeArg(ctx) - disc := startV4(ctx) + disc, _ := startV4(ctx) defer disc.Close()   start := time.Now() @@ -156,7 +156,7 @@ }   func discv4RequestRecord(ctx *cli.Context) error { n := getNodeArg(ctx) - disc := startV4(ctx) + disc, _ := startV4(ctx) defer disc.Close()   respN, err := disc.RequestENR(n) @@ -169,7 +169,7 @@ }   func discv4Resolve(ctx *cli.Context) error { n := getNodeArg(ctx) - disc := startV4(ctx) + disc, _ := startV4(ctx) defer disc.Close()   fmt.Println(disc.Resolve(n).String()) @@ -196,10 +196,13 @@ } nodeargs = append(nodeargs, n) }   - // Run the crawler. - disc := startV4(ctx) + disc, config := startV4(ctx) defer disc.Close() - c := newCrawler(inputSet, disc, enode.IterNodes(nodeargs)) + + c, err := newCrawler(inputSet, config.Bootnodes, disc, enode.IterNodes(nodeargs)) + if err != nil { + return err + } c.revalidateInterval = 0 output := c.run(0, 1) writeNodesJSON(nodesFile, output) @@ -211,14 +214,18 @@ if ctx.NArg() < 1 { return errors.New("need nodes file as argument") } nodesFile := ctx.Args().First() - var inputSet nodeSet + inputSet := make(nodeSet) if common.FileExist(nodesFile) { inputSet = loadNodesJSON(nodesFile) }   - disc := startV4(ctx) + disc, config := startV4(ctx) defer disc.Close() - c := newCrawler(inputSet, disc, disc.RandomNodes()) + + c, err := newCrawler(inputSet, config.Bootnodes, disc, disc.RandomNodes()) + if err != nil { + return err + } c.revalidateInterval = 10 * time.Minute output := c.run(ctx.Duration(crawlTimeoutFlag.Name), ctx.Int(crawlParallelismFlag.Name)) writeNodesJSON(nodesFile, output) @@ -238,14 +245,14 @@ return runTests(ctx, v4test.AllTests) }   // startV4 starts an ephemeral discovery V4 node. -func startV4(ctx *cli.Context) *discover.UDPv4 { +func startV4(ctx *cli.Context) (*discover.UDPv4, discover.Config) { ln, config := makeDiscoveryConfig(ctx) socket := listen(ctx, ln) disc, err := discover.ListenV4(socket, ln, config) if err != nil { exit(err) } - return disc + return disc, config }   func makeDiscoveryConfig(ctx *cli.Context) (*enode.LocalNode, discover.Config) {
diff --git ethereum/go-ethereum/cmd/geth/chaincmd.go taikoxyz/taiko-geth/cmd/geth/chaincmd.go index 41591ac138a815e2a747c140ddfd2e9e087c4790..a6bb2c2d2c411c3e3f4440a5af2ab545f4cec891 100644 --- ethereum/go-ethereum/cmd/geth/chaincmd.go +++ taikoxyz/taiko-geth/cmd/geth/chaincmd.go @@ -39,7 +39,6 @@ "github.com/ethereum/go-ethereum/internal/flags" "github.com/ethereum/go-ethereum/log" "github.com/ethereum/go-ethereum/metrics" "github.com/ethereum/go-ethereum/node" - "github.com/ethereum/go-ethereum/trie" "github.com/urfave/cli/v2" )   @@ -49,7 +48,9 @@ Action: initGenesis, Name: "init", Usage: "Bootstrap and initialize a new genesis block", ArgsUsage: "<genesisPath>", - Flags: flags.Merge([]cli.Flag{utils.CachePreimagesFlag}, utils.DatabasePathFlags), + Flags: flags.Merge([]cli.Flag{ + utils.CachePreimagesFlag, + }, utils.DatabaseFlags), Description: ` The init command initializes a new genesis block and definition for the network. This is a destructive action and changes the network in which you will be @@ -94,7 +95,9 @@ utils.MetricsInfluxDBTokenFlag, utils.MetricsInfluxDBBucketFlag, utils.MetricsInfluxDBOrganizationFlag, utils.TxLookupLimitFlag, - }, utils.DatabasePathFlags), + utils.TransactionHistoryFlag, + utils.StateHistoryFlag, + }, utils.DatabaseFlags), Description: ` The import command imports blocks from an RLP-encoded form. The form can be one file with several RLP-encoded blocks, or several files can be used. @@ -110,7 +113,7 @@ ArgsUsage: "<filename> [<blockNumFirst> <blockNumLast>]", Flags: flags.Merge([]cli.Flag{ utils.CacheFlag, utils.SyncModeFlag, - }, utils.DatabasePathFlags), + }, utils.DatabaseFlags), Description: ` Requires a first argument of the file to write to. Optional second and third arguments control the first and @@ -126,7 +129,7 @@ ArgsUsage: "<datafile>", Flags: flags.Merge([]cli.Flag{ utils.CacheFlag, utils.SyncModeFlag, - }, utils.DatabasePathFlags), + }, utils.DatabaseFlags), Description: ` The import-preimages command imports hash preimages from an RLP encoded stream. It's deprecated, please use "geth db import" instead. @@ -140,7 +143,7 @@ ArgsUsage: "<dumpfile>", Flags: flags.Merge([]cli.Flag{ utils.CacheFlag, utils.SyncModeFlag, - }, utils.DatabasePathFlags), + }, utils.DatabaseFlags), Description: ` The export-preimages command exports hash preimages to an RLP encoded stream. It's deprecated, please use "geth db export" instead. @@ -159,7 +162,7 @@ utils.ExcludeStorageFlag, utils.IncludeIncompletesFlag, utils.StartKeyFlag, utils.DumpLimitFlag, - }, utils.DatabasePathFlags), + }, utils.DatabaseFlags), Description: ` This command dumps out the state for a given block (or latest, if none provided). `, @@ -195,14 +198,15 @@ chaindb, err := stack.OpenDatabaseWithFreezer(name, 0, 0, ctx.String(utils.AncientFlag.Name), "", false) if err != nil { utils.Fatalf("Failed to open database: %v", err) } - triedb := trie.NewDatabaseWithConfig(chaindb, &trie.Config{ - Preimages: ctx.Bool(utils.CachePreimagesFlag.Name), - }) + defer chaindb.Close() + + triedb := utils.MakeTrieDatabase(ctx, chaindb, ctx.Bool(utils.CachePreimagesFlag.Name), false) + defer triedb.Close() + _, hash, err := core.SetupGenesisBlock(chaindb, triedb, genesis) if err != nil { utils.Fatalf("Failed to write genesis block: %v", err) } - chaindb.Close() log.Info("Successfully wrote genesis state", "database", name, "hash", hash) } return nil @@ -241,7 +245,7 @@ } if ctx.IsSet(utils.DataDirFlag.Name) { utils.Fatalf("no existing datadir at %s", stack.Config().DataDir) } - utils.Fatalf("no network preset provided. no exisiting genesis in the default datadir") + utils.Fatalf("no network preset provided, no existing genesis in the default datadir") return nil }   @@ -332,7 +336,8 @@ stack, _ := makeConfigNode(ctx) defer stack.Close()   - chain, _ := utils.MakeChain(ctx, stack, true) + chain, db := utils.MakeChain(ctx, stack, true) + defer db.Close() start := time.Now()   var err error @@ -372,6 +377,7 @@ stack, _ := makeConfigNode(ctx) defer stack.Close()   db := utils.MakeChainDatabase(ctx, stack, false) + defer db.Close() start := time.Now()   if err := utils.ImportPreimages(db, ctx.Args().First()); err != nil { @@ -390,6 +396,7 @@ stack, _ := makeConfigNode(ctx) defer stack.Close()   db := utils.MakeChainDatabase(ctx, stack, true) + defer db.Close() start := time.Now()   if err := utils.ExportPreimages(db, ctx.Args().First()); err != nil { @@ -401,6 +408,8 @@ }   func parseDumpConfig(ctx *cli.Context, stack *node.Node) (*state.DumpConfig, ethdb.Database, common.Hash, error) { db := utils.MakeChainDatabase(ctx, stack, true) + defer db.Close() + var header *types.Header if ctx.NArg() > 1 { return nil, nil, common.Hash{}, fmt.Errorf("expected 1 argument (number or hash), got %d", ctx.NArg()) @@ -465,10 +474,10 @@ conf, db, root, err := parseDumpConfig(ctx, stack) if err != nil { return err } - config := &trie.Config{ - Preimages: true, // always enable preimage lookup - } - state, err := state.New(root, state.NewDatabaseWithConfig(db, config), nil) + triedb := utils.MakeTrieDatabase(ctx, db, true, true) // always enable preimage lookup + defer triedb.Close() + + state, err := state.New(root, state.NewDatabaseWithNodeDB(db, triedb), nil) if err != nil { return err }
diff --git ethereum/go-ethereum/cmd/geth/verkle.go taikoxyz/taiko-geth/cmd/geth/verkle.go index 9ba2b4167164c99cccf02760b721ebd95665644c..aa79889e8c18ee1f9d9d1d4f3416280a4d30ce46 100644 --- ethereum/go-ethereum/cmd/geth/verkle.go +++ taikoxyz/taiko-geth/cmd/geth/verkle.go @@ -45,7 +45,7 @@ Name: "verify", Usage: "verify the conversion of a MPT into a verkle tree", ArgsUsage: "<root>", Action: verifyVerkle, - Flags: flags.Merge(utils.NetworkFlags, utils.DatabasePathFlags), + Flags: flags.Merge(utils.NetworkFlags, utils.DatabaseFlags), Description: ` geth verkle verify <state-root> This command takes a root commitment and attempts to rebuild the tree. @@ -56,7 +56,7 @@ Name: "dump", Usage: "Dump a verkle tree to a DOT file", ArgsUsage: "<root> <key1> [<key 2> ...]", Action: expandVerkle, - Flags: flags.Merge(utils.NetworkFlags, utils.DatabasePathFlags), + Flags: flags.Merge(utils.NetworkFlags, utils.DatabaseFlags), Description: ` geth verkle dump <state-root> <key 1> [<key 2> ...] This command will produce a dot file representing the tree, rooted at <root>. @@ -115,6 +115,7 @@ stack, _ := makeConfigNode(ctx) defer stack.Close()   chaindb := utils.MakeChainDatabase(ctx, stack, true) + defer chaindb.Close() headBlock := rawdb.ReadHeadBlock(chaindb) if headBlock == nil { log.Error("Failed to load head block") @@ -163,6 +164,7 @@ stack, _ := makeConfigNode(ctx) defer stack.Close()   chaindb := utils.MakeChainDatabase(ctx, stack, true) + defer chaindb.Close() var ( rootC common.Hash keylist [][]byte
diff --git ethereum/go-ethereum/cmd/evm/runner.go taikoxyz/taiko-geth/cmd/evm/runner.go index ed7989e872999d98535bf10e017a9563be8a154c..45fc9853519f6d9531a031f9610d79110c1ca910 100644 --- ethereum/go-ethereum/cmd/evm/runner.go +++ taikoxyz/taiko-geth/cmd/evm/runner.go @@ -24,7 +24,6 @@ "io" "math/big" "os" goruntime "runtime" - "runtime/pprof" "testing" "time"   @@ -34,14 +33,13 @@ "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/core" "github.com/ethereum/go-ethereum/core/rawdb" "github.com/ethereum/go-ethereum/core/state" - "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/core/vm" "github.com/ethereum/go-ethereum/core/vm/runtime" "github.com/ethereum/go-ethereum/eth/tracers/logger" "github.com/ethereum/go-ethereum/internal/flags" - "github.com/ethereum/go-ethereum/log" "github.com/ethereum/go-ethereum/params" "github.com/ethereum/go-ethereum/trie" + "github.com/ethereum/go-ethereum/trie/triedb/hashdb" "github.com/urfave/cli/v2" )   @@ -51,6 +49,7 @@ Name: "run", Usage: "run arbitrary evm binary", ArgsUsage: "<code>", Description: `The run command runs arbitrary EVM code.`, + Flags: flags.Merge(vmFlags, traceFlags), }   // readGenesis will read the given JSON format genesis file and return @@ -108,9 +107,6 @@ return output, gasLeft, stats, err }   func runCmd(ctx *cli.Context) error { - glogger := log.NewGlogHandler(log.StreamHandler(os.Stderr, log.TerminalFormat(false))) - glogger.Verbosity(log.Lvl(ctx.Int(VerbosityFlag.Name))) - log.Root().SetHandler(glogger) logconfig := &logger.Config{ EnableMemory: !ctx.Bool(DisableMemoryFlag.Name), DisableStack: ctx.Bool(DisableStackFlag.Name), @@ -120,15 +116,15 @@ Debug: ctx.Bool(DebugFlag.Name), }   var ( - tracer vm.EVMLogger - debugLogger *logger.StructLogger - statedb *state.StateDB - chainConfig *params.ChainConfig - sender = common.BytesToAddress([]byte("sender")) - receiver = common.BytesToAddress([]byte("receiver")) - genesisConfig *core.Genesis - preimages = ctx.Bool(DumpFlag.Name) - blobHashes []common.Hash // TODO (MariusVanDerWijden) implement blob hashes in state tests + tracer vm.EVMLogger + debugLogger *logger.StructLogger + statedb *state.StateDB + chainConfig *params.ChainConfig + sender = common.BytesToAddress([]byte("sender")) + receiver = common.BytesToAddress([]byte("receiver")) + preimages = ctx.Bool(DumpFlag.Name) + blobHashes []common.Hash // TODO (MariusVanDerWijden) implement blob hashes in state tests + blobBaseFee = new(big.Int) // TODO (MariusVanDerWijden) implement blob fee in state tests ) if ctx.Bool(MachineFlag.Name) { tracer = logger.NewJSONLogger(logconfig, os.Stdout) @@ -138,19 +134,30 @@ tracer = debugLogger } else { debugLogger = logger.NewStructLogger(logconfig) } + + initialGas := ctx.Uint64(GasFlag.Name) + genesisConfig := new(core.Genesis) + genesisConfig.GasLimit = initialGas if ctx.String(GenesisFlag.Name) != "" { - gen := readGenesis(ctx.String(GenesisFlag.Name)) - genesisConfig = gen - db := rawdb.NewMemoryDatabase() - genesis := gen.MustCommit(db) - sdb := state.NewDatabaseWithConfig(db, &trie.Config{Preimages: preimages}) - statedb, _ = state.New(genesis.Root(), sdb, nil) - chainConfig = gen.Config + genesisConfig = readGenesis(ctx.String(GenesisFlag.Name)) + if genesisConfig.GasLimit != 0 { + initialGas = genesisConfig.GasLimit + } } else { - sdb := state.NewDatabaseWithConfig(rawdb.NewMemoryDatabase(), &trie.Config{Preimages: preimages}) - statedb, _ = state.New(types.EmptyRootHash, sdb, nil) - genesisConfig = new(core.Genesis) + genesisConfig.Config = params.AllEthashProtocolChanges } + + db := rawdb.NewMemoryDatabase() + triedb := trie.NewDatabase(db, &trie.Config{ + Preimages: preimages, + HashDB: hashdb.Defaults, + }) + defer triedb.Close() + genesis := genesisConfig.MustCommit(db, triedb) + sdb := state.NewDatabaseWithNodeDB(db, triedb) + statedb, _ = state.New(genesis.Root(), sdb, nil) + chainConfig = genesisConfig.Config + if ctx.String(SenderFlag.Name) != "" { sender = common.HexToAddress(ctx.String(SenderFlag.Name)) } @@ -204,10 +211,6 @@ return err } code = common.Hex2Bytes(bin) } - initialGas := ctx.Uint64(GasFlag.Name) - if genesisConfig.GasLimit != 0 { - initialGas = genesisConfig.GasLimit - } runtimeConfig := runtime.Config{ Origin: sender, State: statedb, @@ -219,24 +222,12 @@ Time: genesisConfig.Timestamp, Coinbase: genesisConfig.Coinbase, BlockNumber: new(big.Int).SetUint64(genesisConfig.Number), BlobHashes: blobHashes, + BlobBaseFee: blobBaseFee, EVMConfig: vm.Config{ Tracer: tracer, }, }   - if cpuProfilePath := ctx.String(CPUProfileFlag.Name); cpuProfilePath != "" { - f, err := os.Create(cpuProfilePath) - if err != nil { - fmt.Println("could not create CPU profile: ", err) - os.Exit(1) - } - if err := pprof.StartCPUProfile(f); err != nil { - fmt.Println("could not start CPU profile: ", err) - os.Exit(1) - } - defer pprof.StopCPUProfile() - } - if chainConfig != nil { runtimeConfig.ChainConfig = chainConfig } else { @@ -282,19 +273,6 @@ if ctx.Bool(DumpFlag.Name) { statedb.Commit(genesisConfig.Number, true) fmt.Println(string(statedb.Dump(nil))) - } - - if memProfilePath := ctx.String(MemProfileFlag.Name); memProfilePath != "" { - f, err := os.Create(memProfilePath) - if err != nil { - fmt.Println("could not create memory profile: ", err) - os.Exit(1) - } - if err := pprof.WriteHeapProfile(f); err != nil { - fmt.Println("could not write memory profile: ", err) - os.Exit(1) - } - f.Close() }   if ctx.Bool(DebugFlag.Name) {
diff --git ethereum/go-ethereum/cmd/evm/t8n_test.go taikoxyz/taiko-geth/cmd/evm/t8n_test.go index d7a4db739c9c6bb3f57f38b7a80ea8ed7f7f56ad..ad09a6b4d61feb158852a4d280e2d8c3a178350f 100644 --- ethereum/go-ethereum/cmd/evm/t8n_test.go +++ taikoxyz/taiko-geth/cmd/evm/t8n_test.go @@ -267,6 +267,14 @@ }, output: t8nOutput{alloc: true, result: true}, expOut: "exp.json", }, + { // More cancun tests + base: "./testdata/29", + input: t8nInput{ + "alloc.json", "txs.json", "env.json", "Cancun", "", + }, + output: t8nOutput{alloc: true, result: true}, + expOut: "exp.json", + }, } { args := []string{"t8n"} args = append(args, tc.output.get()...)
diff --git ethereum/go-ethereum/cmd/geth/main.go taikoxyz/taiko-geth/cmd/geth/main.go index 568aec4b8b7a8204ea0e49be3b123b51f39b7d66..fa6221f52808361d0b8d6885c2a27aa12f5bef11 100644 --- ethereum/go-ethereum/cmd/geth/main.go +++ taikoxyz/taiko-geth/cmd/geth/main.go @@ -88,6 +88,8 @@ utils.ExitWhenSyncedFlag, utils.GCModeFlag, utils.SnapshotFlag, utils.TxLookupLimitFlag, + utils.TransactionHistoryFlag, + utils.StateHistoryFlag, utils.LightServeFlag, utils.LightIngressFlag, utils.LightEgressFlag, @@ -142,7 +144,7 @@ utils.GpoPercentileFlag, utils.GpoMaxGasPriceFlag, utils.GpoIgnoreGasPriceFlag, configFileFlag, - }, utils.NetworkFlags, utils.DatabasePathFlags) + }, utils.NetworkFlags, utils.DatabaseFlags)   rpcFlags = []cli.Flag{ utils.HTTPEnabledFlag, @@ -241,11 +243,19 @@ consoleFlags, debug.Flags, metricsFlags, ) + // CHANGE(taiko): append Taiko flags into the original GETH flags + app.Flags = append(app.Flags, &utils.TaikoFlag) + + flags.AutoEnvVars(app.Flags, "GETH")   app.Before = func(ctx *cli.Context) error { maxprocs.Set() // Automatically set GOMAXPROCS to match Linux container CPU quota. flags.MigrateGlobalFlags(ctx) - return debug.Setup(ctx) + if err := debug.Setup(ctx); err != nil { + return err + } + flags.CheckEnvVars(ctx, app.Flags, "GETH") + return nil } app.After = func(ctx *cli.Context) error { debug.Exit() @@ -272,6 +282,9 @@ case ctx.IsSet(utils.SepoliaFlag.Name): log.Info("Starting Geth on Sepolia testnet...")   + case ctx.IsSet(utils.HoleskyFlag.Name): + log.Info("Starting Geth on Holesky testnet...") + case ctx.IsSet(utils.DeveloperFlag.Name): log.Info("Starting Geth in ephemeral dev mode...") log.Warn(`You are running Geth in --dev mode. Please note the following: @@ -296,7 +309,8 @@ } // If we're a full node on mainnet without --cache specified, bump default cache allowance if ctx.String(utils.SyncModeFlag.Name) != "light" && !ctx.IsSet(utils.CacheFlag.Name) && !ctx.IsSet(utils.NetworkIdFlag.Name) { // Make sure we're not on any supported preconfigured testnet either - if !ctx.IsSet(utils.SepoliaFlag.Name) && + if !ctx.IsSet(utils.HoleskyFlag.Name) && + !ctx.IsSet(utils.SepoliaFlag.Name) && !ctx.IsSet(utils.GoerliFlag.Name) && !ctx.IsSet(utils.DeveloperFlag.Name) { // Nope, we're really on mainnet. Bump that cache up!
diff --git ethereum/go-ethereum/cmd/utils/flags_legacy.go taikoxyz/taiko-geth/cmd/utils/flags_legacy.go index cf51b519361a4c6f038ebdab968e9ea530ae046d..6669ff176fdd596535e33451e3d5f1937905d2ba 100644 --- ethereum/go-ethereum/cmd/utils/flags_legacy.go +++ taikoxyz/taiko-geth/cmd/utils/flags_legacy.go @@ -19,6 +19,7 @@ import ( "fmt"   + "github.com/ethereum/go-ethereum/eth/ethconfig" "github.com/ethereum/go-ethereum/internal/flags" "github.com/urfave/cli/v2" ) @@ -37,6 +38,7 @@ LegacyWhitelistFlag, CacheTrieJournalFlag, CacheTrieRejournalFlag, LegacyDiscoveryV5Flag, + TxLookupLimitFlag, }   var ( @@ -66,6 +68,13 @@ } LegacyDiscoveryV5Flag = &cli.BoolFlag{ Name: "v5disc", Usage: "Enables the experimental RLPx V5 (Topic Discovery) mechanism (deprecated, use --discv5 instead)", + Category: flags.DeprecatedCategory, + } + // Deprecated August 2023 + TxLookupLimitFlag = &cli.Uint64Flag{ + Name: "txlookuplimit", + Usage: "Number of recent blocks to maintain transactions index for (default = about one year, 0 = entire chain) (deprecated, use history.transactions instead)", + Value: ethconfig.Defaults.TransactionHistory, Category: flags.DeprecatedCategory, } )
diff --git ethereum/go-ethereum/cmd/geth/snapshot.go taikoxyz/taiko-geth/cmd/geth/snapshot.go index fafc8276047d6bb82d35fc23fa6d730cf1d01e45..64134825116aa491defbd25b616d9d0b67f00c60 100644 --- ethereum/go-ethereum/cmd/geth/snapshot.go +++ taikoxyz/taiko-geth/cmd/geth/snapshot.go @@ -51,7 +51,7 @@ ArgsUsage: "<root>", Action: pruneState, Flags: flags.Merge([]cli.Flag{ utils.BloomFilterSizeFlag, - }, utils.NetworkFlags, utils.DatabasePathFlags), + }, utils.NetworkFlags, utils.DatabaseFlags), Description: ` geth snapshot prune-state <state-root> will prune historical state data with the help of the state snapshot. @@ -61,10 +61,7 @@ two version states are available: genesis and the specific one.   The default pruning target is the HEAD-127 state.   -WARNING: It's necessary to delete the trie clean cache after the pruning. -If you specify another directory for the trie clean cache via "--cache.trie.journal" -during the use of Geth, please also specify it here for correct deletion. Otherwise -the trie clean cache with default directory will be deleted. +WARNING: it's only supported in hash mode(--state.scheme=hash)". `, }, { @@ -72,7 +69,7 @@ Name: "verify-state", Usage: "Recalculate state hash based on the snapshot for verification", ArgsUsage: "<root>", Action: verifyState, - Flags: flags.Merge(utils.NetworkFlags, utils.DatabasePathFlags), + Flags: flags.Merge(utils.NetworkFlags, utils.DatabaseFlags), Description: ` geth snapshot verify-state <state-root> will traverse the whole accounts and storages set based on the specified @@ -85,7 +82,7 @@ Name: "check-dangling-storage", Usage: "Check that there is no 'dangling' snap storage", ArgsUsage: "<root>", Action: checkDanglingStorage, - Flags: flags.Merge(utils.NetworkFlags, utils.DatabasePathFlags), + Flags: flags.Merge(utils.NetworkFlags, utils.DatabaseFlags), Description: ` geth snapshot check-dangling-storage <state-root> traverses the snap storage data, and verifies that all snapshot storage data has a corresponding account. @@ -96,7 +93,7 @@ Name: "inspect-account", Usage: "Check all snapshot layers for the a specific account", ArgsUsage: "<address | hash>", Action: checkAccount, - Flags: flags.Merge(utils.NetworkFlags, utils.DatabasePathFlags), + Flags: flags.Merge(utils.NetworkFlags, utils.DatabaseFlags), Description: ` geth snapshot inspect-account <address | hash> checks all snapshot layers and prints out information about the specified address. @@ -107,7 +104,7 @@ Name: "traverse-state", Usage: "Traverse the state with given root hash and perform quick verification", ArgsUsage: "<root>", Action: traverseState, - Flags: flags.Merge(utils.NetworkFlags, utils.DatabasePathFlags), + Flags: flags.Merge(utils.NetworkFlags, utils.DatabaseFlags), Description: ` geth snapshot traverse-state <state-root> will traverse the whole state from the given state root and will abort if any @@ -122,7 +119,7 @@ Name: "traverse-rawstate", Usage: "Traverse the state with given root hash and perform detailed verification", ArgsUsage: "<root>", Action: traverseRawState, - Flags: flags.Merge(utils.NetworkFlags, utils.DatabasePathFlags), + Flags: flags.Merge(utils.NetworkFlags, utils.DatabaseFlags), Description: ` geth snapshot traverse-rawstate <state-root> will traverse the whole state from the given root and will abort if any referenced @@ -143,7 +140,7 @@ utils.ExcludeCodeFlag, utils.ExcludeStorageFlag, utils.StartKeyFlag, utils.DumpLimitFlag, - }, utils.NetworkFlags, utils.DatabasePathFlags), + }, utils.NetworkFlags, utils.DatabaseFlags), Description: ` This command is semantically equivalent to 'geth dump', but uses the snapshots as the backend data source, making this command a lot faster. @@ -165,6 +162,9 @@ chaindb := utils.MakeChainDatabase(ctx, stack, false) defer chaindb.Close()   + if rawdb.ReadStateScheme(chaindb) != rawdb.HashScheme { + log.Crit("Offline pruning is not required for path scheme") + } prunerconfig := pruner.Config{ Datadir: stack.ResolvePath(""), BloomSize: ctx.Uint64(utils.BloomFilterSizeFlag.Name), @@ -205,13 +205,16 @@ if headBlock == nil { log.Error("Failed to load head block") return errors.New("no head block") } - snapconfig := snapshot.Config{ + triedb := utils.MakeTrieDatabase(ctx, chaindb, false, true) + defer triedb.Close() + + snapConfig := snapshot.Config{ CacheSize: 256, Recovery: false, NoBuild: true, AsyncBuild: false, } - snaptree, err := snapshot.New(snapconfig, chaindb, trie.NewDatabase(chaindb), headBlock.Root()) + snaptree, err := snapshot.New(snapConfig, chaindb, triedb, headBlock.Root()) if err != nil { log.Error("Failed to open snapshot tree", "err", err) return err @@ -242,7 +245,9 @@ func checkDanglingStorage(ctx *cli.Context) error { stack, _ := makeConfigNode(ctx) defer stack.Close()   - return snapshot.CheckDanglingStorage(utils.MakeChainDatabase(ctx, stack, true)) + db := utils.MakeChainDatabase(ctx, stack, true) + defer db.Close() + return snapshot.CheckDanglingStorage(db) }   // traverseState is a helper function used for pruning verification. @@ -253,6 +258,11 @@ stack, _ := makeConfigNode(ctx) defer stack.Close()   chaindb := utils.MakeChainDatabase(ctx, stack, true) + defer chaindb.Close() + + triedb := utils.MakeTrieDatabase(ctx, chaindb, false, true) + defer triedb.Close() + headBlock := rawdb.ReadHeadBlock(chaindb) if headBlock == nil { log.Error("Failed to load head block") @@ -277,7 +287,6 @@ } else { root = headBlock.Root() log.Info("Start traversing the state", "root", root, "number", headBlock.NumberU64()) } - triedb := trie.NewDatabase(chaindb) t, err := trie.NewStateTrie(trie.StateTrieID(root), triedb) if err != nil { log.Error("Failed to open trie", "root", root, "err", err) @@ -318,6 +327,11 @@ } storageIter := trie.NewIterator(storageIt) for storageIter.Next() { slots += 1 + + if time.Since(lastReport) > time.Second*8 { + log.Info("Traversing state", "accounts", accounts, "slots", slots, "codes", codes, "elapsed", common.PrettyDuration(time.Since(start))) + lastReport = time.Now() + } } if storageIter.Err != nil { log.Error("Failed to traverse storage trie", "root", acc.Root, "err", storageIter.Err) @@ -353,6 +367,11 @@ stack, _ := makeConfigNode(ctx) defer stack.Close()   chaindb := utils.MakeChainDatabase(ctx, stack, true) + defer chaindb.Close() + + triedb := utils.MakeTrieDatabase(ctx, chaindb, false, true) + defer triedb.Close() + headBlock := rawdb.ReadHeadBlock(chaindb) if headBlock == nil { log.Error("Failed to load head block") @@ -377,7 +396,6 @@ } else { root = headBlock.Root() log.Info("Start traversing the state", "root", root, "number", headBlock.NumberU64()) } - triedb := trie.NewDatabase(chaindb) t, err := trie.NewStateTrie(trie.StateTrieID(root), triedb) if err != nil { log.Error("Failed to open trie", "root", root, "err", err) @@ -398,6 +416,11 @@ if err != nil { log.Error("Failed to open iterator", "root", root, "err", err) return err } + reader, err := triedb.Reader(root) + if err != nil { + log.Error("State is non-existent", "root", root) + return nil + } for accIter.Next(true) { nodes += 1 node := accIter.Hash() @@ -405,7 +428,7 @@ // Check the present for non-empty hash node(embedded node doesn't // have their own hash). if node != (common.Hash{}) { - blob := rawdb.ReadLegacyTrieNode(chaindb, node) + blob, _ := reader.Node(common.Hash{}, accIter.Path(), node) if len(blob) == 0 { log.Error("Missing trie node(account)", "hash", node) return errors.New("missing account") @@ -446,7 +469,7 @@ // Check the presence for non-empty hash node(embedded node doesn't // have their own hash). if node != (common.Hash{}) { - blob := rawdb.ReadLegacyTrieNode(chaindb, node) + blob, _ := reader.Node(common.BytesToHash(accIter.LeafKey()), storageIter.Path(), node) if len(blob) == 0 { log.Error("Missing trie node(storage)", "hash", node) return errors.New("missing storage") @@ -463,6 +486,10 @@ // Bump the counter if it's leaf node. if storageIter.Leaf() { slots += 1 } + if time.Since(lastReport) > time.Second*8 { + log.Info("Traversing state", "nodes", nodes, "accounts", accounts, "slots", slots, "codes", codes, "elapsed", common.PrettyDuration(time.Since(start))) + lastReport = time.Now() + } } if storageIter.Error() != nil { log.Error("Failed to traverse storage trie", "root", acc.Root, "err", storageIter.Error()) @@ -506,13 +533,16 @@ conf, db, root, err := parseDumpConfig(ctx, stack) if err != nil { return err } + triedb := utils.MakeTrieDatabase(ctx, db, false, true) + defer triedb.Close() + snapConfig := snapshot.Config{ CacheSize: 256, Recovery: false, NoBuild: true, AsyncBuild: false, } - snaptree, err := snapshot.New(snapConfig, db, trie.NewDatabase(db), root) + snaptree, err := snapshot.New(snapConfig, db, triedb, root) if err != nil { return err }
diff --git ethereum/go-ethereum/cmd/geth/version_check_test.go taikoxyz/taiko-geth/cmd/geth/version_check_test.go index bd4d820a79013e8d78d2a85d1d61c8bcf3819712..4458ab5c0606c1629d0917788b1d3a84bc6ca24e 100644 --- ethereum/go-ethereum/cmd/geth/version_check_test.go +++ taikoxyz/taiko-geth/cmd/geth/version_check_test.go @@ -30,17 +30,24 @@ "github.com/jedisct1/go-minisign" )   func TestVerification(t *testing.T) { - // Signatures generated with `minisign` - t.Run("minisig", func(t *testing.T) { - // For this test, the pubkey is in testdata/minisign.pub + // Signatures generated with `minisign`. Legacy format, not pre-hashed file. + t.Run("minisig-legacy", func(t *testing.T) { + // For this test, the pubkey is in testdata/vcheck/minisign.pub // (the privkey is `minisign.sec`, if we want to expand this test. Password 'test' ) pub := "RWQkliYstQBOKOdtClfgC3IypIPX6TAmoEi7beZ4gyR3wsaezvqOMWsp" testVerification(t, pub, "./testdata/vcheck/minisig-sigs/") }) + t.Run("minisig-new", func(t *testing.T) { + // For this test, the pubkey is in testdata/vcheck/minisign.pub + // (the privkey is `minisign.sec`, if we want to expand this test. Password 'test' ) + // `minisign -S -s ./minisign.sec -m data.json -x ./minisig-sigs-new/data.json.minisig` + pub := "RWQkliYstQBOKOdtClfgC3IypIPX6TAmoEi7beZ4gyR3wsaezvqOMWsp" + testVerification(t, pub, "./testdata/vcheck/minisig-sigs-new/") + }) // Signatures generated with `signify-openbsd` t.Run("signify-openbsd", func(t *testing.T) { t.Skip("This currently fails, minisign expects 4 lines of data, signify provides only 2") - // For this test, the pubkey is in testdata/signifykey.pub + // For this test, the pubkey is in testdata/vcheck/signifykey.pub // (the privkey is `signifykey.sec`, if we want to expand this test. Password 'test' ) pub := "RWSKLNhZb0KdATtRT7mZC/bybI3t3+Hv/O2i3ye04Dq9fnT9slpZ1a2/" testVerification(t, pub, "./testdata/vcheck/signify-sigs/") @@ -57,6 +64,9 @@ // Signatures, with and without comments, both trusted and untrusted files, err := os.ReadDir(sigdir) if err != nil { t.Fatal(err) + } + if len(files) == 0 { + t.Fatal("Missing tests") } for _, f := range files { sig, err := os.ReadFile(filepath.Join(sigdir, f.Name()))
diff --git ethereum/go-ethereum/cmd/geth/dbcmd.go taikoxyz/taiko-geth/cmd/geth/dbcmd.go index aa7939851df1c2348b2701832ae36b8ea50f0528..6f802716c5e8740164906af8e93d884dde6f7027 100644 --- ethereum/go-ethereum/cmd/geth/dbcmd.go +++ taikoxyz/taiko-geth/cmd/geth/dbcmd.go @@ -48,7 +48,7 @@ Action: removeDB, Name: "removedb", Usage: "Remove blockchain and state databases", ArgsUsage: "", - Flags: utils.DatabasePathFlags, + Flags: utils.DatabaseFlags, Description: ` Remove blockchain and state databases`, } @@ -77,7 +77,7 @@ Name: "inspect", ArgsUsage: "<prefix> <start>", Flags: flags.Merge([]cli.Flag{ utils.SyncModeFlag, - }, utils.NetworkFlags, utils.DatabasePathFlags), + }, utils.NetworkFlags, utils.DatabaseFlags), Usage: "Inspect the storage size for each type of data in the database", Description: `This commands iterates the entire database. If the optional 'prefix' and 'start' arguments are provided, then the iteration is limited to the given subset of data.`, } @@ -85,7 +85,7 @@ dbCheckStateContentCmd = &cli.Command{ Action: checkStateContent, Name: "check-state-content", ArgsUsage: "<start (optional)>", - Flags: flags.Merge(utils.NetworkFlags, utils.DatabasePathFlags), + Flags: flags.Merge(utils.NetworkFlags, utils.DatabaseFlags), Usage: "Verify that state data is cryptographically correct", Description: `This command iterates the entire database for 32-byte keys, looking for rlp-encoded trie nodes. For each trie node encountered, it checks that the key corresponds to the keccak256(value). If this is not true, this indicates @@ -97,7 +97,7 @@ Name: "stats", Usage: "Print leveldb statistics", Flags: flags.Merge([]cli.Flag{ utils.SyncModeFlag, - }, utils.NetworkFlags, utils.DatabasePathFlags), + }, utils.NetworkFlags, utils.DatabaseFlags), } dbCompactCmd = &cli.Command{ Action: dbCompact, @@ -107,7 +107,7 @@ Flags: flags.Merge([]cli.Flag{ utils.SyncModeFlag, utils.CacheFlag, utils.CacheDatabaseFlag, - }, utils.NetworkFlags, utils.DatabasePathFlags), + }, utils.NetworkFlags, utils.DatabaseFlags), Description: `This command performs a database compaction. WARNING: This operation may take a very long time to finish, and may cause database corruption if it is aborted during execution'!`, @@ -119,7 +119,7 @@ Usage: "Show the value of a database key", ArgsUsage: "<hex-encoded key>", Flags: flags.Merge([]cli.Flag{ utils.SyncModeFlag, - }, utils.NetworkFlags, utils.DatabasePathFlags), + }, utils.NetworkFlags, utils.DatabaseFlags), Description: "This command looks up the specified database key from the database.", } dbDeleteCmd = &cli.Command{ @@ -129,7 +129,7 @@ Usage: "Delete a database key (WARNING: may corrupt your database)", ArgsUsage: "<hex-encoded key>", Flags: flags.Merge([]cli.Flag{ utils.SyncModeFlag, - }, utils.NetworkFlags, utils.DatabasePathFlags), + }, utils.NetworkFlags, utils.DatabaseFlags), Description: `This command deletes the specified database key from the database. WARNING: This is a low-level operation which may cause database corruption!`, } @@ -140,7 +140,7 @@ Usage: "Set the value of a database key (WARNING: may corrupt your database)", ArgsUsage: "<hex-encoded key> <hex-encoded value>", Flags: flags.Merge([]cli.Flag{ utils.SyncModeFlag, - }, utils.NetworkFlags, utils.DatabasePathFlags), + }, utils.NetworkFlags, utils.DatabaseFlags), Description: `This command sets a given database key to the given value. WARNING: This is a low-level operation which may cause database corruption!`, } @@ -151,7 +151,7 @@ Usage: "Show the storage key/values of a given storage trie", ArgsUsage: "<hex-encoded state root> <hex-encoded account hash> <hex-encoded storage trie root> <hex-encoded start (optional)> <int max elements (optional)>", Flags: flags.Merge([]cli.Flag{ utils.SyncModeFlag, - }, utils.NetworkFlags, utils.DatabasePathFlags), + }, utils.NetworkFlags, utils.DatabaseFlags), Description: "This command looks up the specified database key from the database.", } dbDumpFreezerIndex = &cli.Command{ @@ -161,7 +161,7 @@ Usage: "Dump out the index of a specific freezer table", ArgsUsage: "<freezer-type> <table-type> <start (int)> <end (int)>", Flags: flags.Merge([]cli.Flag{ utils.SyncModeFlag, - }, utils.NetworkFlags, utils.DatabasePathFlags), + }, utils.NetworkFlags, utils.DatabaseFlags), Description: "This command displays information about the freezer index.", } dbImportCmd = &cli.Command{ @@ -171,7 +171,7 @@ Usage: "Imports leveldb-data from an exported RLP dump.", ArgsUsage: "<dumpfile> <start (optional)", Flags: flags.Merge([]cli.Flag{ utils.SyncModeFlag, - }, utils.NetworkFlags, utils.DatabasePathFlags), + }, utils.NetworkFlags, utils.DatabaseFlags), Description: "The import command imports the specific chain data from an RLP encoded stream.", } dbExportCmd = &cli.Command{ @@ -181,7 +181,7 @@ Usage: "Exports the chain data into an RLP dump. If the <dumpfile> has .gz suffix, gzip compression will be used.", ArgsUsage: "<type> <dumpfile>", Flags: flags.Merge([]cli.Flag{ utils.SyncModeFlag, - }, utils.NetworkFlags, utils.DatabasePathFlags), + }, utils.NetworkFlags, utils.DatabaseFlags), Description: "Exports the specified chain data to an RLP encoded stream, optionally gzip-compressed.", } dbMetadataCmd = &cli.Command{ @@ -190,7 +190,7 @@ Name: "metadata", Usage: "Shows metadata about the chain status.", Flags: flags.Merge([]cli.Flag{ utils.SyncModeFlag, - }, utils.NetworkFlags, utils.DatabasePathFlags), + }, utils.NetworkFlags, utils.DatabaseFlags), Description: "Shows metadata about the chain status.", } ) @@ -482,6 +482,9 @@ db := utils.MakeChainDatabase(ctx, stack, true) defer db.Close()   + triedb := utils.MakeTrieDatabase(ctx, db, false, true) + defer triedb.Close() + var ( state []byte storage []byte @@ -515,7 +518,7 @@ return err } } id := trie.StorageTrieID(common.BytesToHash(state), common.BytesToHash(account), common.BytesToHash(storage)) - theTrie, err := trie.New(id, trie.NewDatabase(db)) + theTrie, err := trie.New(id, triedb) if err != nil { return err } @@ -591,6 +594,7 @@ } close(stop) }() db := utils.MakeChainDatabase(ctx, stack, false) + defer db.Close() return utils.ImportLDBData(db, fName, int64(start), stop) }   @@ -687,6 +691,7 @@ } close(stop) }() db := utils.MakeChainDatabase(ctx, stack, true) + defer db.Close() return utils.ExportChaindata(ctx.Args().Get(1), kind, exporter(db), stop) }   @@ -694,6 +699,8 @@ func showMetaData(ctx *cli.Context) error { stack, _ := makeConfigNode(ctx) defer stack.Close() db := utils.MakeChainDatabase(ctx, stack, true) + defer db.Close() + ancients, err := db.Ancients() if err != nil { fmt.Fprintf(os.Stderr, "Error accessing ancients: %v", err)
diff --git ethereum/go-ethereum/cmd/devp2p/README.md taikoxyz/taiko-geth/cmd/devp2p/README.md index 7922a6f37869fb7a3e96a9b3535a5d20a916dbfa..5ca7b497a26f67eab1f3402aa0f5ddf6dc0f9909 100644 --- ethereum/go-ethereum/cmd/devp2p/README.md +++ taikoxyz/taiko-geth/cmd/devp2p/README.md @@ -44,7 +44,7 @@ - `-limit <N>` limits the output set to N entries, taking the top N nodes by score - `-ip <CIDR>` filters nodes by IP subnet - `-min-age <duration>` filters nodes by 'first seen' time -- `-eth-network <mainnet/goerli/sepolia>` filters nodes by "eth" ENR entry +- `-eth-network <mainnet/goerli/sepolia/holesky>` filters nodes by "eth" ENR entry - `-les-server` filters nodes by LES server support - `-snap` filters nodes by snap protocol support
diff --git ethereum/go-ethereum/cmd/utils/flags.go taikoxyz/taiko-geth/cmd/utils/flags.go index e0c7a42670e1549224ce8df8fadd6ee80eefb2de..2bdbc8d06d184e0b075d6dc01847384740bfc8e3 100644 --- ethereum/go-ethereum/cmd/utils/flags.go +++ taikoxyz/taiko-geth/cmd/utils/flags.go @@ -18,7 +18,6 @@ // Package utils contains internal helper functions for go-ethereum commands. package utils   import ( - "bytes" "context" "crypto/ecdsa" "encoding/hex" @@ -39,16 +38,14 @@ "github.com/ethereum/go-ethereum/accounts" "github.com/ethereum/go-ethereum/accounts/keystore" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common/fdlimit" - "github.com/ethereum/go-ethereum/common/hexutil" "github.com/ethereum/go-ethereum/core" "github.com/ethereum/go-ethereum/core/rawdb" "github.com/ethereum/go-ethereum/core/txpool/legacypool" - "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/core/vm" "github.com/ethereum/go-ethereum/crypto" "github.com/ethereum/go-ethereum/crypto/kzg4844" "github.com/ethereum/go-ethereum/eth" - ethcatalyst "github.com/ethereum/go-ethereum/eth/catalyst" + "github.com/ethereum/go-ethereum/eth/catalyst" "github.com/ethereum/go-ethereum/eth/downloader" "github.com/ethereum/go-ethereum/eth/ethconfig" "github.com/ethereum/go-ethereum/eth/filters" @@ -72,8 +69,10 @@ "github.com/ethereum/go-ethereum/p2p/enode" "github.com/ethereum/go-ethereum/p2p/nat" "github.com/ethereum/go-ethereum/p2p/netutil" "github.com/ethereum/go-ethereum/params" - "github.com/ethereum/go-ethereum/rlp" "github.com/ethereum/go-ethereum/rpc" + "github.com/ethereum/go-ethereum/trie" + "github.com/ethereum/go-ethereum/trie/triedb/hashdb" + "github.com/ethereum/go-ethereum/trie/triedb/pathdb" pcsclite "github.com/gballet/go-libpcsclite" gopsutil "github.com/shirou/gopsutil/mem" "github.com/urfave/cli/v2" @@ -133,7 +132,7 @@ Category: flags.AccountCategory, } NetworkIdFlag = &cli.Uint64Flag{ Name: "networkid", - Usage: "Explicitly set network id (integer)(For testnets: use --goerli, --sepolia instead)", + Usage: "Explicitly set network id (integer)(For testnets: use --goerli, --sepolia, --holesky instead)", Value: ethconfig.Defaults.NetworkId, Category: flags.EthCategory, } @@ -152,7 +151,11 @@ Name: "sepolia", Usage: "Sepolia network: pre-configured proof-of-work test network", Category: flags.EthCategory, } - + HoleskyFlag = &cli.BoolFlag{ + Name: "holesky", + Usage: "Holesky network: pre-configured proof-of-stake test network", + Category: flags.EthCategory, + } // Dev mode DeveloperFlag = &cli.BoolFlag{ Name: "dev", @@ -218,30 +221,12 @@ Value: 0, }   defaultSyncMode = ethconfig.Defaults.SyncMode - SyncModeFlag = &flags.TextMarshalerFlag{ - Name: "syncmode", - Usage: `Blockchain sync mode ("snap", "full" or "light")`, - Value: &defaultSyncMode, - Category: flags.EthCategory, - } - GCModeFlag = &cli.StringFlag{ - Name: "gcmode", - Usage: `Blockchain garbage collection mode ("full", "archive")`, - Value: "full", - Category: flags.EthCategory, - } - SnapshotFlag = &cli.BoolFlag{ + SnapshotFlag = &cli.BoolFlag{ Name: "snapshot", Usage: `Enables snapshot-database mode (default = enable)`, Value: true, Category: flags.EthCategory, } - TxLookupLimitFlag = &cli.Uint64Flag{ - Name: "txlookuplimit", - Usage: "Number of recent blocks to maintain transactions index for (default = about one year, 0 = entire chain)", - Value: ethconfig.Defaults.TxLookupLimit, - Category: flags.EthCategory, - } LightKDFFlag = &cli.BoolFlag{ Name: "lightkdf", Usage: "Reduce key-derivation RAM & CPU usage at some expense of KDF strength", @@ -268,6 +253,35 @@ Name: "override.verkle", Usage: "Manually specify the Verkle fork timestamp, overriding the bundled setting", Category: flags.EthCategory, } + SyncModeFlag = &flags.TextMarshalerFlag{ + Name: "syncmode", + Usage: `Blockchain sync mode ("snap", "full" or "light")`, + Value: &defaultSyncMode, + Category: flags.StateCategory, + } + GCModeFlag = &cli.StringFlag{ + Name: "gcmode", + Usage: `Blockchain garbage collection mode, only relevant in state.scheme=hash ("full", "archive")`, + Value: "full", + Category: flags.StateCategory, + } + StateSchemeFlag = &cli.StringFlag{ + Name: "state.scheme", + Usage: "Scheme to use for storing ethereum state ('hash' or 'path')", + Category: flags.StateCategory, + } + StateHistoryFlag = &cli.Uint64Flag{ + Name: "history.state", + Usage: "Number of recent blocks to retain state history for (default = 90,000 blocks, 0 = entire chain)", + Value: ethconfig.Defaults.StateHistory, + Category: flags.StateCategory, + } + TransactionHistoryFlag = &cli.Uint64Flag{ + Name: "history.transactions", + Usage: "Number of recent blocks to maintain transactions index for (default = about one year, 0 = entire chain)", + Value: ethconfig.Defaults.TransactionHistory, + Category: flags.StateCategory, + } // Light server and client settings LightServeFlag = &cli.IntFlag{ Name: "light.serve", @@ -576,9 +590,9 @@ Category: flags.LoggingCategory, }   // MISC settings - SyncTargetFlag = &cli.PathFlag{ + SyncTargetFlag = &cli.StringFlag{ Name: "synctarget", - Usage: `File for containing the hex-encoded block-rlp as sync target(dev feature)`, + Usage: `Hash of the block to full sync to (dev testing feature)`, TakesFile: true, Category: flags.MiscCategory, } @@ -937,25 +951,22 @@ // TestnetFlags is the flag group of all built-in supported testnets. TestnetFlags = []cli.Flag{ GoerliFlag, SepoliaFlag, + HoleskyFlag, } // NetworkFlags is the flag group of all built-in supported networks. NetworkFlags = append([]cli.Flag{MainnetFlag}, TestnetFlags...)   - // DatabasePathFlags is the flag group of all database path flags. - DatabasePathFlags = []cli.Flag{ + // DatabaseFlags is the flag group of all database flags. + DatabaseFlags = []cli.Flag{ DataDirFlag, AncientFlag, RemoteDBFlag, + DBEngineFlag, + StateSchemeFlag, HttpHeaderFlag, } )   -func init() { - if rawdb.PebbleEnabled { - DatabasePathFlags = append(DatabasePathFlags, DBEngineFlag) - } -} - // MakeDataDir retrieves the currently requested data directory, terminating // if none (or the empty string) is specified. If the node is starting a testnet, // then a subdirectory of the specified datadir will be used. @@ -967,6 +978,9 @@ } if ctx.Bool(SepoliaFlag.Name) { return filepath.Join(path, "sepolia") } + if ctx.Bool(HoleskyFlag.Name) { + return filepath.Join(path, "holesky") + } return path } Fatalf("Cannot determine default data directory, please set manually (--datadir)") @@ -975,7 +989,7 @@ }   // setNodeKey creates a node key from set command line flags, either loading it // from a file or as a specified hex value. If neither flags were provided, this -// method returns nil and an emphemeral key is to be generated. +// method returns nil and an ephemeral key is to be generated. func setNodeKey(ctx *cli.Context, cfg *p2p.Config) { var ( hex = ctx.String(NodeKeyHexFlag.Name) @@ -1008,33 +1022,45 @@ }   // setBootstrapNodes creates a list of bootstrap nodes from the command line // flags, reverting to pre-configured ones if none have been specified. +// Priority order for bootnodes configuration: +// +// 1. --bootnodes flag +// 2. Config file +// 3. Network preset flags (e.g. --goerli) +// 4. default to mainnet nodes func setBootstrapNodes(ctx *cli.Context, cfg *p2p.Config) { urls := params.MainnetBootnodes - switch { - case ctx.IsSet(BootnodesFlag.Name): + if ctx.IsSet(BootnodesFlag.Name) { urls = SplitAndTrim(ctx.String(BootnodesFlag.Name)) - case ctx.Bool(SepoliaFlag.Name): - urls = params.SepoliaBootnodes - case ctx.Bool(GoerliFlag.Name): - urls = params.GoerliBootnodes + } else { + if cfg.BootstrapNodes != nil { + return // Already set by config file, don't apply defaults. + } + switch { + case ctx.Bool(HoleskyFlag.Name): + urls = params.HoleskyBootnodes + case ctx.Bool(SepoliaFlag.Name): + urls = params.SepoliaBootnodes + case ctx.Bool(GoerliFlag.Name): + urls = params.GoerliBootnodes + } } + cfg.BootstrapNodes = mustParseBootnodes(urls) +}   - // don't apply defaults if BootstrapNodes is already set - if cfg.BootstrapNodes != nil { - return - } - - cfg.BootstrapNodes = make([]*enode.Node, 0, len(urls)) +func mustParseBootnodes(urls []string) []*enode.Node { + nodes := make([]*enode.Node, 0, len(urls)) for _, url := range urls { if url != "" { node, err := enode.Parse(enode.ValidSchemes, url) if err != nil { log.Crit("Bootstrap URL invalid", "enode", url, "err", err) - continue + return nil } - cfg.BootstrapNodes = append(cfg.BootstrapNodes, node) + nodes = append(nodes, node) } } + return nodes }   // setBootstrapNodesV5 creates a list of bootstrap nodes from the command line @@ -1465,6 +1491,8 @@ case ctx.Bool(GoerliFlag.Name) && cfg.DataDir == node.DefaultDataDir(): cfg.DataDir = filepath.Join(node.DefaultDataDir(), "goerli") case ctx.Bool(SepoliaFlag.Name) && cfg.DataDir == node.DefaultDataDir(): cfg.DataDir = filepath.Join(node.DefaultDataDir(), "sepolia") + case ctx.Bool(HoleskyFlag.Name) && cfg.DataDir == node.DefaultDataDir(): + cfg.DataDir = filepath.Join(node.DefaultDataDir(), "holesky") } }   @@ -1621,16 +1649,11 @@ // SetEthConfig applies eth-related command line flags to the config. func SetEthConfig(ctx *cli.Context, stack *node.Node, cfg *ethconfig.Config) { // Avoid conflicting network flags - CheckExclusive(ctx, MainnetFlag, DeveloperFlag, GoerliFlag, SepoliaFlag) + CheckExclusive(ctx, MainnetFlag, DeveloperFlag, GoerliFlag, SepoliaFlag, HoleskyFlag) CheckExclusive(ctx, LightServeFlag, SyncModeFlag, "light") CheckExclusive(ctx, DeveloperFlag, ExternalSignerFlag) // Can't use both ephemeral unlocked and external signer - if ctx.String(GCModeFlag.Name) == "archive" && ctx.Uint64(TxLookupLimitFlag.Name) != 0 { - ctx.Set(TxLookupLimitFlag.Name, "0") - log.Warn("Disable transaction unindexing for archive node") - } - if ctx.IsSet(LightServeFlag.Name) && ctx.Uint64(TxLookupLimitFlag.Name) != 0 { - log.Warn("LES server cannot serve old transaction status and cannot connect below les/4 protocol version if transaction lookup index is limited") - } + + // Set configurations from CLI flags setEtherbase(ctx, cfg) setGPO(ctx, &cfg.GPO, ctx.String(SyncModeFlag.Name) == "light") setTxPool(ctx, &cfg.TxPool) @@ -1658,7 +1681,9 @@ log.Debug("Sanitizing Go's GC trigger", "percent", int(gogc)) godebug.SetGCPercent(int(gogc))   - if ctx.IsSet(SyncModeFlag.Name) { + if ctx.IsSet(SyncTargetFlag.Name) { + cfg.SyncMode = downloader.FullSync // dev sync target forces full sync + } else if ctx.IsSet(SyncModeFlag.Name) { cfg.SyncMode = *flags.GlobalTextMarshaler(ctx, SyncModeFlag.Name).(*downloader.SyncMode) } if ctx.IsSet(NetworkIdFlag.Name) { @@ -1687,8 +1712,30 @@ if cfg.NoPruning && !cfg.Preimages { cfg.Preimages = true log.Info("Enabling recording of key preimages since archive mode is used") } - if ctx.IsSet(TxLookupLimitFlag.Name) { - cfg.TxLookupLimit = ctx.Uint64(TxLookupLimitFlag.Name) + if ctx.IsSet(StateHistoryFlag.Name) { + cfg.StateHistory = ctx.Uint64(StateHistoryFlag.Name) + } + if ctx.IsSet(StateSchemeFlag.Name) { + cfg.StateScheme = ctx.String(StateSchemeFlag.Name) + } + // Parse transaction history flag, if user is still using legacy config + // file with 'TxLookupLimit' configured, copy the value to 'TransactionHistory'. + if cfg.TransactionHistory == ethconfig.Defaults.TransactionHistory && cfg.TxLookupLimit != ethconfig.Defaults.TxLookupLimit { + log.Warn("The config option 'TxLookupLimit' is deprecated and will be removed, please use 'TransactionHistory'") + cfg.TransactionHistory = cfg.TxLookupLimit + } + if ctx.IsSet(TransactionHistoryFlag.Name) { + cfg.TransactionHistory = ctx.Uint64(TransactionHistoryFlag.Name) + } else if ctx.IsSet(TxLookupLimitFlag.Name) { + log.Warn("The flag --txlookuplimit is deprecated and will be removed, please use --history.transactions") + cfg.TransactionHistory = ctx.Uint64(TxLookupLimitFlag.Name) + } + if ctx.String(GCModeFlag.Name) == "archive" && cfg.TransactionHistory != 0 { + cfg.TransactionHistory = 0 + log.Warn("Disabled transaction unindexing for archive node") + } + if ctx.IsSet(LightServeFlag.Name) && cfg.TransactionHistory != 0 { + log.Warn("LES server cannot serve old transaction status and cannot connect below les/4 protocol version if transaction lookup index is limited") } if ctx.IsSet(CacheFlag.Name) || ctx.IsSet(CacheTrieFlag.Name) { cfg.TrieCleanCache = ctx.Int(CacheFlag.Name) * ctx.Int(CacheTrieFlag.Name) / 100 @@ -1745,12 +1792,21 @@ } } // Override any default configs for hard coded networks. switch { + // CHANGE(taiko): when --taiko flag is set, use the Taiko genesis. + case ctx.IsSet(TaikoFlag.Name): + cfg.Genesis = core.TaikoGenesisBlock(cfg.NetworkId) case ctx.Bool(MainnetFlag.Name): if !ctx.IsSet(NetworkIdFlag.Name) { cfg.NetworkId = 1 } cfg.Genesis = core.DefaultGenesisBlock() SetDNSDiscoveryDefaults(cfg, params.MainnetGenesisHash) + case ctx.Bool(HoleskyFlag.Name): + if !ctx.IsSet(NetworkIdFlag.Name) { + cfg.NetworkId = 17000 + } + cfg.Genesis = core.DefaultHoleskyGenesisBlock() + SetDNSDiscoveryDefaults(cfg, params.HoleskyGenesisHash) case ctx.Bool(SepoliaFlag.Name): if !ctx.IsSet(NetworkIdFlag.Name) { cfg.NetworkId = 11155111 @@ -1814,15 +1870,7 @@ // Create a new developer genesis block or reuse existing one cfg.Genesis = core.DeveloperGenesisBlock(ctx.Uint64(DeveloperGasLimitFlag.Name), developer.Address) if ctx.IsSet(DataDirFlag.Name) { - // If datadir doesn't exist we need to open db in write-mode - // so leveldb can create files. - readonly := true - if !common.FileExist(stack.ResolvePath("chaindata")) { - readonly = false - } - // Check if we have an already initialized chain and fall back to - // that if so. Otherwise we need to generate a new genesis spec. - chaindb := MakeChainDatabase(ctx, stack, readonly) + chaindb := tryMakeReadOnlyDatabase(ctx, stack) if rawdb.ReadCanonicalHash(chaindb, 0) != (common.Hash{}) { cfg.Genesis = nil // fallback to db content } @@ -1917,21 +1965,9 @@ return filterSystem }   // RegisterFullSyncTester adds the full-sync tester service into node. -func RegisterFullSyncTester(stack *node.Node, eth *eth.Ethereum, path string) { - blob, err := os.ReadFile(path) - if err != nil { - Fatalf("Failed to read block file: %v", err) - } - rlpBlob, err := hexutil.Decode(string(bytes.TrimRight(blob, "\r\n"))) - if err != nil { - Fatalf("Failed to decode block blob: %v", err) - } - var block types.Block - if err := rlp.DecodeBytes(rlpBlob, &block); err != nil { - Fatalf("Failed to decode block: %v", err) - } - ethcatalyst.RegisterFullSyncTester(stack, eth, &block) - log.Info("Registered full-sync tester", "number", block.NumberU64(), "hash", block.Hash()) +func RegisterFullSyncTester(stack *node.Node, eth *eth.Ethereum, target common.Hash) { + catalyst.RegisterFullSyncTester(stack, eth, target) + log.Info("Registered full-sync tester", "hash", target) }   func SetupMetrics(ctx *cli.Context) { @@ -2040,6 +2076,18 @@ } return chainDb }   +// tryMakeReadOnlyDatabase try to open the chain database in read-only mode, +// or fallback to write mode if the database is not initialized. +func tryMakeReadOnlyDatabase(ctx *cli.Context, stack *node.Node) ethdb.Database { + // If the database doesn't exist we need to open it in write-mode to allow + // the engine to create files. + readonly := true + if rawdb.PreexistingDatabase(stack.ResolvePath("chaindata")) == "" { + readonly = false + } + return MakeChainDatabase(ctx, stack, readonly) +} + func IsNetworkPreset(ctx *cli.Context) bool { for _, flag := range NetworkFlags { bFlag, _ := flag.(*cli.BoolFlag) @@ -2061,7 +2109,7 @@ endpoint = endpoint[4:] } var opts []rpc.ClientOption if len(headers) > 0 { - var customHeaders = make(http.Header) + customHeaders := make(http.Header) for _, h := range headers { kv := strings.Split(h, ":") if len(kv) != 2 { @@ -2079,6 +2127,8 @@ var genesis *core.Genesis switch { case ctx.Bool(MainnetFlag.Name): genesis = core.DefaultGenesisBlock() + case ctx.Bool(HoleskyFlag.Name): + genesis = core.DefaultHoleskyGenesisBlock() case ctx.Bool(SepoliaFlag.Name): genesis = core.DefaultSepoliaGenesisBlock() case ctx.Bool(GoerliFlag.Name): @@ -2106,6 +2156,10 @@ } if gcmode := ctx.String(GCModeFlag.Name); gcmode != "full" && gcmode != "archive" { Fatalf("--%s must be either 'full' or 'archive'", GCModeFlag.Name) } + scheme, err := rawdb.ParseStateScheme(ctx.String(StateSchemeFlag.Name), chainDb) + if err != nil { + Fatalf("%v", err) + } cache := &core.CacheConfig{ TrieCleanLimit: ethconfig.Defaults.TrieCleanCache, TrieCleanNoPrefetch: ctx.Bool(CacheNoPrefetchFlag.Name), @@ -2114,6 +2168,8 @@ TrieDirtyDisabled: ctx.String(GCModeFlag.Name) == "archive", TrieTimeLimit: ethconfig.Defaults.TrieTimeout, SnapshotLimit: ethconfig.Defaults.SnapshotCache, Preimages: ctx.Bool(CachePreimagesFlag.Name), + StateScheme: scheme, + StateHistory: ctx.Uint64(StateHistoryFlag.Name), } if cache.TrieDirtyDisabled && !cache.Preimages { cache.Preimages = true @@ -2158,3 +2214,27 @@ preloads = append(preloads, strings.TrimSpace(file)) } return preloads } + +// MakeTrieDatabase constructs a trie database based on the configured scheme. +func MakeTrieDatabase(ctx *cli.Context, disk ethdb.Database, preimage bool, readOnly bool) *trie.Database { + config := &trie.Config{ + Preimages: preimage, + } + scheme, err := rawdb.ParseStateScheme(ctx.String(StateSchemeFlag.Name), disk) + if err != nil { + Fatalf("%v", err) + } + if scheme == rawdb.HashScheme { + // Read-only mode is not implemented in hash mode, + // ignore the parameter silently. TODO(rjl493456442) + // please config it if read mode is implemented. + config.HashDB = hashdb.Defaults + return trie.NewDatabase(disk, config) + } + if readOnly { + config.PathDB = pathdb.ReadOnly + } else { + config.PathDB = pathdb.Defaults + } + return trie.NewDatabase(disk, config) +}
diff --git ethereum/go-ethereum/cmd/devp2p/nodesetcmd.go taikoxyz/taiko-geth/cmd/devp2p/nodesetcmd.go index f1dd220d570899aa6ec0b804c68dc9747a18788a..6fbc185ad8adaafac8c1515a7120f9e5125f2624 100644 --- ethereum/go-ethereum/cmd/devp2p/nodesetcmd.go +++ taikoxyz/taiko-geth/cmd/devp2p/nodesetcmd.go @@ -25,6 +25,7 @@ "strconv" "strings" "time"   + "github.com/ethereum/go-ethereum/core" "github.com/ethereum/go-ethereum/core/forkid" "github.com/ethereum/go-ethereum/p2p/enr" "github.com/ethereum/go-ethereum/params" @@ -228,11 +229,13 @@ func ethFilter(args []string) (nodeFilter, error) { var filter forkid.Filter switch args[0] { case "mainnet": - filter = forkid.NewStaticFilter(params.MainnetChainConfig, params.MainnetGenesisHash) + filter = forkid.NewStaticFilter(params.MainnetChainConfig, core.DefaultGenesisBlock().ToBlock()) case "goerli": - filter = forkid.NewStaticFilter(params.GoerliChainConfig, params.GoerliGenesisHash) + filter = forkid.NewStaticFilter(params.GoerliChainConfig, core.DefaultGoerliGenesisBlock().ToBlock()) case "sepolia": - filter = forkid.NewStaticFilter(params.SepoliaChainConfig, params.SepoliaGenesisHash) + filter = forkid.NewStaticFilter(params.SepoliaChainConfig, core.DefaultSepoliaGenesisBlock().ToBlock()) + case "holesky": + filter = forkid.NewStaticFilter(params.HoleskyChainConfig, core.DefaultHoleskyGenesisBlock().ToBlock()) default: return nil, fmt.Errorf("unknown network %q", args[0]) }
diff --git ethereum/go-ethereum/cmd/utils/taiko_flags.go taikoxyz/taiko-geth/cmd/utils/taiko_flags.go new file mode 100644 index 0000000000000000000000000000000000000000..d6d23c96cfbe517dc2264ff5d367bb87d62ebf78 --- /dev/null +++ taikoxyz/taiko-geth/cmd/utils/taiko_flags.go @@ -0,0 +1,35 @@ +package utils + +import ( + "os" + + "github.com/ethereum/go-ethereum/eth" + "github.com/ethereum/go-ethereum/eth/ethconfig" + "github.com/ethereum/go-ethereum/node" + "github.com/ethereum/go-ethereum/params" + "github.com/ethereum/go-ethereum/rpc" + "github.com/urfave/cli/v2" +) + +var ( + TaikoFlag = cli.BoolFlag{ + Name: "taiko", + Usage: "Taiko network", + } +) + +// RegisterTaikoAPIs initializes and registers the Taiko RPC APIs. +func RegisterTaikoAPIs(stack *node.Node, cfg *ethconfig.Config, backend *eth.Ethereum) { + if os.Getenv("TAIKO_TEST") != "" { + return + } + // Add methods under "taiko_" RPC namespace to the available APIs list + stack.RegisterAPIs([]rpc.API{ + { + Namespace: "taiko", + Version: params.VersionWithMeta, + Service: eth.NewTaikoAPIBackend(backend), + Public: true, + }, + }) +}
diff --git ethereum/go-ethereum/cmd/geth/config.go taikoxyz/taiko-geth/cmd/geth/config.go index 1a3de04bd4d2ad68682ee3495c08c3f7357cb7ea..64c569ca63f02c471665ddbe012006a8f39fb39b 100644 --- ethereum/go-ethereum/cmd/geth/config.go +++ taikoxyz/taiko-geth/cmd/geth/config.go @@ -22,9 +22,9 @@ "errors" "fmt" "os" "reflect" + "runtime" + "strings" "unicode" - - "github.com/urfave/cli/v2"   "github.com/ethereum/go-ethereum/accounts" "github.com/ethereum/go-ethereum/accounts/external" @@ -32,6 +32,8 @@ "github.com/ethereum/go-ethereum/accounts/keystore" "github.com/ethereum/go-ethereum/accounts/scwallet" "github.com/ethereum/go-ethereum/accounts/usbwallet" "github.com/ethereum/go-ethereum/cmd/utils" + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/common/hexutil" "github.com/ethereum/go-ethereum/eth/catalyst" "github.com/ethereum/go-ethereum/eth/downloader" "github.com/ethereum/go-ethereum/eth/ethconfig" @@ -43,6 +45,7 @@ "github.com/ethereum/go-ethereum/metrics" "github.com/ethereum/go-ethereum/node" "github.com/ethereum/go-ethereum/params" "github.com/naoina/toml" + "github.com/urfave/cli/v2" )   var ( @@ -177,6 +180,23 @@ cfg.Eth.OverrideVerkle = &v } backend, eth := utils.RegisterEthService(stack, &cfg.Eth)   + // CHANGE(TAIKO): register Taiko RPC APIs. + utils.RegisterTaikoAPIs(stack, &cfg.Eth, eth) + + // Create gauge with geth system and build information + if eth != nil { // The 'eth' backend may be nil in light mode + var protos []string + for _, p := range eth.Protocols() { + protos = append(protos, fmt.Sprintf("%v/%d", p.Name, p.Version)) + } + metrics.NewRegisteredGaugeInfo("geth/info", nil).Update(metrics.GaugeInfoValue{ + "arch": runtime.GOARCH, + "os": runtime.GOOS, + "version": cfg.Node.Version, + "protocols": strings.Join(protos, ","), + }) + } + // Configure log filter RPC API. filterSystem := utils.RegisterFilterAPI(stack, backend, &cfg.Eth)   @@ -184,17 +204,18 @@ // Configure GraphQL if requested. if ctx.IsSet(utils.GraphQLEnabledFlag.Name) { utils.RegisterGraphQLService(stack, backend, filterSystem, &cfg.Node) } - // Add the Ethereum Stats daemon if requested. if cfg.Ethstats.URL != "" { utils.RegisterEthStatsService(stack, backend, cfg.Ethstats.URL) } - // Configure full-sync tester service if requested - if ctx.IsSet(utils.SyncTargetFlag.Name) && cfg.Eth.SyncMode == downloader.FullSync { - utils.RegisterFullSyncTester(stack, eth, ctx.Path(utils.SyncTargetFlag.Name)) + if ctx.IsSet(utils.SyncTargetFlag.Name) { + hex := hexutil.MustDecode(ctx.String(utils.SyncTargetFlag.Name)) + if len(hex) != common.HashLength { + utils.Fatalf("invalid sync target length: have %d, want %d", len(hex), common.HashLength) + } + utils.RegisterFullSyncTester(stack, eth, common.BytesToHash(hex)) } - // Start the dev mode if requested, or launch the engine API for // interacting with external consensus client. if ctx.IsSet(utils.DeveloperFlag.Name) {
diff --git ethereum/go-ethereum/cmd/evm/staterunner.go taikoxyz/taiko-geth/cmd/evm/staterunner.go index 231830f6d78bf7094e2a2c3ef33cbd4809383af4..8a07fccdf88669592f7cbc79a6ecccff4729edc3 100644 --- ethereum/go-ethereum/cmd/evm/staterunner.go +++ taikoxyz/taiko-geth/cmd/evm/staterunner.go @@ -23,10 +23,11 @@ "fmt" "os"   "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/core/rawdb" "github.com/ethereum/go-ethereum/core/state" + "github.com/ethereum/go-ethereum/core/state/snapshot" "github.com/ethereum/go-ethereum/core/vm" "github.com/ethereum/go-ethereum/eth/tracers/logger" - "github.com/ethereum/go-ethereum/log" "github.com/ethereum/go-ethereum/tests" "github.com/urfave/cli/v2" ) @@ -50,11 +51,6 @@ State *state.Dump `json:"state,omitempty"` }   func stateTestCmd(ctx *cli.Context) error { - // Configure the go-ethereum logger - glogger := log.NewGlogHandler(log.StreamHandler(os.Stderr, log.TerminalFormat(false))) - glogger.Verbosity(log.Lvl(ctx.Int(VerbosityFlag.Name))) - log.Root().SetHandler(glogger) - // Configure the EVM logger config := &logger.Config{ EnableMemory: !ctx.Bool(DisableMemoryFlag.Name), @@ -104,25 +100,23 @@ for key, test := range tests { for _, st := range test.Subtests() { // Run the test and aggregate the result result := &StatetestResult{Name: key, Fork: st.Fork, Pass: true} - _, s, err := test.Run(st, cfg, false) - // print state root for evmlab tracing - if s != nil { - root := s.IntermediateRoot(false) - result.Root = &root - if jsonOut { - fmt.Fprintf(os.Stderr, "{\"stateRoot\": \"%#x\"}\n", root) + test.Run(st, cfg, false, rawdb.HashScheme, func(err error, snaps *snapshot.Tree, state *state.StateDB) { + if state != nil { + root := state.IntermediateRoot(false) + result.Root = &root + if jsonOut { + fmt.Fprintf(os.Stderr, "{\"stateRoot\": \"%#x\"}\n", root) + } } - } - if err != nil { - // Test failed, mark as so and dump any state to aid debugging - result.Pass, result.Error = false, err.Error() - if dump && s != nil { - s, _ = state.New(*result.Root, s.Database(), nil) - dump := s.RawDump(nil) - result.State = &dump + if err != nil { + // Test failed, mark as so and dump any state to aid debugging + result.Pass, result.Error = false, err.Error() + if dump { + dump := state.RawDump(nil) + result.State = &dump + } } - } - + }) results = append(results, *result) } }

This shows modifications to consensus files.

This is our Taiko consensus engine, built for L2 rollup.

diff --git ethereum/go-ethereum/consensus/taiko/consensus_test.go taikoxyz/taiko-geth/consensus/taiko/consensus_test.go new file mode 100644 index 0000000000000000000000000000000000000000..42adf38af1f1aafe16b9f6b6de02a999f38fdf79 --- /dev/null +++ taikoxyz/taiko-geth/consensus/taiko/consensus_test.go @@ -0,0 +1,227 @@ +package taiko_test + +import ( + "bytes" + "math/big" + "testing" + "time" + + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/consensus" + "github.com/ethereum/go-ethereum/consensus/taiko" + "github.com/ethereum/go-ethereum/core" + "github.com/ethereum/go-ethereum/core/rawdb" + "github.com/ethereum/go-ethereum/core/types" + "github.com/ethereum/go-ethereum/crypto" + "github.com/ethereum/go-ethereum/eth" + "github.com/ethereum/go-ethereum/eth/ethconfig" + "github.com/ethereum/go-ethereum/node" + "github.com/ethereum/go-ethereum/params" + "github.com/ethereum/go-ethereum/trie" + "github.com/stretchr/testify/assert" +) + +var ( + testL2RollupAddress = common.HexToAddress("0x79fcdef22feed20eddacbb2587640e45491b757f") + testKey, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291") + goldenTouchKey, _ = crypto.HexToECDSA("92954368afd3caa1f3ce3ead0069c1af414054aefe1ef9aeacc1bf426222ce38") + testAddr = crypto.PubkeyToAddress(testKey.PublicKey) + + genesis *core.Genesis + txs []*types.Transaction + testEngine *taiko.Taiko +) + +func init() { + config := params.TestChainConfig + config.GrayGlacierBlock = nil + config.ArrowGlacierBlock = nil + config.Ethash = nil + config.Taiko = true + testEngine = taiko.New(config) + + genesis = &core.Genesis{ + Config: config, + Alloc: core.GenesisAlloc{testAddr: {Balance: big.NewInt(2e15)}}, + ExtraData: []byte("test genesis"), + Timestamp: 9000, + Difficulty: common.Big0, + BaseFee: big.NewInt(params.InitialBaseFee), + } + + txs = []*types.Transaction{ + types.MustSignNewTx(goldenTouchKey, types.LatestSigner(genesis.Config), &types.DynamicFeeTx{ + Nonce: 0, + GasTipCap: common.Big0, + GasFeeCap: new(big.Int).SetUint64(875_000_000), + Data: taiko.AnchorSelector, + Gas: taiko.AnchorGasLimit, + To: &taiko.TaikoL2Address, + }), + types.MustSignNewTx(testKey, types.LatestSigner(genesis.Config), &types.LegacyTx{ + Nonce: 0, + Value: big.NewInt(12), + GasPrice: big.NewInt(params.InitialBaseFee), + Gas: params.TxGas, + To: &common.Address{2}, + }), + types.MustSignNewTx(testKey, types.LatestSigner(genesis.Config), &types.LegacyTx{ + Nonce: 1, + Value: big.NewInt(8), + GasPrice: big.NewInt(params.InitialBaseFee), + Gas: params.TxGas, + To: &common.Address{2}, + }), + // prepareBlockTx + types.MustSignNewTx(testKey, types.LatestSigner(genesis.Config), &types.LegacyTx{ + Nonce: 2, + Value: big.NewInt(8), + GasPrice: big.NewInt(params.InitialBaseFee), + Gas: params.TxGas, + To: &testL2RollupAddress, + }), + } +} + +func newTestBackend(t *testing.T) (*eth.Ethereum, []*types.Block) { + // Generate test chain. + blocks := generateTestChain() + + // Create node + n, err := node.New(&node.Config{}) + if err != nil { + t.Fatalf("can't create new node: %v", err) + } + + // Create Ethereum Service + config := &ethconfig.Config{ + Genesis: genesis, + } + + ethservice, err := eth.New(n, config) + if err != nil { + t.Fatalf("can't create new ethereum service: %v", err) + } + + // Import the test chain. + if err := n.Start(); err != nil { + t.Fatalf("can't start test node: %v", err) + } + + if _, err := ethservice.BlockChain().InsertChain(blocks[1:]); err != nil { + t.Fatalf("can't import test blocks: %v", err) + } + + if _, ok := ethservice.Engine().(*taiko.Taiko); !ok { + t.Fatalf("not use taiko engine") + } + + return ethservice, blocks +} + +func generateTestChain() []*types.Block { + db := rawdb.NewMemoryDatabase() + generate := func(i int, g *core.BlockGen) { + g.OffsetTime(5) + + g.SetExtra([]byte("test_taiko")) + g.SetDifficulty(common.Big0) + + for i, tx := range txs { + if i == 0 { + if err := tx.MarkAsAnchor(); err != nil { + panic(err) + } + } + g.AddTx(tx) + } + } + + gblock := genesis.MustCommit(db, trie.NewDatabase(db, trie.HashDefaults)) + + blocks, _ := core.GenerateChain(genesis.Config, gblock, testEngine, db, 1, generate) + + blocks = append([]*types.Block{gblock}, blocks...) + return blocks +} + +func TestVerifyHeader(t *testing.T) { + ethService, blocks := newTestBackend(t) + + for _, b := range blocks { + err := testEngine.VerifyHeader(ethService.BlockChain(), b.Header()) + assert.NoErrorf(t, err, "VerifyHeader error: %s", err) + } + + err := testEngine.VerifyHeader(ethService.BlockChain(), &types.Header{ + Number: common.Big1, + Time: uint64(time.Now().Unix()), + BaseFee: big.NewInt(params.InitialBaseFee), + WithdrawalsHash: &types.EmptyWithdrawalsHash, + UncleHash: types.EmptyUncleHash, + }) + assert.ErrorIs(t, err, consensus.ErrUnknownAncestor, "VerifyHeader should throw ErrUnknownAncestor when parentHash is unknown") + + err = testEngine.VerifyHeader(ethService.BlockChain(), &types.Header{ + ParentHash: blocks[len(blocks)-1].Hash(), + Number: common.Big0, + Time: uint64(time.Now().Unix()), + BaseFee: big.NewInt(params.InitialBaseFee), + WithdrawalsHash: &types.EmptyWithdrawalsHash, + UncleHash: types.EmptyUncleHash, + }) + assert.ErrorIs(t, err, consensus.ErrInvalidNumber, "VerifyHeader should throw ErrInvalidNumber when the block number is wrong") + + err = testEngine.VerifyHeader(ethService.BlockChain(), &types.Header{ + ParentHash: blocks[len(blocks)-1].Hash(), + Number: new(big.Int).SetInt64(int64(len(blocks))), + Time: uint64(time.Now().Unix()), + Extra: bytes.Repeat([]byte{1}, int(params.MaximumExtraDataSize+1)), + BaseFee: big.NewInt(params.InitialBaseFee), + WithdrawalsHash: &types.EmptyWithdrawalsHash, + UncleHash: types.EmptyUncleHash, + }) + assert.ErrorContains(t, err, "extra-data too long", "VerifyHeader should throw ErrExtraDataTooLong when the block has too much extra data") + + err = testEngine.VerifyHeader(ethService.BlockChain(), &types.Header{ + ParentHash: blocks[len(blocks)-1].Hash(), + Number: new(big.Int).SetInt64(int64(len(blocks))), + Time: uint64(time.Now().Unix()), + Difficulty: common.Big1, + BaseFee: big.NewInt(params.InitialBaseFee), + WithdrawalsHash: &types.EmptyWithdrawalsHash, + UncleHash: types.EmptyUncleHash, + }) + assert.ErrorContains(t, err, "invalid difficulty", "VerifyHeader should throw ErrInvalidDifficulty when difficulty is not 0") + + err = testEngine.VerifyHeader(ethService.BlockChain(), &types.Header{ + ParentHash: blocks[len(blocks)-1].Hash(), + Number: new(big.Int).SetInt64(int64(len(blocks))), + Time: uint64(time.Now().Unix()), + GasLimit: params.MaxGasLimit + 1, + BaseFee: big.NewInt(params.InitialBaseFee), + WithdrawalsHash: &types.EmptyWithdrawalsHash, + UncleHash: types.EmptyUncleHash, + }) + assert.ErrorContains(t, err, "invalid gasLimit", "VerifyHeader should throw ErrInvalidGasLimit when gasLimit is higher than the limit") + + err = testEngine.VerifyHeader(ethService.BlockChain(), &types.Header{ + ParentHash: blocks[len(blocks)-1].Hash(), + Number: new(big.Int).SetInt64(int64(len(blocks))), + Time: uint64(time.Now().Unix()), + GasLimit: params.MaxGasLimit, + BaseFee: big.NewInt(params.InitialBaseFee), + UncleHash: types.EmptyUncleHash, + }) + assert.ErrorContains(t, err, "withdrawals hash missing", "VerifyHeader should throw ErrWithdrawalsHashMissing withdrawalshash is nil") + + err = testEngine.VerifyHeader(ethService.BlockChain(), &types.Header{ + ParentHash: blocks[len(blocks)-1].Hash(), + Number: new(big.Int).SetInt64(int64(len(blocks))), + Time: uint64(time.Now().Unix()), + GasLimit: params.MaxGasLimit, + BaseFee: big.NewInt(params.InitialBaseFee), + WithdrawalsHash: &types.EmptyWithdrawalsHash, + }) + assert.ErrorContains(t, err, "uncles not empty", "VerifyHeader should throw ErrUnclesNotEmpty if uncles is not the empty hash") +}
diff --git ethereum/go-ethereum/consensus/taiko/consensus.go taikoxyz/taiko-geth/consensus/taiko/consensus.go new file mode 100644 index 0000000000000000000000000000000000000000..79e39e1f6122a600824de43c04d548c1fc2ffae6 --- /dev/null +++ taikoxyz/taiko-geth/consensus/taiko/consensus.go @@ -0,0 +1,347 @@ +package taiko + +import ( + "bytes" + "errors" + "fmt" + "math/big" + "runtime" + "strings" + "time" + + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/consensus" + "github.com/ethereum/go-ethereum/core/state" + "github.com/ethereum/go-ethereum/core/types" + "github.com/ethereum/go-ethereum/crypto" + "github.com/ethereum/go-ethereum/log" + "github.com/ethereum/go-ethereum/params" + "github.com/ethereum/go-ethereum/rpc" + "github.com/ethereum/go-ethereum/trie" +) + +var ( + ErrOlderBlockTime = errors.New("timestamp older than parent") + ErrUnclesNotEmpty = errors.New("uncles not empty") + ErrEmptyBasefee = errors.New("empty base fee") + ErrEmptyWithdrawalsHash = errors.New("withdrawals hash missing") + ErrAnchorTxNotFound = errors.New("anchor transaction not found") + + GoldenTouchAccount = common.HexToAddress("0x0000777735367b36bC9B61C50022d9D0700dB4Ec") + AnchorSelector = crypto.Keccak256([]byte("anchor(bytes32,bytes32,uint64,uint32)"))[:4] + AnchorGasLimit = uint64(250_000) + TaikoL2Address = common.HexToAddress("0x1000777700000000000000000000000000000001") +) + +// Taiko is a consensus engine used by L2 rollup. +type Taiko struct { + chainConfig *params.ChainConfig +} + +var _ = new(Taiko) + +func New(chainConfig *params.ChainConfig) *Taiko { + crypto.Keccak256() + return &Taiko{chainConfig} +} + +// check all method stubs for interface `Engine` without affect performance. +var _ consensus.Engine = (*Taiko)(nil) + +// Author retrieves the Ethereum address of the account that minted the given +// block, who proposes the block (not the prover). +func (t *Taiko) Author(header *types.Header) (common.Address, error) { + return header.Coinbase, nil +} + +// VerifyHeader checks whether a header conforms to the consensus rules of a +// given engine. Verifying the seal may be done optionally here, or explicitly +// via the VerifySeal method. +func (t *Taiko) VerifyHeader(chain consensus.ChainHeaderReader, header *types.Header) error { + // Short circuit if the header is known, or its parent not + number := header.Number.Uint64() + if chain.GetHeader(header.Hash(), number) != nil { + return nil + } + parent := chain.GetHeader(header.ParentHash, number-1) + if parent == nil { + return consensus.ErrUnknownAncestor + } + // Sanity checks passed, do a proper verification + return t.verifyHeader(chain, header, parent, time.Now().Unix()) +} + +// VerifyHeaders is similar to VerifyHeader, but verifies a batch of headers +// concurrently. The method returns a quit channel to abort the operations and +// a results channel to retrieve the async verifications (the order is that of +// the input slice). +func (t *Taiko) VerifyHeaders(chain consensus.ChainHeaderReader, headers []*types.Header) (chan<- struct{}, <-chan error) { + // Spawn as many workers as allowed threads + workers := runtime.GOMAXPROCS(0) + if len(headers) < workers { + workers = len(headers) + } + + // Create a task channel and spawn the verifiers + var ( + inputs = make(chan int) + done = make(chan int, workers) + errors = make([]error, len(headers)) + abort = make(chan struct{}) + unixNow = time.Now().Unix() + ) + for i := 0; i < workers; i++ { + go func() { + for index := range inputs { + errors[index] = t.verifyHeaderWorker(chain, headers, index, unixNow) + done <- index + } + }() + } + + errorsOut := make(chan error, len(headers)) + go func() { + defer close(inputs) + var ( + in, out = 0, 0 + checked = make([]bool, len(headers)) + inputs = inputs + ) + for { + select { + case inputs <- in: + if in++; in == len(headers) { + // Reached end of headers. Stop sending to workers. + inputs = nil + } + case index := <-done: + for checked[index] = true; checked[out]; out++ { + errorsOut <- errors[out] + if out == len(headers)-1 { + return + } + } + case <-abort: + return + } + } + }() + return abort, errorsOut +} + +func (t *Taiko) verifyHeader(chain consensus.ChainHeaderReader, header, parent *types.Header, unixNow int64) error { + if header.Time > uint64(unixNow) { + return consensus.ErrFutureBlock + } + + // Ensure that the header's extra-data section is of a reasonable size (<= 32 bytes) + if uint64(len(header.Extra)) > params.MaximumExtraDataSize { + return fmt.Errorf("extra-data too long: %d > %d", len(header.Extra), params.MaximumExtraDataSize) + } + + // Timestamp should later than or equal to parent (when many L2 blocks included in one L1 block) + if header.Time < parent.Time { + return ErrOlderBlockTime + } + + // Verify that the block number is parent's +1 + if diff := new(big.Int).Sub(header.Number, parent.Number); diff.Cmp(big.NewInt(1)) != 0 { + return consensus.ErrInvalidNumber + } + + // Difficulty should always be zero + if header.Difficulty != nil && header.Difficulty.Cmp(common.Big0) != 0 { + return fmt.Errorf("invalid difficulty: have %v, want %v", header.Difficulty, common.Big0) + } + + // Verify that the gas limit is <= 2^63-1 + if header.GasLimit > params.MaxGasLimit { + return fmt.Errorf("invalid gasLimit: have %v, max %v", header.GasLimit, params.MaxGasLimit) + } + + // Verify that the gasUsed is <= gasLimit + if header.GasUsed > header.GasLimit { + return fmt.Errorf("invalid gasUsed: have %d, gasLimit %d", header.GasUsed, header.GasLimit) + } + + // Uncles should be empty + if header.UncleHash != types.CalcUncleHash(nil) { + return ErrUnclesNotEmpty + } + + // BaseFee should not be empty + if header.BaseFee == nil { + return ErrEmptyBasefee + } + + // WithdrawalsHash should not be empty + if header.WithdrawalsHash == nil { + return ErrEmptyWithdrawalsHash + } + + return nil +} + +func (t *Taiko) verifyHeaderWorker(chain consensus.ChainHeaderReader, headers []*types.Header, index int, unixNow int64) error { + var parent *types.Header + if index == 0 { + parent = chain.GetHeader(headers[0].ParentHash, headers[0].Number.Uint64()-1) + } else if headers[index-1].Hash() == headers[index].ParentHash { + parent = headers[index-1] + } + if parent == nil { + return consensus.ErrUnknownAncestor + } + + return t.verifyHeader(chain, headers[index], parent, unixNow) +} + +// VerifyUncles verifies that the given block's uncles conform to the consensus +// rules of a given engine. +// +// always returning an error for any uncles as this consensus mechanism doesn't permit uncles. +func (t *Taiko) VerifyUncles(chain consensus.ChainReader, block *types.Block) error { + if len(block.Uncles()) > 0 { + return ErrUnclesNotEmpty + } + + return nil +} + +// Prepare initializes the consensus fields of a block header according to the +// rules of a particular engine. The changes are executed inline. +func (t *Taiko) Prepare(chain consensus.ChainHeaderReader, header *types.Header) error { + parent := chain.GetHeader(header.ParentHash, header.Number.Uint64()-1) + if parent == nil { + return consensus.ErrUnknownAncestor + } + header.Difficulty = common.Big0 + return nil +} + +// Finalize runs any post-transaction state modifications (e.g. block rewards) +// but does not assemble the block. +// +// Note: The block header and state database might be updated to reflect any +// consensus rules that happen at finalization (e.g. block rewards). +func (t *Taiko) Finalize(chain consensus.ChainHeaderReader, header *types.Header, state *state.StateDB, txs []*types.Transaction, uncles []*types.Header, withdrawals []*types.Withdrawal) { + // no block rewards in l2 + header.UncleHash = types.CalcUncleHash(nil) + header.Difficulty = common.Big0 + // Withdrawals processing. + for _, w := range withdrawals { + state.AddBalance(w.Address, new(big.Int).SetUint64(w.Amount)) + } + header.Root = state.IntermediateRoot(true) +} + +// FinalizeAndAssemble runs any post-transaction state modifications (e.g. block +// rewards) and assembles the final block. +// +// Note: The block header and state database might be updated to reflect any +// consensus rules that happen at finalization (e.g. block rewards). +func (t *Taiko) FinalizeAndAssemble(chain consensus.ChainHeaderReader, header *types.Header, state *state.StateDB, txs []*types.Transaction, uncles []*types.Header, receipts []*types.Receipt, withdrawals []*types.Withdrawal) (*types.Block, error) { + if withdrawals == nil { + withdrawals = make([]*types.Withdrawal, 0) + } + + // Verify anchor transaction + if len(txs) != 0 { // Transactions list might be empty when building empty payload. + isAnchor, err := t.ValidateAnchorTx(txs[0], header) + if err != nil { + return nil, err + } + if !isAnchor { + return nil, ErrAnchorTxNotFound + } + } + + // Finalize block + t.Finalize(chain, header, state, txs, uncles, withdrawals) + return types.NewBlockWithWithdrawals( + header, txs, nil /* ignore uncles */, receipts, withdrawals, trie.NewStackTrie(nil), + ), nil +} + +// Seal generates a new sealing request for the given input block and pushes +// the result into the given channel. +// +// Note, the method returns immediately and will send the result async. More +// than one result may also be returned depending on the consensus algorithm. +func (t *Taiko) Seal(chain consensus.ChainHeaderReader, block *types.Block, results chan<- *types.Block, stop <-chan struct{}) error { + header := block.Header() + + // Sealing the genesis block is not supported + number := header.Number.Uint64() + if number == 0 { + return consensus.ErrInvalidNumber + } + + select { + case results <- block.WithSeal(header): + case <-stop: + return nil + default: + log.Warn("Sealing result is not read by miner", "sealHash", t.SealHash(header)) + } + + return nil +} + +// SealHash returns the hash of a block prior to it being sealed. +func (t *Taiko) SealHash(header *types.Header) common.Hash { + // Keccak(rlp(header)) + return header.Hash() +} + +// CalcDifficulty is the difficulty adjustment algorithm. It returns the difficulty +// that a new block should have. +func (t *Taiko) CalcDifficulty(chain consensus.ChainHeaderReader, time uint64, parent *types.Header) *big.Int { + return common.Big0 +} + +// ValidateAnchorTx checks if the given transaction is a valid TaikoL2.anchor transaction. +func (t *Taiko) ValidateAnchorTx(tx *types.Transaction, header *types.Header) (bool, error) { + if tx.Type() != types.DynamicFeeTxType { + return false, nil + } + + if tx.To() == nil || *tx.To() != TaikoL2Address { + return false, nil + } + + if !bytes.HasPrefix(tx.Data(), AnchorSelector) { + return false, nil + } + + if tx.Value().Cmp(common.Big0) != 0 { + return false, nil + } + + if tx.Gas() != AnchorGasLimit { + return false, nil + } + + if tx.GasFeeCap().Cmp(header.BaseFee) != 0 { + return false, nil + } + + s := types.MakeSigner(t.chainConfig, header.Number, header.Time) + + addr, err := s.Sender(tx) + if err != nil { + return false, err + } + + return strings.EqualFold(addr.String(), GoldenTouchAccount.String()), nil +} + +// APIs returns the RPC APIs this consensus engine provides. +func (t *Taiko) APIs(chain consensus.ChainHeaderReader) []rpc.API { + return nil +} + +// Close terminates any background threads maintained by the consensus engine. +func (t *Taiko) Close() error { + return nil +}
diff --git ethereum/go-ethereum/consensus/beacon/consensus.go taikoxyz/taiko-geth/consensus/beacon/consensus.go index 1ad4358cfff86dcef8b250f03c32090ef1dc6bfb..e856f4e6ceadb62947b39d7858e4b44282a6fd22 100644 --- ethereum/go-ethereum/consensus/beacon/consensus.go +++ taikoxyz/taiko-geth/consensus/beacon/consensus.go @@ -269,15 +269,21 @@ } if !shanghai && header.WithdrawalsHash != nil { return fmt.Errorf("invalid withdrawalsHash: have %x, expected nil", header.WithdrawalsHash) } - // Verify the existence / non-existence of excessBlobGas + // Verify the existence / non-existence of cancun-specific header fields cancun := chain.Config().IsCancun(header.Number, header.Time) - if !cancun && header.ExcessBlobGas != nil { - return fmt.Errorf("invalid excessBlobGas: have %d, expected nil", header.ExcessBlobGas) - } - if !cancun && header.BlobGasUsed != nil { - return fmt.Errorf("invalid blobGasUsed: have %d, expected nil", header.BlobGasUsed) - } - if cancun { + if !cancun { + switch { + case header.ExcessBlobGas != nil: + return fmt.Errorf("invalid excessBlobGas: have %d, expected nil", header.ExcessBlobGas) + case header.BlobGasUsed != nil: + return fmt.Errorf("invalid blobGasUsed: have %d, expected nil", header.BlobGasUsed) + case header.ParentBeaconRoot != nil: + return fmt.Errorf("invalid parentBeaconRoot, have %#x, expected nil", header.ParentBeaconRoot) + } + } else { + if header.ParentBeaconRoot == nil { + return errors.New("header is missing beaconRoot") + } if err := eip4844.VerifyEIP4844Header(parent, header); err != nil { return err }
diff --git ethereum/go-ethereum/consensus/misc/gaslimit.go taikoxyz/taiko-geth/consensus/misc/gaslimit.go index 25f35300b94d7b8413b3be47dbb13fc0fb0ba4b1..dfcabd9a802c4341dbc25ba96d76b4ccc6e550b5 100644 --- ethereum/go-ethereum/consensus/misc/gaslimit.go +++ taikoxyz/taiko-geth/consensus/misc/gaslimit.go @@ -17,7 +17,6 @@ package misc   import ( - "errors" "fmt"   "github.com/ethereum/go-ethereum/params" @@ -36,7 +35,7 @@ if uint64(diff) >= limit { return fmt.Errorf("invalid gas limit: have %d, want %d +-= %d", headerGasLimit, parentGasLimit, limit-1) } if headerGasLimit < params.MinGasLimit { - return errors.New("invalid gas limit below 5000") + return fmt.Errorf("invalid gas limit below %d", params.MinGasLimit) } return nil }

This shows modifications to core files.

diff --git ethereum/go-ethereum/core/mkalloc.go taikoxyz/taiko-geth/core/mkalloc.go index 0e7355f6313a267aab87dc4a1f6245afd1ff5a44..12c40c14fbeaeeb5eb66aea7216f5fc5c256085b 100644 --- ethereum/go-ethereum/core/mkalloc.go +++ taikoxyz/taiko-geth/core/mkalloc.go @@ -32,24 +32,51 @@ "math/big" "os" "strconv"   + "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/core" "github.com/ethereum/go-ethereum/rlp" "golang.org/x/exp/slices" )   -type allocItem struct{ Addr, Balance *big.Int } +type allocItem struct { + Addr *big.Int + Balance *big.Int + Misc *allocItemMisc `rlp:"optional"` +} + +type allocItemMisc struct { + Nonce uint64 + Code []byte + Slots []allocItemStorageItem +} + +type allocItemStorageItem struct { + Key common.Hash + Val common.Hash +}   func makelist(g *core.Genesis) []allocItem { items := make([]allocItem, 0, len(g.Alloc)) for addr, account := range g.Alloc { + var misc *allocItemMisc if len(account.Storage) > 0 || len(account.Code) > 0 || account.Nonce != 0 { - panic(fmt.Sprintf("can't encode account %x", addr)) + misc = &allocItemMisc{ + Nonce: account.Nonce, + Code: account.Code, + Slots: make([]allocItemStorageItem, 0, len(account.Storage)), + } + for key, val := range account.Storage { + misc.Slots = append(misc.Slots, allocItemStorageItem{key, val}) + } + slices.SortFunc(misc.Slots, func(a, b allocItemStorageItem) int { + return a.Key.Cmp(b.Key) + }) } bigAddr := new(big.Int).SetBytes(addr.Bytes()) - items = append(items, allocItem{bigAddr, account.Balance}) + items = append(items, allocItem{bigAddr, account.Balance, misc}) } - slices.SortFunc(items, func(a, b allocItem) bool { - return a.Addr.Cmp(b.Addr) < 0 + slices.SortFunc(items, func(a, b allocItem) int { + return a.Addr.Cmp(b.Addr) }) return items }
diff --git ethereum/go-ethereum/core/blockchain_insert.go taikoxyz/taiko-geth/core/blockchain_insert.go index 8f496e182c9e4c0c22fdf287454d44a255318634..9bf662b6b7102e66161516a3b5f64968083be328 100644 --- ethereum/go-ethereum/core/blockchain_insert.go +++ taikoxyz/taiko-geth/core/blockchain_insert.go @@ -39,7 +39,7 @@ const statsReportLimit = 8 * time.Second   // report prints statistics if some number of blocks have been processed // or more than a few seconds have passed since the last message. -func (st *insertStats) report(chain []*types.Block, index int, dirty common.StorageSize, setHead bool) { +func (st *insertStats) report(chain []*types.Block, index int, snapDiffItems, snapBufItems, trieDiffNodes, triebufNodes common.StorageSize, setHead bool) { // Fetch the timings for the batch var ( now = mclock.Now() @@ -63,7 +63,16 @@ } if timestamp := time.Unix(int64(end.Time()), 0); time.Since(timestamp) > time.Minute { context = append(context, []interface{}{"age", common.PrettyAge(timestamp)}...) } - context = append(context, []interface{}{"dirty", dirty}...) + if snapDiffItems != 0 || snapBufItems != 0 { // snapshots enabled + context = append(context, []interface{}{"snapdiffs", snapDiffItems}...) + if snapBufItems != 0 { // future snapshot refactor + context = append(context, []interface{}{"snapdirty", snapBufItems}...) + } + } + if trieDiffNodes != 0 { // pathdb + context = append(context, []interface{}{"triediffs", trieDiffNodes}...) + } + context = append(context, []interface{}{"triedirty", triebufNodes}...)   if st.queued > 0 { context = append(context, []interface{}{"queued", st.queued}...)
diff --git ethereum/go-ethereum/core/blockchain.go taikoxyz/taiko-geth/core/blockchain.go index ba6eb574667c9c5487eebe4473f373512b81770d..baf2f9f82f42580256b2c1b1cde9a9298ac21e4f 100644 --- ethereum/go-ethereum/core/blockchain.go +++ taikoxyz/taiko-geth/core/blockchain.go @@ -48,6 +48,8 @@ "github.com/ethereum/go-ethereum/metrics" "github.com/ethereum/go-ethereum/params" "github.com/ethereum/go-ethereum/rlp" "github.com/ethereum/go-ethereum/trie" + "github.com/ethereum/go-ethereum/trie/triedb/hashdb" + "github.com/ethereum/go-ethereum/trie/triedb/pathdb" "golang.org/x/exp/slices" )   @@ -57,6 +59,8 @@ headHeaderGauge = metrics.NewRegisteredGauge("chain/head/header", nil) headFastBlockGauge = metrics.NewRegisteredGauge("chain/head/receipt", nil) headFinalizedBlockGauge = metrics.NewRegisteredGauge("chain/head/finalized", nil) headSafeBlockGauge = metrics.NewRegisteredGauge("chain/head/safe", nil) + + chainInfoGauge = metrics.NewRegisteredGaugeInfo("chain/info", nil)   accountReadTimer = metrics.NewRegisteredTimer("chain/account/reads", nil) accountHashTimer = metrics.NewRegisteredTimer("chain/account/hashes", nil) @@ -128,7 +132,7 @@ BlockChainVersion uint64 = 8 )   // CacheConfig contains the configuration values for the trie database -// that's resident in a blockchain. +// and state snapshot these are resident in a blockchain. type CacheConfig struct { TrieCleanLimit int // Memory allowance (MB) to use for caching trie nodes in memory TrieCleanNoPrefetch bool // Whether to disable heuristic state prefetching for followup blocks @@ -137,11 +141,31 @@ TrieDirtyDisabled bool // Whether to disable trie write caching and GC altogether (archive node) TrieTimeLimit time.Duration // Time limit after which to flush the current in-memory trie to disk SnapshotLimit int // Memory allowance (MB) to use for caching snapshot entries in memory Preimages bool // Whether to store preimage of trie key to the disk + StateHistory uint64 // Number of blocks from head whose state histories are reserved. + StateScheme string // Scheme used to store ethereum states and merkle tree nodes on top   SnapshotNoBuild bool // Whether the background generation is allowed SnapshotWait bool // Wait for snapshot construction on startup. TODO(karalabe): This is a dirty hack for testing, nuke it }   +// triedbConfig derives the configures for trie database. +func (c *CacheConfig) triedbConfig() *trie.Config { + config := &trie.Config{Preimages: c.Preimages} + if c.StateScheme == rawdb.HashScheme { + config.HashDB = &hashdb.Config{ + CleanCacheSize: c.TrieCleanLimit * 1024 * 1024, + } + } + if c.StateScheme == rawdb.PathScheme { + config.PathDB = &pathdb.Config{ + StateHistory: c.StateHistory, + CleanCacheSize: c.TrieCleanLimit * 1024 * 1024, + DirtyCacheSize: c.TrieDirtyLimit * 1024 * 1024, + } + } + return config +} + // defaultCacheConfig are the default caching values if none are specified by the // user (also used during testing). var defaultCacheConfig = &CacheConfig{ @@ -150,6 +174,15 @@ TrieDirtyLimit: 256, TrieTimeLimit: 5 * time.Minute, SnapshotLimit: 256, SnapshotWait: true, + StateScheme: rawdb.HashScheme, +} + +// DefaultCacheConfigWithScheme returns a deep copied default cache config with +// a provided trie node scheme. +func DefaultCacheConfigWithScheme(scheme string) *CacheConfig { + config := *defaultCacheConfig + config.StateScheme = scheme + return &config }   // BlockChain represents the canonical chain given a database with a genesis @@ -235,10 +268,8 @@ if cacheConfig == nil { cacheConfig = defaultCacheConfig } // Open trie database with provided config - triedb := trie.NewDatabaseWithConfig(db, &trie.Config{ - Cache: cacheConfig.TrieCleanLimit, - Preimages: cacheConfig.Preimages, - }) + triedb := trie.NewDatabase(db, cacheConfig.triedbConfig()) + // Setup the genesis block, commit the provided genesis specification // to database if the genesis block is not present yet, or load the // stored one from database. @@ -293,6 +324,9 @@ bc.currentSnapBlock.Store(nil) bc.currentFinalBlock.Store(nil) bc.currentSafeBlock.Store(nil)   + // Update chain info data metrics + chainInfoGauge.Update(metrics.GaugeInfoValue{"chain_id": bc.chainConfig.ChainID.String()}) + // If Geth is initialized with an external ancient store, re-initialize the // missing chain indexes and chain flags. This procedure can survive crash // and can be resumed in next restart since chain flags are updated in last step. @@ -303,31 +337,41 @@ // Load blockchain states from disk if err := bc.loadLastState(); err != nil { return nil, err } - // Make sure the state associated with the block is available + // Make sure the state associated with the block is available, or log out + // if there is no available state, waiting for state sync. head := bc.CurrentBlock() if !bc.HasState(head.Root) { - // Head state is missing, before the state recovery, find out the - // disk layer point of snapshot(if it's enabled). Make sure the - // rewound point is lower than disk layer. - var diskRoot common.Hash - if bc.cacheConfig.SnapshotLimit > 0 { - diskRoot = rawdb.ReadSnapshotRoot(bc.db) - } - if diskRoot != (common.Hash{}) { - log.Warn("Head state missing, repairing", "number", head.Number, "hash", head.Hash(), "snaproot", diskRoot) + if head.Number.Uint64() == 0 { + // The genesis state is missing, which is only possible in the path-based + // scheme. This situation occurs when the initial state sync is not finished + // yet, or the chain head is rewound below the pivot point. In both scenario, + // there is no possible recovery approach except for rerunning a snap sync. + // Do nothing here until the state syncer picks it up. + log.Info("Genesis state is missing, wait state sync") + } else { + // Head state is missing, before the state recovery, find out the + // disk layer point of snapshot(if it's enabled). Make sure the + // rewound point is lower than disk layer. + var diskRoot common.Hash + if bc.cacheConfig.SnapshotLimit > 0 { + diskRoot = rawdb.ReadSnapshotRoot(bc.db) + } + if diskRoot != (common.Hash{}) { + log.Warn("Head state missing, repairing", "number", head.Number, "hash", head.Hash(), "snaproot", diskRoot)   - snapDisk, err := bc.setHeadBeyondRoot(head.Number.Uint64(), 0, diskRoot, true) - if err != nil { - return nil, err - } - // Chain rewound, persist old snapshot number to indicate recovery procedure - if snapDisk != 0 { - rawdb.WriteSnapshotRecoveryNumber(bc.db, snapDisk) - } - } else { - log.Warn("Head state missing, repairing", "number", head.Number, "hash", head.Hash()) - if _, err := bc.setHeadBeyondRoot(head.Number.Uint64(), 0, common.Hash{}, true); err != nil { - return nil, err + snapDisk, err := bc.setHeadBeyondRoot(head.Number.Uint64(), 0, diskRoot, true) + if err != nil { + return nil, err + } + // Chain rewound, persist old snapshot number to indicate recovery procedure + if snapDisk != 0 { + rawdb.WriteSnapshotRecoveryNumber(bc.db, snapDisk) + } + } else { + log.Warn("Head state missing, repairing", "number", head.Number, "hash", head.Hash()) + if _, err := bc.setHeadBeyondRoot(head.Number.Uint64(), 0, common.Hash{}, true); err != nil { + return nil, err + } } } } @@ -532,7 +576,7 @@ // Send chain head event to update the transaction pool header := bc.CurrentBlock() block := bc.GetBlock(header.Hash(), header.Number.Uint64()) if block == nil { - // This should never happen. In practice, previsouly currentBlock + // This should never happen. In practice, previously currentBlock // contained the entire block whereas now only a "marker", so there // is an ever so slight chance for a race we should handle. log.Error("Current block not found in database", "block", header.Number, "hash", header.Hash()) @@ -554,7 +598,7 @@ // Send chain head event to update the transaction pool header := bc.CurrentBlock() block := bc.GetBlock(header.Hash(), header.Number.Uint64()) if block == nil { - // This should never happen. In practice, previsouly currentBlock + // This should never happen. In practice, previously currentBlock // contained the entire block whereas now only a "marker", so there // is an ever so slight chance for a race we should handle. log.Error("Current block not found in database", "block", header.Number, "hash", header.Hash()) @@ -632,7 +676,7 @@ // If a root threshold was requested but not yet crossed, check if root != (common.Hash{}) && !beyondRoot && newHeadBlock.Root() == root { beyondRoot, rootNumber = true, newHeadBlock.NumberU64() } - if !bc.HasState(newHeadBlock.Root()) { + if !bc.HasState(newHeadBlock.Root()) && !bc.stateRecoverable(newHeadBlock.Root()) { log.Trace("Block state missing, rewinding further", "number", newHeadBlock.NumberU64(), "hash", newHeadBlock.Hash()) if pivot == nil || newHeadBlock.NumberU64() > *pivot { parent := bc.GetBlock(newHeadBlock.ParentHash(), newHeadBlock.NumberU64()-1) @@ -648,20 +692,14 @@ newHeadBlock = bc.genesisBlock } } if beyondRoot || newHeadBlock.NumberU64() == 0 { - if newHeadBlock.NumberU64() == 0 { - // Recommit the genesis state into disk in case the rewinding destination - // is genesis block and the relevant state is gone. In the future this - // rewinding destination can be the earliest block stored in the chain - // if the historical chain pruning is enabled. In that case the logic - // needs to be improved here. - if !bc.HasState(bc.genesisBlock.Root()) { - if err := CommitGenesisState(bc.db, bc.triedb, bc.genesisBlock.Hash()); err != nil { - log.Crit("Failed to commit genesis state", "err", err) - } - log.Debug("Recommitted genesis state to disk") + if !bc.HasState(newHeadBlock.Root()) && bc.stateRecoverable(newHeadBlock.Root()) { + // Rewind to a block with recoverable state. If the state is + // missing, run the state recovery here. + if err := bc.triedb.Recover(newHeadBlock.Root()); err != nil { + log.Crit("Failed to rollback state", "err", err) // Shouldn't happen } + log.Debug("Rewound to block with state", "number", newHeadBlock.NumberU64(), "hash", newHeadBlock.Hash()) } - log.Debug("Rewound to block with state", "number", newHeadBlock.NumberU64(), "hash", newHeadBlock.Hash()) break } log.Debug("Skipping block with threshold state", "number", newHeadBlock.NumberU64(), "hash", newHeadBlock.Hash(), "root", newHeadBlock.Root()) @@ -676,6 +714,15 @@ // last step, however the direction of SetHead is from high // to low, so it's safe to update in-memory markers directly. bc.currentBlock.Store(newHeadBlock.Header()) headBlockGauge.Update(int64(newHeadBlock.NumberU64())) + + // The head state is missing, which is only possible in the path-based + // scheme. This situation occurs when the chain head is rewound below + // the pivot point. In this scenario, there is no possible recovery + // approach except for rerunning a snap sync. Do nothing here until the + // state syncer picks it up. + if !bc.HasState(newHeadBlock.Root()) { + log.Info("Chain is stateless, wait state sync", "number", newHeadBlock.Number(), "hash", newHeadBlock.Hash()) + } } // Rewind the snap block in a simpleton way to the target head if currentSnapBlock := bc.CurrentSnapBlock(); currentSnapBlock != nil && header.Number.Uint64() < currentSnapBlock.Number.Uint64() { @@ -772,7 +819,13 @@ block := bc.GetBlockByHash(hash) if block == nil { return fmt.Errorf("non existent block [%x..]", hash[:4]) } + // Reset the trie database with the fresh snap synced state. root := block.Root() + if bc.triedb.Scheme() == rawdb.PathScheme { + if err := bc.triedb.Enable(root); err != nil { + return err + } + } if !bc.HasState(root) { return fmt.Errorf("non existent state [%x..]", root[:4]) } @@ -929,7 +982,7 @@ // it will abort them using the procInterrupt. func (bc *BlockChain) Stop() { bc.stopWithoutSaving()   - // Ensure that the entirety of the state snapshot is journalled to disk. + // Ensure that the entirety of the state snapshot is journaled to disk. var snapBase common.Hash if bc.snaps != nil { var err error @@ -937,41 +990,47 @@ if snapBase, err = bc.snaps.Journal(bc.CurrentBlock().Root); err != nil { log.Error("Failed to journal state snapshot", "err", err) } } - - // Ensure the state of a recent block is also stored to disk before exiting. - // We're writing three different states to catch different restart scenarios: - // - HEAD: So we don't need to reprocess any blocks in the general case - // - HEAD-1: So we don't do large reorgs if our HEAD becomes an uncle - // - HEAD-127: So we have a hard limit on the number of blocks reexecuted - if !bc.cacheConfig.TrieDirtyDisabled { - triedb := bc.triedb + if bc.triedb.Scheme() == rawdb.PathScheme { + // Ensure that the in-memory trie nodes are journaled to disk properly. + if err := bc.triedb.Journal(bc.CurrentBlock().Root); err != nil { + log.Info("Failed to journal in-memory trie nodes", "err", err) + } + } else { + // Ensure the state of a recent block is also stored to disk before exiting. + // We're writing three different states to catch different restart scenarios: + // - HEAD: So we don't need to reprocess any blocks in the general case + // - HEAD-1: So we don't do large reorgs if our HEAD becomes an uncle + // - HEAD-127: So we have a hard limit on the number of blocks reexecuted + if !bc.cacheConfig.TrieDirtyDisabled { + triedb := bc.triedb   - for _, offset := range []uint64{0, 1, TriesInMemory - 1} { - if number := bc.CurrentBlock().Number.Uint64(); number > offset { - recent := bc.GetBlockByNumber(number - offset) + for _, offset := range []uint64{0, 1, TriesInMemory - 1} { + if number := bc.CurrentBlock().Number.Uint64(); number > offset { + recent := bc.GetBlockByNumber(number - offset)   - log.Info("Writing cached state to disk", "block", recent.Number(), "hash", recent.Hash(), "root", recent.Root()) - if err := triedb.Commit(recent.Root(), true); err != nil { + log.Info("Writing cached state to disk", "block", recent.Number(), "hash", recent.Hash(), "root", recent.Root()) + if err := triedb.Commit(recent.Root(), true); err != nil { + log.Error("Failed to commit recent state trie", "err", err) + } + } + } + if snapBase != (common.Hash{}) { + log.Info("Writing snapshot state to disk", "root", snapBase) + if err := triedb.Commit(snapBase, true); err != nil { log.Error("Failed to commit recent state trie", "err", err) } } - } - if snapBase != (common.Hash{}) { - log.Info("Writing snapshot state to disk", "root", snapBase) - if err := triedb.Commit(snapBase, true); err != nil { - log.Error("Failed to commit recent state trie", "err", err) + for !bc.triegc.Empty() { + triedb.Dereference(bc.triegc.PopItem()) } - } - for !bc.triegc.Empty() { - triedb.Dereference(bc.triegc.PopItem()) - } - if size, _ := triedb.Size(); size != 0 { - log.Error("Dangling trie nodes after full cleanup") + if _, nodes, _ := triedb.Size(); nodes != 0 { // all memory is contained within the nodes return for hashdb + log.Error("Dangling trie nodes after full cleanup") + } } } - // Flush the collected preimages to disk - if err := bc.stateCache.TrieDB().Close(); err != nil { - log.Error("Failed to close trie db", "err", err) + // Close the trie database, release all the held resources as the last step. + if err := bc.triedb.Close(); err != nil { + log.Error("Failed to close trie database", "err", err) } log.Info("Blockchain stopped") } @@ -1028,19 +1087,30 @@ ancientBlocks, liveBlocks types.Blocks ancientReceipts, liveReceipts []types.Receipts ) // Do a sanity check that the provided chain is actually ordered and linked - for i := 0; i < len(blockChain); i++ { + for i, block := range blockChain { if i != 0 { - if blockChain[i].NumberU64() != blockChain[i-1].NumberU64()+1 || blockChain[i].ParentHash() != blockChain[i-1].Hash() { - log.Error("Non contiguous receipt insert", "number", blockChain[i].Number(), "hash", blockChain[i].Hash(), "parent", blockChain[i].ParentHash(), - "prevnumber", blockChain[i-1].Number(), "prevhash", blockChain[i-1].Hash()) - return 0, fmt.Errorf("non contiguous insert: item %d is #%d [%x..], item %d is #%d [%x..] (parent [%x..])", i-1, blockChain[i-1].NumberU64(), - blockChain[i-1].Hash().Bytes()[:4], i, blockChain[i].NumberU64(), blockChain[i].Hash().Bytes()[:4], blockChain[i].ParentHash().Bytes()[:4]) + prev := blockChain[i-1] + if block.NumberU64() != prev.NumberU64()+1 || block.ParentHash() != prev.Hash() { + log.Error("Non contiguous receipt insert", + "number", block.Number(), "hash", block.Hash(), "parent", block.ParentHash(), + "prevnumber", prev.Number(), "prevhash", prev.Hash()) + return 0, fmt.Errorf("non contiguous insert: item %d is #%d [%x..], item %d is #%d [%x..] (parent [%x..])", + i-1, prev.NumberU64(), prev.Hash().Bytes()[:4], + i, block.NumberU64(), block.Hash().Bytes()[:4], block.ParentHash().Bytes()[:4]) } } - if blockChain[i].NumberU64() <= ancientLimit { - ancientBlocks, ancientReceipts = append(ancientBlocks, blockChain[i]), append(ancientReceipts, receiptChain[i]) + if block.NumberU64() <= ancientLimit { + ancientBlocks, ancientReceipts = append(ancientBlocks, block), append(ancientReceipts, receiptChain[i]) } else { - liveBlocks, liveReceipts = append(liveBlocks, blockChain[i]), append(liveReceipts, receiptChain[i]) + liveBlocks, liveReceipts = append(liveBlocks, block), append(liveReceipts, receiptChain[i]) + } + + // Here we also validate that blob transactions in the block do not contain a sidecar. + // While the sidecar does not affect the block hash / tx hash, sending blobs within a block is not allowed. + for txIndex, tx := range block.Transactions() { + if tx.Type() == types.BlobTxType && tx.BlobTxSidecar() != nil { + return 0, fmt.Errorf("block #%d contains unexpected blob sidecar in tx at index %d", block.NumberU64(), txIndex) + } } }   @@ -1123,7 +1193,7 @@ // an external ancient database, during the setup, blockchain will start // a background routine to re-indexed all indices in [ancients - txlookupLimit, ancients) // range. In this case, all tx indices of newly imported blocks should be // generated. - var batch = bc.db.NewBatch() + batch := bc.db.NewBatch() for i, block := range blockChain { if bc.txLookupLimit == 0 || ancientLimit <= bc.txLookupLimit || block.NumberU64() >= ancientLimit-bc.txLookupLimit { rawdb.WriteTxLookupEntriesByBlock(batch, block) @@ -1341,6 +1411,11 @@ root, err := state.Commit(block.NumberU64(), bc.chainConfig.IsEIP158(block.Number())) if err != nil { return err } + // If node is running in path mode, skip explicit gc operation + // which is unnecessary in this mode. + if bc.triedb.Scheme() == rawdb.PathScheme { + return nil + } // If we're running an archive node, always flush if bc.cacheConfig.TrieDirtyDisabled { return bc.triedb.Commit(root, false) @@ -1349,15 +1424,15 @@ // Full but not archive node, do proper garbage collection bc.triedb.Reference(root, common.Hash{}) // metadata reference to keep trie alive bc.triegc.Push(root, -int64(block.NumberU64()))   + // Flush limits are not considered for the first TriesInMemory blocks. current := block.NumberU64() - // Flush limits are not considered for the first TriesInMemory blocks. if current <= TriesInMemory { return nil } // If we exceeded our memory allowance, flush matured singleton nodes to disk var ( - nodes, imgs = bc.triedb.Size() - limit = common.StorageSize(bc.cacheConfig.TrieDirtyLimit) * 1024 * 1024 + _, nodes, imgs = bc.triedb.Size() // all memory is contained within the nodes return for hashdb + limit = common.StorageSize(bc.cacheConfig.TrieDirtyLimit) * 1024 * 1024 ) if nodes > limit || imgs > 4*1024*1024 { bc.triedb.Cap(limit - ethdb.IdealBatchSize) @@ -1793,8 +1868,12 @@ // Report the import stats before returning the various results stats.processed++ stats.usedGas += usedGas   - dirty, _ := bc.triedb.Size() - stats.report(chain, it.index, dirty, setHead) + var snapDiffItems, snapBufItems common.StorageSize + if bc.snaps != nil { + snapDiffItems, snapBufItems = bc.snaps.Size() + } + trieDiffNodes, trieBufNodes, _ := bc.triedb.Size() + stats.report(chain, it.index, snapDiffItems, snapBufItems, trieDiffNodes, trieBufNodes, setHead)   if !setHead { // After merge we expect few side chains. Simply count @@ -1936,6 +2015,12 @@ numbers []uint64 ) parent := it.previous() for parent != nil && !bc.HasState(parent.Root) { + if bc.stateRecoverable(parent.Root) { + if err := bc.triedb.Recover(parent.Root); err != nil { + return 0, err + } + break + } hashes = append(hashes, parent.Hash()) numbers = append(numbers, parent.Number.Uint64())   @@ -1992,6 +2077,12 @@ numbers []uint64 parent = block ) for parent != nil && !bc.HasState(parent.Root()) { + if bc.stateRecoverable(parent.Root()) { + if err := bc.triedb.Recover(parent.Root()); err != nil { + return common.Hash{}, err + } + break + } hashes = append(hashes, parent.Hash()) numbers = append(numbers, parent.NumberU64()) parent = bc.GetBlock(parent.ParentHash(), parent.NumberU64()-1) @@ -2336,6 +2427,12 @@ // indexBlocks reindexes or unindexes transactions depending on user configuration func (bc *BlockChain) indexBlocks(tail *uint64, head uint64, done chan struct{}) { defer func() { close(done) }()   + // If head is 0, it means the chain is just initialized and no blocks are inserted, + // so don't need to indexing anything. + if head == 0 { + return + } + // The tail flag is not existent, it means the node is just initialized // and all blocks(may from ancient store) are not indexed yet. if tail == nil { @@ -2393,6 +2490,15 @@ if sub == nil { return } defer sub.Unsubscribe() + log.Info("Initialized transaction indexer", "limit", bc.TxLookupLimit()) + + // Launch the initial processing if chain is not empty. This step is + // useful in these scenarios that chain has no progress and indexer + // is never triggered. + if head := rawdb.ReadHeadBlock(bc.db); head != nil { + done = make(chan struct{}) + go bc.indexBlocks(rawdb.ReadTxIndexTail(bc.db), head.NumberU64(), done) + }   for { select { @@ -2479,7 +2585,7 @@ func (bc *BlockChain) SetTrieFlushInterval(interval time.Duration) { bc.flushInterval.Store(int64(interval)) }   -// GetTrieFlushInterval gets the in-memroy tries flush interval +// GetTrieFlushInterval gets the in-memory tries flush interval func (bc *BlockChain) GetTrieFlushInterval() time.Duration { return time.Duration(bc.flushInterval.Load()) }
diff --git ethereum/go-ethereum/core/dao_test.go taikoxyz/taiko-geth/core/dao_test.go index f2e8dfe8f9aa3bdd784d558e817e494fb2a845a6..b9a899ef2f92f34ac69baff039b2d4bc3a50bf3c 100644 --- ethereum/go-ethereum/core/dao_test.go +++ taikoxyz/taiko-geth/core/dao_test.go @@ -83,7 +83,7 @@ } if _, err := bc.InsertChain(blocks); err != nil { t.Fatalf("failed to import contra-fork chain for expansion: %v", err) } - if err := bc.stateCache.TrieDB().Commit(bc.CurrentHeader().Root, false); err != nil { + if err := bc.triedb.Commit(bc.CurrentHeader().Root, false); err != nil { t.Fatalf("failed to commit contra-fork head for expansion: %v", err) } bc.Stop() @@ -106,7 +106,7 @@ } if _, err := bc.InsertChain(blocks); err != nil { t.Fatalf("failed to import pro-fork chain for expansion: %v", err) } - if err := bc.stateCache.TrieDB().Commit(bc.CurrentHeader().Root, false); err != nil { + if err := bc.triedb.Commit(bc.CurrentHeader().Root, false); err != nil { t.Fatalf("failed to commit pro-fork head for expansion: %v", err) } bc.Stop() @@ -131,7 +131,7 @@ } if _, err := bc.InsertChain(blocks); err != nil { t.Fatalf("failed to import contra-fork chain for expansion: %v", err) } - if err := bc.stateCache.TrieDB().Commit(bc.CurrentHeader().Root, false); err != nil { + if err := bc.triedb.Commit(bc.CurrentHeader().Root, false); err != nil { t.Fatalf("failed to commit contra-fork head for expansion: %v", err) } blocks, _ = GenerateChain(&proConf, conBc.GetBlockByHash(conBc.CurrentBlock().Hash()), ethash.NewFaker(), genDb, 1, func(i int, gen *BlockGen) {}) @@ -149,7 +149,7 @@ } if _, err := bc.InsertChain(blocks); err != nil { t.Fatalf("failed to import pro-fork chain for expansion: %v", err) } - if err := bc.stateCache.TrieDB().Commit(bc.CurrentHeader().Root, false); err != nil { + if err := bc.triedb.Commit(bc.CurrentHeader().Root, false); err != nil { t.Fatalf("failed to commit pro-fork head for expansion: %v", err) } blocks, _ = GenerateChain(&conConf, proBc.GetBlockByHash(proBc.CurrentBlock().Hash()), ethash.NewFaker(), genDb, 1, func(i int, gen *BlockGen) {})
diff --git ethereum/go-ethereum/core/blockchain_snapshot_test.go taikoxyz/taiko-geth/core/blockchain_snapshot_test.go index 3bd876a58ec7ca319a74778e8c1c5b50c6c4cd5c..dd012c430c4d49a8cf247084423713de3a96b660 100644 --- ethereum/go-ethereum/core/blockchain_snapshot_test.go +++ taikoxyz/taiko-geth/core/blockchain_snapshot_test.go @@ -24,6 +24,7 @@ "bytes" "fmt" "math/big" "os" + "path" "strings" "testing" "time" @@ -39,6 +40,7 @@ )   // snapshotTestBasic wraps the common testing fields in the snapshot tests. type snapshotTestBasic struct { + scheme string // Disk scheme used for storing trie nodes chainBlocks int // Number of blocks to generate for the canonical chain snapshotBlock uint64 // Block number of the relevant snapshot disk layer commitBlock uint64 // Block number for which to commit the state to disk @@ -51,6 +53,7 @@ expSnapshotBottom uint64 // The block height corresponding to the snapshot disk layer   // share fields, set in runtime datadir string + ancient string db ethdb.Database genDb ethdb.Database engine consensus.Engine @@ -60,10 +63,12 @@ func (basic *snapshotTestBasic) prepare(t *testing.T) (*BlockChain, []*types.Block) { // Create a temporary persistent database datadir := t.TempDir() + ancient := path.Join(datadir, "ancient")   db, err := rawdb.Open(rawdb.OpenOptions{ Directory: datadir, - AncientsDirectory: datadir, + AncientsDirectory: ancient, + Ephemeral: true, }) if err != nil { t.Fatalf("Failed to create persistent database: %v", err) @@ -75,13 +80,8 @@ BaseFee: big.NewInt(params.InitialBaseFee), Config: params.AllEthashProtocolChanges, } engine = ethash.NewFullFaker() - - // Snapshot is enabled, the first snapshot is created from the Genesis. - // The snapshot memory allowance is 256MB, it means no snapshot flush - // will happen during the block insertion. - cacheConfig = defaultCacheConfig ) - chain, err := NewBlockChain(db, cacheConfig, gspec, nil, engine, vm.Config{}, nil, nil) + chain, err := NewBlockChain(db, DefaultCacheConfigWithScheme(basic.scheme), gspec, nil, engine, vm.Config{}, nil, nil) if err != nil { t.Fatalf("Failed to create chain: %v", err) } @@ -102,7 +102,7 @@ } startPoint = point   if basic.commitBlock > 0 && basic.commitBlock == point { - chain.stateCache.TrieDB().Commit(blocks[point-1].Root(), false) + chain.TrieDB().Commit(blocks[point-1].Root(), false) } if basic.snapshotBlock > 0 && basic.snapshotBlock == point { // Flushing the entire snap tree into the disk, the @@ -121,6 +121,7 @@ }   // Set runtime fields basic.datadir = datadir + basic.ancient = ancient basic.db = db basic.genDb = genDb basic.engine = engine @@ -210,6 +211,7 @@ func (basic *snapshotTestBasic) teardown() { basic.db.Close() basic.genDb.Close() os.RemoveAll(basic.datadir) + os.RemoveAll(basic.ancient) }   // snapshotTest is a test case type for normal snapshot recovery. @@ -226,7 +228,7 @@ chain, blocks := snaptest.prepare(t)   // Restart the chain normally chain.Stop() - newchain, err := NewBlockChain(snaptest.db, nil, snaptest.gspec, nil, snaptest.engine, vm.Config{}, nil, nil) + newchain, err := NewBlockChain(snaptest.db, DefaultCacheConfigWithScheme(snaptest.scheme), snaptest.gspec, nil, snaptest.engine, vm.Config{}, nil, nil) if err != nil { t.Fatalf("Failed to recreate chain: %v", err) } @@ -235,7 +237,7 @@ snaptest.verify(t, newchain, blocks) }   -// crashSnapshotTest is a test case type for innormal snapshot recovery. +// crashSnapshotTest is a test case type for irregular snapshot recovery. // It can be used for testing that restart Geth after the crash. type crashSnapshotTest struct { snapshotTestBasic @@ -251,13 +253,14 @@ // Pull the plug on the database, simulating a hard crash db := chain.db db.Close() chain.stopWithoutSaving() + chain.triedb.Close()   // Start a new blockchain back up and see where the repair leads us newdb, err := rawdb.Open(rawdb.OpenOptions{ Directory: snaptest.datadir, - AncientsDirectory: snaptest.datadir, + AncientsDirectory: snaptest.ancient, + Ephemeral: true, }) - if err != nil { t.Fatalf("Failed to reopen persistent database: %v", err) } @@ -267,13 +270,13 @@ // The interesting thing is: instead of starting the blockchain after // the crash, we do restart twice here: one after the crash and one // after the normal stop. It's used to ensure the broken snapshot // can be detected all the time. - newchain, err := NewBlockChain(newdb, nil, snaptest.gspec, nil, snaptest.engine, vm.Config{}, nil, nil) + newchain, err := NewBlockChain(newdb, DefaultCacheConfigWithScheme(snaptest.scheme), snaptest.gspec, nil, snaptest.engine, vm.Config{}, nil, nil) if err != nil { t.Fatalf("Failed to recreate chain: %v", err) } newchain.Stop()   - newchain, err = NewBlockChain(newdb, nil, snaptest.gspec, nil, snaptest.engine, vm.Config{}, nil, nil) + newchain, err = NewBlockChain(newdb, DefaultCacheConfigWithScheme(snaptest.scheme), snaptest.gspec, nil, snaptest.engine, vm.Config{}, nil, nil) if err != nil { t.Fatalf("Failed to recreate chain: %v", err) } @@ -300,7 +303,7 @@ chain, blocks := snaptest.prepare(t)   // Insert blocks without enabling snapshot if gapping is required. chain.Stop() - gappedBlocks, _ := GenerateChain(params.TestChainConfig, blocks[len(blocks)-1], snaptest.engine, snaptest.genDb, snaptest.gapped, func(i int, b *BlockGen) {}) + gappedBlocks, _ := GenerateChain(snaptest.gspec.Config, blocks[len(blocks)-1], snaptest.engine, snaptest.genDb, snaptest.gapped, func(i int, b *BlockGen) {})   // Insert a few more blocks without enabling snapshot var cacheConfig = &CacheConfig{ @@ -308,6 +311,7 @@ TrieCleanLimit: 256, TrieDirtyLimit: 256, TrieTimeLimit: 5 * time.Minute, SnapshotLimit: 0, + StateScheme: snaptest.scheme, } newchain, err := NewBlockChain(snaptest.db, cacheConfig, snaptest.gspec, nil, snaptest.engine, vm.Config{}, nil, nil) if err != nil { @@ -317,7 +321,7 @@ newchain.InsertChain(gappedBlocks) newchain.Stop()   // Restart the chain with enabling the snapshot - newchain, err = NewBlockChain(snaptest.db, nil, snaptest.gspec, nil, snaptest.engine, vm.Config{}, nil, nil) + newchain, err = NewBlockChain(snaptest.db, DefaultCacheConfigWithScheme(snaptest.scheme), snaptest.gspec, nil, snaptest.engine, vm.Config{}, nil, nil) if err != nil { t.Fatalf("Failed to recreate chain: %v", err) } @@ -345,7 +349,7 @@ // Rewind the chain if setHead operation is required. chain.SetHead(snaptest.setHead) chain.Stop()   - newchain, err := NewBlockChain(snaptest.db, nil, snaptest.gspec, nil, snaptest.engine, vm.Config{}, nil, nil) + newchain, err := NewBlockChain(snaptest.db, DefaultCacheConfigWithScheme(snaptest.scheme), snaptest.gspec, nil, snaptest.engine, vm.Config{}, nil, nil) if err != nil { t.Fatalf("Failed to recreate chain: %v", err) } @@ -379,22 +383,24 @@ TrieCleanLimit: 256, TrieDirtyLimit: 256, TrieTimeLimit: 5 * time.Minute, SnapshotLimit: 0, + StateScheme: snaptest.scheme, } newchain, err := NewBlockChain(snaptest.db, config, snaptest.gspec, nil, snaptest.engine, vm.Config{}, nil, nil) if err != nil { t.Fatalf("Failed to recreate chain: %v", err) } - newBlocks, _ := GenerateChain(params.TestChainConfig, blocks[len(blocks)-1], snaptest.engine, snaptest.genDb, snaptest.newBlocks, func(i int, b *BlockGen) {}) + newBlocks, _ := GenerateChain(snaptest.gspec.Config, blocks[len(blocks)-1], snaptest.engine, snaptest.genDb, snaptest.newBlocks, func(i int, b *BlockGen) {}) newchain.InsertChain(newBlocks) newchain.Stop()   - // Restart the chain, the wiper should starts working + // Restart the chain, the wiper should start working config = &CacheConfig{ TrieCleanLimit: 256, TrieDirtyLimit: 256, TrieTimeLimit: 5 * time.Minute, SnapshotLimit: 256, SnapshotWait: false, // Don't wait rebuild + StateScheme: snaptest.scheme, } tmp, err := NewBlockChain(snaptest.db, config, snaptest.gspec, nil, snaptest.engine, vm.Config{}, nil, nil) if err != nil { @@ -402,14 +408,15 @@ t.Fatalf("Failed to recreate chain: %v", err) }   // Simulate the blockchain crash. + tmp.triedb.Close() tmp.stopWithoutSaving()   - newchain, err = NewBlockChain(snaptest.db, nil, snaptest.gspec, nil, snaptest.engine, vm.Config{}, nil, nil) + newchain, err = NewBlockChain(snaptest.db, DefaultCacheConfigWithScheme(snaptest.scheme), snaptest.gspec, nil, snaptest.engine, vm.Config{}, nil, nil) if err != nil { t.Fatalf("Failed to recreate chain: %v", err) } - defer newchain.Stop() snaptest.verify(t, newchain, blocks) + newchain.Stop() }   // Tests a Geth restart with valid snapshot. Before the shutdown, all snapshot @@ -433,20 +440,23 @@ // Expected head header : C8 // Expected head fast block: C8 // Expected head block : C8 // Expected snapshot disk : G - test := &snapshotTest{ - snapshotTestBasic{ - chainBlocks: 8, - snapshotBlock: 0, - commitBlock: 0, - expCanonicalBlocks: 8, - expHeadHeader: 8, - expHeadFastBlock: 8, - expHeadBlock: 8, - expSnapshotBottom: 0, // Initial disk layer built from genesis - }, + for _, scheme := range []string{rawdb.HashScheme, rawdb.PathScheme} { + test := &snapshotTest{ + snapshotTestBasic{ + scheme: scheme, + chainBlocks: 8, + snapshotBlock: 0, + commitBlock: 0, + expCanonicalBlocks: 8, + expHeadHeader: 8, + expHeadFastBlock: 8, + expHeadBlock: 8, + expSnapshotBottom: 0, // Initial disk layer built from genesis + }, + } + test.test(t) + test.teardown() } - test.test(t) - test.teardown() }   // Tests a Geth was crashed and restarts with a broken snapshot. In this case the @@ -472,20 +482,23 @@ // Expected head header : C8 // Expected head fast block: C8 // Expected head block : G // Expected snapshot disk : C4 - test := &crashSnapshotTest{ - snapshotTestBasic{ - chainBlocks: 8, - snapshotBlock: 4, - commitBlock: 0, - expCanonicalBlocks: 8, - expHeadHeader: 8, - expHeadFastBlock: 8, - expHeadBlock: 0, - expSnapshotBottom: 4, // Last committed disk layer, wait recovery - }, + for _, scheme := range []string{rawdb.HashScheme, rawdb.PathScheme} { + test := &crashSnapshotTest{ + snapshotTestBasic{ + scheme: scheme, + chainBlocks: 8, + snapshotBlock: 4, + commitBlock: 0, + expCanonicalBlocks: 8, + expHeadHeader: 8, + expHeadFastBlock: 8, + expHeadBlock: 0, + expSnapshotBottom: 4, // Last committed disk layer, wait recovery + }, + } + test.test(t) + test.teardown() } - test.test(t) - test.teardown() }   // Tests a Geth was crashed and restarts with a broken snapshot. In this case the @@ -511,20 +524,23 @@ // Expected head header : C8 // Expected head fast block: C8 // Expected head block : C2 // Expected snapshot disk : C4 - test := &crashSnapshotTest{ - snapshotTestBasic{ - chainBlocks: 8, - snapshotBlock: 4, - commitBlock: 2, - expCanonicalBlocks: 8, - expHeadHeader: 8, - expHeadFastBlock: 8, - expHeadBlock: 2, - expSnapshotBottom: 4, // Last committed disk layer, wait recovery - }, + for _, scheme := range []string{rawdb.HashScheme, rawdb.PathScheme} { + test := &crashSnapshotTest{ + snapshotTestBasic{ + scheme: scheme, + chainBlocks: 8, + snapshotBlock: 4, + commitBlock: 2, + expCanonicalBlocks: 8, + expHeadHeader: 8, + expHeadFastBlock: 8, + expHeadBlock: 2, + expSnapshotBottom: 4, // Last committed disk layer, wait recovery + }, + } + test.test(t) + test.teardown() } - test.test(t) - test.teardown() }   // Tests a Geth was crashed and restarts with a broken snapshot. In this case @@ -550,20 +566,27 @@ // Expected head header : C8 // Expected head fast block: C8 // Expected head block : G // Expected snapshot disk : C4 - test := &crashSnapshotTest{ - snapshotTestBasic{ - chainBlocks: 8, - snapshotBlock: 4, - commitBlock: 6, - expCanonicalBlocks: 8, - expHeadHeader: 8, - expHeadFastBlock: 8, - expHeadBlock: 0, - expSnapshotBottom: 4, // Last committed disk layer, wait recovery - }, + for _, scheme := range []string{rawdb.HashScheme, rawdb.PathScheme} { + expHead := uint64(0) + if scheme == rawdb.PathScheme { + expHead = uint64(4) + } + test := &crashSnapshotTest{ + snapshotTestBasic{ + scheme: scheme, + chainBlocks: 8, + snapshotBlock: 4, + commitBlock: 6, + expCanonicalBlocks: 8, + expHeadHeader: 8, + expHeadFastBlock: 8, + expHeadBlock: expHead, + expSnapshotBottom: 4, // Last committed disk layer, wait recovery + }, + } + test.test(t) + test.teardown() } - test.test(t) - test.teardown() }   // Tests a Geth was running with snapshot enabled. Then restarts without @@ -587,21 +610,24 @@ // Expected head header : C10 // Expected head fast block: C10 // Expected head block : C10 // Expected snapshot disk : C10 - test := &gappedSnapshotTest{ - snapshotTestBasic: snapshotTestBasic{ - chainBlocks: 8, - snapshotBlock: 0, - commitBlock: 0, - expCanonicalBlocks: 10, - expHeadHeader: 10, - expHeadFastBlock: 10, - expHeadBlock: 10, - expSnapshotBottom: 10, // Rebuilt snapshot from the latest HEAD - }, - gapped: 2, + for _, scheme := range []string{rawdb.HashScheme, rawdb.PathScheme} { + test := &gappedSnapshotTest{ + snapshotTestBasic: snapshotTestBasic{ + scheme: scheme, + chainBlocks: 8, + snapshotBlock: 0, + commitBlock: 0, + expCanonicalBlocks: 10, + expHeadHeader: 10, + expHeadFastBlock: 10, + expHeadBlock: 10, + expSnapshotBottom: 10, // Rebuilt snapshot from the latest HEAD + }, + gapped: 2, + } + test.test(t) + test.teardown() } - test.test(t) - test.teardown() }   // Tests the Geth was running with snapshot enabled and resetHead is applied. @@ -625,21 +651,24 @@ // Expected head header : C4 // Expected head fast block: C4 // Expected head block : C4 // Expected snapshot disk : G - test := &setHeadSnapshotTest{ - snapshotTestBasic: snapshotTestBasic{ - chainBlocks: 8, - snapshotBlock: 0, - commitBlock: 0, - expCanonicalBlocks: 4, - expHeadHeader: 4, - expHeadFastBlock: 4, - expHeadBlock: 4, - expSnapshotBottom: 0, // The initial disk layer is built from the genesis - }, - setHead: 4, + for _, scheme := range []string{rawdb.HashScheme, rawdb.PathScheme} { + test := &setHeadSnapshotTest{ + snapshotTestBasic: snapshotTestBasic{ + scheme: scheme, + chainBlocks: 8, + snapshotBlock: 0, + commitBlock: 0, + expCanonicalBlocks: 4, + expHeadHeader: 4, + expHeadFastBlock: 4, + expHeadBlock: 4, + expSnapshotBottom: 0, // The initial disk layer is built from the genesis + }, + setHead: 4, + } + test.test(t) + test.teardown() } - test.test(t) - test.teardown() }   // Tests the Geth was running with a complete snapshot and then imports a few @@ -663,19 +692,22 @@ // Expected head header : C10 // Expected head fast block: C10 // Expected head block : C8 // Expected snapshot disk : C10 - test := &wipeCrashSnapshotTest{ - snapshotTestBasic: snapshotTestBasic{ - chainBlocks: 8, - snapshotBlock: 4, - commitBlock: 0, - expCanonicalBlocks: 10, - expHeadHeader: 10, - expHeadFastBlock: 10, - expHeadBlock: 10, - expSnapshotBottom: 10, - }, - newBlocks: 2, + for _, scheme := range []string{rawdb.HashScheme, rawdb.PathScheme} { + test := &wipeCrashSnapshotTest{ + snapshotTestBasic: snapshotTestBasic{ + scheme: scheme, + chainBlocks: 8, + snapshotBlock: 4, + commitBlock: 0, + expCanonicalBlocks: 10, + expHeadHeader: 10, + expHeadFastBlock: 10, + expHeadBlock: 10, + expSnapshotBottom: 10, + }, + newBlocks: 2, + } + test.test(t) + test.teardown() } - test.test(t) - test.teardown() }
diff --git ethereum/go-ethereum/core/blockchain_sethead_test.go taikoxyz/taiko-geth/core/blockchain_sethead_test.go index 9dc350db849e4d8d08c680c1b497ccae235f2b9b..fa739f924f5be7671966d06be47dd79b50bf68f9 100644 --- ethereum/go-ethereum/core/blockchain_sethead_test.go +++ taikoxyz/taiko-geth/core/blockchain_sethead_test.go @@ -22,6 +22,7 @@ import ( "fmt" "math/big" + "path" "strings" "testing" "time" @@ -29,9 +30,13 @@ "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/consensus/ethash" "github.com/ethereum/go-ethereum/core/rawdb" + "github.com/ethereum/go-ethereum/core/state" "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/core/vm" "github.com/ethereum/go-ethereum/params" + "github.com/ethereum/go-ethereum/trie" + "github.com/ethereum/go-ethereum/trie/triedb/hashdb" + "github.com/ethereum/go-ethereum/trie/triedb/pathdb" )   // rewindTest is a test case for chain rollback upon user request. @@ -1949,16 +1954,24 @@ }, snapshots) }   func testSetHead(t *testing.T, tt *rewindTest, snapshots bool) { + for _, scheme := range []string{rawdb.HashScheme, rawdb.PathScheme} { + testSetHeadWithScheme(t, tt, snapshots, scheme) + } +} + +func testSetHeadWithScheme(t *testing.T, tt *rewindTest, snapshots bool, scheme string) { // It's hard to follow the test case, visualize the input // log.Root().SetHandler(log.LvlFilterHandler(log.LvlTrace, log.StreamHandler(os.Stderr, log.TerminalFormat(true)))) // fmt.Println(tt.dump(false))   // Create a temporary persistent database datadir := t.TempDir() + ancient := path.Join(datadir, "ancient")   db, err := rawdb.Open(rawdb.OpenOptions{ Directory: datadir, - AncientsDirectory: datadir, + AncientsDirectory: ancient, + Ephemeral: true, }) if err != nil { t.Fatalf("Failed to create persistent database: %v", err) @@ -1977,6 +1990,7 @@ TrieCleanLimit: 256, TrieDirtyLimit: 256, TrieTimeLimit: 5 * time.Minute, SnapshotLimit: 0, // Disable snapshot + StateScheme: scheme, } ) if snapshots { @@ -2007,7 +2021,7 @@ if _, err := chain.InsertChain(canonblocks[:tt.commitBlock]); err != nil { t.Fatalf("Failed to import canonical chain start: %v", err) } if tt.commitBlock > 0 { - chain.stateCache.TrieDB().Commit(canonblocks[tt.commitBlock-1].Root(), false) + chain.triedb.Commit(canonblocks[tt.commitBlock-1].Root(), false) if snapshots { if err := chain.snaps.Cap(canonblocks[tt.commitBlock-1].Root(), 0); err != nil { t.Fatalf("Failed to flatten snapshots: %v", err) @@ -2017,13 +2031,17 @@ } if _, err := chain.InsertChain(canonblocks[tt.commitBlock:]); err != nil { t.Fatalf("Failed to import canonical chain tail: %v", err) } - // Manually dereference anything not committed to not have to work with 128+ tries - for _, block := range sideblocks { - chain.stateCache.TrieDB().Dereference(block.Root()) - } - for _, block := range canonblocks { - chain.stateCache.TrieDB().Dereference(block.Root()) + // Reopen the trie database without persisting in-memory dirty nodes. + chain.triedb.Close() + dbconfig := &trie.Config{} + if scheme == rawdb.PathScheme { + dbconfig.PathDB = pathdb.Defaults + } else { + dbconfig.HashDB = hashdb.Defaults } + chain.triedb = trie.NewDatabase(chain.db, dbconfig) + chain.stateCache = state.NewDatabaseWithNodeDB(chain.db, chain.triedb) + // Force run a freeze cycle type freezer interface { Freeze(threshold uint64) error
diff --git ethereum/go-ethereum/core/headerchain_test.go taikoxyz/taiko-geth/core/headerchain_test.go index 08d19f695072730af2d10dad711894846a5e74bd..2c0323e6f74d8711587cefdaec12b161a2f7f1a1 100644 --- ethereum/go-ethereum/core/headerchain_test.go +++ taikoxyz/taiko-geth/core/headerchain_test.go @@ -73,7 +73,7 @@ var ( db = rawdb.NewMemoryDatabase() gspec = &Genesis{BaseFee: big.NewInt(params.InitialBaseFee), Config: params.AllEthashProtocolChanges} ) - gspec.Commit(db, trie.NewDatabase(db)) + gspec.Commit(db, trie.NewDatabase(db, nil)) hc, err := NewHeaderChain(db, gspec.Config, ethash.NewFaker(), func() bool { return false }) if err != nil { t.Fatal(err)
diff --git ethereum/go-ethereum/core/block_validator_test.go taikoxyz/taiko-geth/core/block_validator_test.go index 460eaad21c548686ef75c24cc4467e1c5cc67c57..48bdceff623ac7d21383e52f0ecd28ecb9d40484 100644 --- ethereum/go-ethereum/core/block_validator_test.go +++ taikoxyz/taiko-geth/core/block_validator_test.go @@ -35,6 +35,11 @@ )   // Tests that simple header verification works, for both good and bad blocks. func TestHeaderVerification(t *testing.T) { + testHeaderVerification(t, rawdb.HashScheme) + testHeaderVerification(t, rawdb.PathScheme) +} + +func testHeaderVerification(t *testing.T, scheme string) { // Create a simple chain to verify var ( gspec = &Genesis{Config: params.TestChainConfig} @@ -45,7 +50,7 @@ for i, block := range blocks { headers[i] = block.Header() } // Run the header checker for blocks one-by-one, checking for both valid and invalid nonces - chain, _ := NewBlockChain(rawdb.NewMemoryDatabase(), nil, gspec, nil, ethash.NewFaker(), vm.Config{}, nil, nil) + chain, _ := NewBlockChain(rawdb.NewMemoryDatabase(), DefaultCacheConfigWithScheme(scheme), gspec, nil, ethash.NewFaker(), vm.Config{}, nil, nil) defer chain.Stop()   for i := 0; i < len(blocks); i++ {
diff --git ethereum/go-ethereum/core/blockchain_reader.go taikoxyz/taiko-geth/core/blockchain_reader.go index f9d0e3531f72289bf96ff52823d0451f8e5ac2d7..466a86c144155008b88c5652b5313f44a900263d 100644 --- ethereum/go-ethereum/core/blockchain_reader.go +++ taikoxyz/taiko-geth/core/blockchain_reader.go @@ -293,10 +293,16 @@ } return bc.HasState(block.Root()) }   -// TrieNode retrieves a blob of data associated with a trie node -// either from ephemeral in-memory cache, or from persistent storage. -func (bc *BlockChain) TrieNode(hash common.Hash) ([]byte, error) { - return bc.stateCache.TrieDB().Node(hash) +// stateRecoverable checks if the specified state is recoverable. +// Note, this function assumes the state is not present, because +// state is not treated as recoverable if it's available, thus +// false will be returned in this case. +func (bc *BlockChain) stateRecoverable(root common.Hash) bool { + if bc.triedb.Scheme() == rawdb.HashScheme { + return false + } + result, _ := bc.triedb.Recoverable(root) + return result }   // ContractCodeWithPrefix retrieves a blob of data associated with a contract
diff --git ethereum/go-ethereum/core/state_processor_test.go taikoxyz/taiko-geth/core/state_processor_test.go index b4482acf35bac02a772799c01464d1c6330d6df0..6c6ef5adfd4358bda235938edb29421dd3e1e207 100644 --- ethereum/go-ethereum/core/state_processor_test.go +++ taikoxyz/taiko-geth/core/state_processor_test.go @@ -132,7 +132,7 @@ tooBigInitCode = [params.MaxInitCodeSize + 1]byte{} )   defer blockchain.Stop() - bigNumber := new(big.Int).SetBytes(common.FromHex("0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff")) + bigNumber := new(big.Int).SetBytes(common.MaxHash.Bytes()) tooBigNumber := new(big.Int).Set(bigNumber) tooBigNumber.Add(tooBigNumber, common.Big1) for i, tt := range []struct { @@ -410,6 +410,9 @@ excess := eip4844.CalcExcessBlobGas(pExcess, pUsed) used := uint64(nBlobs * params.BlobTxBlobGasPerBlob) header.ExcessBlobGas = &excess header.BlobGasUsed = &used + + beaconRoot := common.HexToHash("0xbeac00") + header.ParentBeaconRoot = &beaconRoot } // Assemble and return the final block for sealing if config.IsShanghai(header.Number, header.Time) {
diff --git ethereum/go-ethereum/core/blockchain_test.go taikoxyz/taiko-geth/core/blockchain_test.go index 1b4b569575a50891c19e5a40f69aef1e7110a4f9..992f8d168f6adb4355aa15be1dcd91b1ebc1b142 100644 --- ethereum/go-ethereum/core/blockchain_test.go +++ taikoxyz/taiko-geth/core/blockchain_test.go @@ -52,7 +52,7 @@ // newCanonical creates a chain database, and injects a deterministic canonical // chain. Depending on the full flag, if creates either a full block chain or a // header only chain. The database and genesis specification for block generation // are also returned in case more test blocks are needed later. -func newCanonical(engine consensus.Engine, n int, full bool) (ethdb.Database, *Genesis, *BlockChain, error) { +func newCanonical(engine consensus.Engine, n int, full bool, scheme string) (ethdb.Database, *Genesis, *BlockChain, error) { var ( genesis = &Genesis{ BaseFee: big.NewInt(params.InitialBaseFee), @@ -60,7 +60,7 @@ Config: params.AllEthashProtocolChanges, } ) // Initialize a fresh chain with only a genesis block - blockchain, _ := NewBlockChain(rawdb.NewMemoryDatabase(), nil, genesis, nil, engine, vm.Config{}, nil, nil) + blockchain, _ := NewBlockChain(rawdb.NewMemoryDatabase(), DefaultCacheConfigWithScheme(scheme), genesis, nil, engine, vm.Config{}, nil, nil)   // Create and inject the requested chain if n == 0 { @@ -83,9 +83,9 @@ return new(big.Int).Mul(big.NewInt(n), big.NewInt(params.GWei)) }   // Test fork of length N starting from block i -func testFork(t *testing.T, blockchain *BlockChain, i, n int, full bool, comparator func(td1, td2 *big.Int)) { +func testFork(t *testing.T, blockchain *BlockChain, i, n int, full bool, comparator func(td1, td2 *big.Int), scheme string) { // Copy old chain up to #i into a new db - genDb, _, blockchain2, err := newCanonical(ethash.NewFaker(), i, full) + genDb, _, blockchain2, err := newCanonical(ethash.NewFaker(), i, full, scheme) if err != nil { t.Fatal("could not make new canonical in testFork", err) } @@ -198,9 +198,13 @@ blockchain.chainmu.Unlock() } return nil } - func TestLastBlock(t *testing.T) { - genDb, _, blockchain, err := newCanonical(ethash.NewFaker(), 0, true) + testLastBlock(t, rawdb.HashScheme) + testLastBlock(t, rawdb.PathScheme) +} + +func testLastBlock(t *testing.T, scheme string) { + genDb, _, blockchain, err := newCanonical(ethash.NewFaker(), 0, true, scheme) if err != nil { t.Fatalf("failed to create pristine chain: %v", err) } @@ -217,9 +221,9 @@ }   // Test inserts the blocks/headers after the fork choice rule is changed. // The chain is reorged to whatever specified. -func testInsertAfterMerge(t *testing.T, blockchain *BlockChain, i, n int, full bool) { +func testInsertAfterMerge(t *testing.T, blockchain *BlockChain, i, n int, full bool, scheme string) { // Copy old chain up to #i into a new db - genDb, _, blockchain2, err := newCanonical(ethash.NewFaker(), i, full) + genDb, _, blockchain2, err := newCanonical(ethash.NewFaker(), i, full, scheme) if err != nil { t.Fatal("could not make new canonical in testFork", err) } @@ -266,14 +270,20 @@ }   // Tests that given a starting canonical chain of a given size, it can be extended // with various length chains. -func TestExtendCanonicalHeaders(t *testing.T) { testExtendCanonical(t, false) } -func TestExtendCanonicalBlocks(t *testing.T) { testExtendCanonical(t, true) } +func TestExtendCanonicalHeaders(t *testing.T) { + testExtendCanonical(t, false, rawdb.HashScheme) + testExtendCanonical(t, false, rawdb.PathScheme) +} +func TestExtendCanonicalBlocks(t *testing.T) { + testExtendCanonical(t, true, rawdb.HashScheme) + testExtendCanonical(t, true, rawdb.PathScheme) +}   -func testExtendCanonical(t *testing.T, full bool) { +func testExtendCanonical(t *testing.T, full bool, scheme string) { length := 5   // Make first chain starting from genesis - _, _, processor, err := newCanonical(ethash.NewFaker(), length, full) + _, _, processor, err := newCanonical(ethash.NewFaker(), length, full, scheme) if err != nil { t.Fatalf("failed to make new canonical chain: %v", err) } @@ -286,41 +296,53 @@ t.Errorf("total difficulty mismatch: have %v, expected more than %v", td2, td1) } } // Start fork from current height - testFork(t, processor, length, 1, full, better) - testFork(t, processor, length, 2, full, better) - testFork(t, processor, length, 5, full, better) - testFork(t, processor, length, 10, full, better) + testFork(t, processor, length, 1, full, better, scheme) + testFork(t, processor, length, 2, full, better, scheme) + testFork(t, processor, length, 5, full, better, scheme) + testFork(t, processor, length, 10, full, better, scheme) }   // Tests that given a starting canonical chain of a given size, it can be extended // with various length chains. -func TestExtendCanonicalHeadersAfterMerge(t *testing.T) { testExtendCanonicalAfterMerge(t, false) } -func TestExtendCanonicalBlocksAfterMerge(t *testing.T) { testExtendCanonicalAfterMerge(t, true) } +func TestExtendCanonicalHeadersAfterMerge(t *testing.T) { + testExtendCanonicalAfterMerge(t, false, rawdb.HashScheme) + testExtendCanonicalAfterMerge(t, false, rawdb.PathScheme) +} +func TestExtendCanonicalBlocksAfterMerge(t *testing.T) { + testExtendCanonicalAfterMerge(t, true, rawdb.HashScheme) + testExtendCanonicalAfterMerge(t, true, rawdb.PathScheme) +}   -func testExtendCanonicalAfterMerge(t *testing.T, full bool) { +func testExtendCanonicalAfterMerge(t *testing.T, full bool, scheme string) { length := 5   // Make first chain starting from genesis - _, _, processor, err := newCanonical(ethash.NewFaker(), length, full) + _, _, processor, err := newCanonical(ethash.NewFaker(), length, full, scheme) if err != nil { t.Fatalf("failed to make new canonical chain: %v", err) } defer processor.Stop()   - testInsertAfterMerge(t, processor, length, 1, full) - testInsertAfterMerge(t, processor, length, 10, full) + testInsertAfterMerge(t, processor, length, 1, full, scheme) + testInsertAfterMerge(t, processor, length, 10, full, scheme) }   // Tests that given a starting canonical chain of a given size, creating shorter // forks do not take canonical ownership. -func TestShorterForkHeaders(t *testing.T) { testShorterFork(t, false) } -func TestShorterForkBlocks(t *testing.T) { testShorterFork(t, true) } +func TestShorterForkHeaders(t *testing.T) { + testShorterFork(t, false, rawdb.HashScheme) + testShorterFork(t, false, rawdb.PathScheme) +} +func TestShorterForkBlocks(t *testing.T) { + testShorterFork(t, true, rawdb.HashScheme) + testShorterFork(t, true, rawdb.PathScheme) +}   -func testShorterFork(t *testing.T, full bool) { +func testShorterFork(t *testing.T, full bool, scheme string) { length := 10   // Make first chain starting from genesis - _, _, processor, err := newCanonical(ethash.NewFaker(), length, full) + _, _, processor, err := newCanonical(ethash.NewFaker(), length, full, scheme) if err != nil { t.Fatalf("failed to make new canonical chain: %v", err) } @@ -333,93 +355,117 @@ t.Errorf("total difficulty mismatch: have %v, expected less than %v", td2, td1) } } // Sum of numbers must be less than `length` for this to be a shorter fork - testFork(t, processor, 0, 3, full, worse) - testFork(t, processor, 0, 7, full, worse) - testFork(t, processor, 1, 1, full, worse) - testFork(t, processor, 1, 7, full, worse) - testFork(t, processor, 5, 3, full, worse) - testFork(t, processor, 5, 4, full, worse) + testFork(t, processor, 0, 3, full, worse, scheme) + testFork(t, processor, 0, 7, full, worse, scheme) + testFork(t, processor, 1, 1, full, worse, scheme) + testFork(t, processor, 1, 7, full, worse, scheme) + testFork(t, processor, 5, 3, full, worse, scheme) + testFork(t, processor, 5, 4, full, worse, scheme) }   // Tests that given a starting canonical chain of a given size, creating shorter // forks do not take canonical ownership. -func TestShorterForkHeadersAfterMerge(t *testing.T) { testShorterForkAfterMerge(t, false) } -func TestShorterForkBlocksAfterMerge(t *testing.T) { testShorterForkAfterMerge(t, true) } +func TestShorterForkHeadersAfterMerge(t *testing.T) { + testShorterForkAfterMerge(t, false, rawdb.HashScheme) + testShorterForkAfterMerge(t, false, rawdb.PathScheme) +} +func TestShorterForkBlocksAfterMerge(t *testing.T) { + testShorterForkAfterMerge(t, true, rawdb.HashScheme) + testShorterForkAfterMerge(t, true, rawdb.PathScheme) +}   -func testShorterForkAfterMerge(t *testing.T, full bool) { +func testShorterForkAfterMerge(t *testing.T, full bool, scheme string) { length := 10   // Make first chain starting from genesis - _, _, processor, err := newCanonical(ethash.NewFaker(), length, full) + _, _, processor, err := newCanonical(ethash.NewFaker(), length, full, scheme) if err != nil { t.Fatalf("failed to make new canonical chain: %v", err) } defer processor.Stop()   - testInsertAfterMerge(t, processor, 0, 3, full) - testInsertAfterMerge(t, processor, 0, 7, full) - testInsertAfterMerge(t, processor, 1, 1, full) - testInsertAfterMerge(t, processor, 1, 7, full) - testInsertAfterMerge(t, processor, 5, 3, full) - testInsertAfterMerge(t, processor, 5, 4, full) + testInsertAfterMerge(t, processor, 0, 3, full, scheme) + testInsertAfterMerge(t, processor, 0, 7, full, scheme) + testInsertAfterMerge(t, processor, 1, 1, full, scheme) + testInsertAfterMerge(t, processor, 1, 7, full, scheme) + testInsertAfterMerge(t, processor, 5, 3, full, scheme) + testInsertAfterMerge(t, processor, 5, 4, full, scheme) }   // Tests that given a starting canonical chain of a given size, creating longer // forks do take canonical ownership. -func TestLongerForkHeaders(t *testing.T) { testLongerFork(t, false) } -func TestLongerForkBlocks(t *testing.T) { testLongerFork(t, true) } +func TestLongerForkHeaders(t *testing.T) { + testLongerFork(t, false, rawdb.HashScheme) + testLongerFork(t, false, rawdb.PathScheme) +} +func TestLongerForkBlocks(t *testing.T) { + testLongerFork(t, true, rawdb.HashScheme) + testLongerFork(t, true, rawdb.PathScheme) +}   -func testLongerFork(t *testing.T, full bool) { +func testLongerFork(t *testing.T, full bool, scheme string) { length := 10   // Make first chain starting from genesis - _, _, processor, err := newCanonical(ethash.NewFaker(), length, full) + _, _, processor, err := newCanonical(ethash.NewFaker(), length, full, scheme) if err != nil { t.Fatalf("failed to make new canonical chain: %v", err) } defer processor.Stop()   - testInsertAfterMerge(t, processor, 0, 11, full) - testInsertAfterMerge(t, processor, 0, 15, full) - testInsertAfterMerge(t, processor, 1, 10, full) - testInsertAfterMerge(t, processor, 1, 12, full) - testInsertAfterMerge(t, processor, 5, 6, full) - testInsertAfterMerge(t, processor, 5, 8, full) + testInsertAfterMerge(t, processor, 0, 11, full, scheme) + testInsertAfterMerge(t, processor, 0, 15, full, scheme) + testInsertAfterMerge(t, processor, 1, 10, full, scheme) + testInsertAfterMerge(t, processor, 1, 12, full, scheme) + testInsertAfterMerge(t, processor, 5, 6, full, scheme) + testInsertAfterMerge(t, processor, 5, 8, full, scheme) }   // Tests that given a starting canonical chain of a given size, creating longer // forks do take canonical ownership. -func TestLongerForkHeadersAfterMerge(t *testing.T) { testLongerForkAfterMerge(t, false) } -func TestLongerForkBlocksAfterMerge(t *testing.T) { testLongerForkAfterMerge(t, true) } +func TestLongerForkHeadersAfterMerge(t *testing.T) { + testLongerForkAfterMerge(t, false, rawdb.HashScheme) + testLongerForkAfterMerge(t, false, rawdb.PathScheme) +} +func TestLongerForkBlocksAfterMerge(t *testing.T) { + testLongerForkAfterMerge(t, true, rawdb.HashScheme) + testLongerForkAfterMerge(t, true, rawdb.PathScheme) +}   -func testLongerForkAfterMerge(t *testing.T, full bool) { +func testLongerForkAfterMerge(t *testing.T, full bool, scheme string) { length := 10   // Make first chain starting from genesis - _, _, processor, err := newCanonical(ethash.NewFaker(), length, full) + _, _, processor, err := newCanonical(ethash.NewFaker(), length, full, scheme) if err != nil { t.Fatalf("failed to make new canonical chain: %v", err) } defer processor.Stop()   - testInsertAfterMerge(t, processor, 0, 11, full) - testInsertAfterMerge(t, processor, 0, 15, full) - testInsertAfterMerge(t, processor, 1, 10, full) - testInsertAfterMerge(t, processor, 1, 12, full) - testInsertAfterMerge(t, processor, 5, 6, full) - testInsertAfterMerge(t, processor, 5, 8, full) + testInsertAfterMerge(t, processor, 0, 11, full, scheme) + testInsertAfterMerge(t, processor, 0, 15, full, scheme) + testInsertAfterMerge(t, processor, 1, 10, full, scheme) + testInsertAfterMerge(t, processor, 1, 12, full, scheme) + testInsertAfterMerge(t, processor, 5, 6, full, scheme) + testInsertAfterMerge(t, processor, 5, 8, full, scheme) }   // Tests that given a starting canonical chain of a given size, creating equal // forks do take canonical ownership. -func TestEqualForkHeaders(t *testing.T) { testEqualFork(t, false) } -func TestEqualForkBlocks(t *testing.T) { testEqualFork(t, true) } +func TestEqualForkHeaders(t *testing.T) { + testEqualFork(t, false, rawdb.HashScheme) + testEqualFork(t, false, rawdb.PathScheme) +} +func TestEqualForkBlocks(t *testing.T) { + testEqualFork(t, true, rawdb.HashScheme) + testEqualFork(t, true, rawdb.PathScheme) +}   -func testEqualFork(t *testing.T, full bool) { +func testEqualFork(t *testing.T, full bool, scheme string) { length := 10   // Make first chain starting from genesis - _, _, processor, err := newCanonical(ethash.NewFaker(), length, full) + _, _, processor, err := newCanonical(ethash.NewFaker(), length, full, scheme) if err != nil { t.Fatalf("failed to make new canonical chain: %v", err) } @@ -432,44 +478,56 @@ t.Errorf("total difficulty mismatch: have %v, want %v", td2, td1) } } // Sum of numbers must be equal to `length` for this to be an equal fork - testFork(t, processor, 0, 10, full, equal) - testFork(t, processor, 1, 9, full, equal) - testFork(t, processor, 2, 8, full, equal) - testFork(t, processor, 5, 5, full, equal) - testFork(t, processor, 6, 4, full, equal) - testFork(t, processor, 9, 1, full, equal) + testFork(t, processor, 0, 10, full, equal, scheme) + testFork(t, processor, 1, 9, full, equal, scheme) + testFork(t, processor, 2, 8, full, equal, scheme) + testFork(t, processor, 5, 5, full, equal, scheme) + testFork(t, processor, 6, 4, full, equal, scheme) + testFork(t, processor, 9, 1, full, equal, scheme) }   // Tests that given a starting canonical chain of a given size, creating equal // forks do take canonical ownership. -func TestEqualForkHeadersAfterMerge(t *testing.T) { testEqualForkAfterMerge(t, false) } -func TestEqualForkBlocksAfterMerge(t *testing.T) { testEqualForkAfterMerge(t, true) } +func TestEqualForkHeadersAfterMerge(t *testing.T) { + testEqualForkAfterMerge(t, false, rawdb.HashScheme) + testEqualForkAfterMerge(t, false, rawdb.PathScheme) +} +func TestEqualForkBlocksAfterMerge(t *testing.T) { + testEqualForkAfterMerge(t, true, rawdb.HashScheme) + testEqualForkAfterMerge(t, true, rawdb.PathScheme) +}   -func testEqualForkAfterMerge(t *testing.T, full bool) { +func testEqualForkAfterMerge(t *testing.T, full bool, scheme string) { length := 10   // Make first chain starting from genesis - _, _, processor, err := newCanonical(ethash.NewFaker(), length, full) + _, _, processor, err := newCanonical(ethash.NewFaker(), length, full, scheme) if err != nil { t.Fatalf("failed to make new canonical chain: %v", err) } defer processor.Stop()   - testInsertAfterMerge(t, processor, 0, 10, full) - testInsertAfterMerge(t, processor, 1, 9, full) - testInsertAfterMerge(t, processor, 2, 8, full) - testInsertAfterMerge(t, processor, 5, 5, full) - testInsertAfterMerge(t, processor, 6, 4, full) - testInsertAfterMerge(t, processor, 9, 1, full) + testInsertAfterMerge(t, processor, 0, 10, full, scheme) + testInsertAfterMerge(t, processor, 1, 9, full, scheme) + testInsertAfterMerge(t, processor, 2, 8, full, scheme) + testInsertAfterMerge(t, processor, 5, 5, full, scheme) + testInsertAfterMerge(t, processor, 6, 4, full, scheme) + testInsertAfterMerge(t, processor, 9, 1, full, scheme) }   // Tests that chains missing links do not get accepted by the processor. -func TestBrokenHeaderChain(t *testing.T) { testBrokenChain(t, false) } -func TestBrokenBlockChain(t *testing.T) { testBrokenChain(t, true) } +func TestBrokenHeaderChain(t *testing.T) { + testBrokenChain(t, false, rawdb.HashScheme) + testBrokenChain(t, false, rawdb.PathScheme) +} +func TestBrokenBlockChain(t *testing.T) { + testBrokenChain(t, true, rawdb.HashScheme) + testBrokenChain(t, true, rawdb.PathScheme) +}   -func testBrokenChain(t *testing.T, full bool) { +func testBrokenChain(t *testing.T, full bool, scheme string) { // Make chain starting from genesis - genDb, _, blockchain, err := newCanonical(ethash.NewFaker(), 10, full) + genDb, _, blockchain, err := newCanonical(ethash.NewFaker(), 10, full, scheme) if err != nil { t.Fatalf("failed to make new canonical chain: %v", err) } @@ -491,19 +549,31 @@ }   // Tests that reorganising a long difficult chain after a short easy one // overwrites the canonical numbers and links in the database. -func TestReorgLongHeaders(t *testing.T) { testReorgLong(t, false) } -func TestReorgLongBlocks(t *testing.T) { testReorgLong(t, true) } +func TestReorgLongHeaders(t *testing.T) { + testReorgLong(t, false, rawdb.HashScheme) + testReorgLong(t, false, rawdb.PathScheme) +} +func TestReorgLongBlocks(t *testing.T) { + testReorgLong(t, true, rawdb.HashScheme) + testReorgLong(t, true, rawdb.PathScheme) +}   -func testReorgLong(t *testing.T, full bool) { - testReorg(t, []int64{0, 0, -9}, []int64{0, 0, 0, -9}, 393280+params.GenesisDifficulty.Int64(), full) +func testReorgLong(t *testing.T, full bool, scheme string) { + testReorg(t, []int64{0, 0, -9}, []int64{0, 0, 0, -9}, 393280+params.GenesisDifficulty.Int64(), full, scheme) }   // Tests that reorganising a short difficult chain after a long easy one // overwrites the canonical numbers and links in the database. -func TestReorgShortHeaders(t *testing.T) { testReorgShort(t, false) } -func TestReorgShortBlocks(t *testing.T) { testReorgShort(t, true) } +func TestReorgShortHeaders(t *testing.T) { + testReorgShort(t, false, rawdb.HashScheme) + testReorgShort(t, false, rawdb.PathScheme) +} +func TestReorgShortBlocks(t *testing.T) { + testReorgShort(t, true, rawdb.HashScheme) + testReorgShort(t, true, rawdb.PathScheme) +}   -func testReorgShort(t *testing.T, full bool) { +func testReorgShort(t *testing.T, full bool, scheme string) { // Create a long easy chain vs. a short heavy one. Due to difficulty adjustment // we need a fairly long chain of blocks with different difficulties for a short // one to become heavier than a long one. The 96 is an empirical value. @@ -515,12 +585,12 @@ diff := make([]int64, len(easy)-1) for i := 0; i < len(diff); i++ { diff[i] = -9 } - testReorg(t, easy, diff, 12615120+params.GenesisDifficulty.Int64(), full) + testReorg(t, easy, diff, 12615120+params.GenesisDifficulty.Int64(), full, scheme) }   -func testReorg(t *testing.T, first, second []int64, td int64, full bool) { +func testReorg(t *testing.T, first, second []int64, td int64, full bool, scheme string) { // Create a pristine chain and database - genDb, _, blockchain, err := newCanonical(ethash.NewFaker(), 0, full) + genDb, _, blockchain, err := newCanonical(ethash.NewFaker(), 0, full, scheme) if err != nil { t.Fatalf("failed to create pristine chain: %v", err) } @@ -588,12 +658,18 @@ } }   // Tests that the insertion functions detect banned hashes. -func TestBadHeaderHashes(t *testing.T) { testBadHashes(t, false) } -func TestBadBlockHashes(t *testing.T) { testBadHashes(t, true) } +func TestBadHeaderHashes(t *testing.T) { + testBadHashes(t, false, rawdb.HashScheme) + testBadHashes(t, false, rawdb.PathScheme) +} +func TestBadBlockHashes(t *testing.T) { + testBadHashes(t, true, rawdb.HashScheme) + testBadHashes(t, true, rawdb.PathScheme) +}   -func testBadHashes(t *testing.T, full bool) { +func testBadHashes(t *testing.T, full bool, scheme string) { // Create a pristine chain and database - genDb, _, blockchain, err := newCanonical(ethash.NewFaker(), 0, full) + genDb, _, blockchain, err := newCanonical(ethash.NewFaker(), 0, full, scheme) if err != nil { t.Fatalf("failed to create pristine chain: %v", err) } @@ -622,12 +698,18 @@ }   // Tests that bad hashes are detected on boot, and the chain rolled back to a // good state prior to the bad hash. -func TestReorgBadHeaderHashes(t *testing.T) { testReorgBadHashes(t, false) } -func TestReorgBadBlockHashes(t *testing.T) { testReorgBadHashes(t, true) } +func TestReorgBadHeaderHashes(t *testing.T) { + testReorgBadHashes(t, false, rawdb.HashScheme) + testReorgBadHashes(t, false, rawdb.PathScheme) +} +func TestReorgBadBlockHashes(t *testing.T) { + testReorgBadHashes(t, true, rawdb.HashScheme) + testReorgBadHashes(t, true, rawdb.PathScheme) +}   -func testReorgBadHashes(t *testing.T, full bool) { +func testReorgBadHashes(t *testing.T, full bool, scheme string) { // Create a pristine chain and database - genDb, gspec, blockchain, err := newCanonical(ethash.NewFaker(), 0, full) + genDb, gspec, blockchain, err := newCanonical(ethash.NewFaker(), 0, full, scheme) if err != nil { t.Fatalf("failed to create pristine chain: %v", err) } @@ -657,7 +739,7 @@ } blockchain.Stop()   // Create a new BlockChain and check that it rolled back the state. - ncm, err := NewBlockChain(blockchain.db, nil, gspec, nil, ethash.NewFaker(), vm.Config{}, nil, nil) + ncm, err := NewBlockChain(blockchain.db, DefaultCacheConfigWithScheme(scheme), gspec, nil, ethash.NewFaker(), vm.Config{}, nil, nil) if err != nil { t.Fatalf("failed to create new chain manager: %v", err) } @@ -677,13 +759,19 @@ ncm.Stop() }   // Tests chain insertions in the face of one entity containing an invalid nonce. -func TestHeadersInsertNonceError(t *testing.T) { testInsertNonceError(t, false) } -func TestBlocksInsertNonceError(t *testing.T) { testInsertNonceError(t, true) } +func TestHeadersInsertNonceError(t *testing.T) { + testInsertNonceError(t, false, rawdb.HashScheme) + testInsertNonceError(t, false, rawdb.PathScheme) +} +func TestBlocksInsertNonceError(t *testing.T) { + testInsertNonceError(t, true, rawdb.HashScheme) + testInsertNonceError(t, true, rawdb.PathScheme) +}   -func testInsertNonceError(t *testing.T, full bool) { +func testInsertNonceError(t *testing.T, full bool, scheme string) { doTest := func(i int) { // Create a pristine chain and database - genDb, _, blockchain, err := newCanonical(ethash.NewFaker(), 0, full) + genDb, _, blockchain, err := newCanonical(ethash.NewFaker(), 0, full, scheme) if err != nil { t.Fatalf("failed to create pristine chain: %v", err) } @@ -738,6 +826,11 @@ // Tests that fast importing a block chain produces the same chain data as the // classical full block processing. func TestFastVsFullChains(t *testing.T) { + testFastVsFullChains(t, rawdb.HashScheme) + testFastVsFullChains(t, rawdb.PathScheme) +} + +func testFastVsFullChains(t *testing.T, scheme string) { // Configure and generate a sample block chain var ( key, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291") @@ -770,7 +863,7 @@ } }) // Import the chain as an archive node for the comparison baseline archiveDb := rawdb.NewMemoryDatabase() - archive, _ := NewBlockChain(archiveDb, nil, gspec, nil, ethash.NewFaker(), vm.Config{}, nil, nil) + archive, _ := NewBlockChain(archiveDb, DefaultCacheConfigWithScheme(scheme), gspec, nil, ethash.NewFaker(), vm.Config{}, nil, nil) defer archive.Stop()   if n, err := archive.InsertChain(blocks); err != nil { @@ -778,7 +871,7 @@ t.Fatalf("failed to process block %d: %v", n, err) } // Fast import the chain as a non-archive node to test fastDb := rawdb.NewMemoryDatabase() - fast, _ := NewBlockChain(fastDb, nil, gspec, nil, ethash.NewFaker(), vm.Config{}, nil, nil) + fast, _ := NewBlockChain(fastDb, DefaultCacheConfigWithScheme(scheme), gspec, nil, ethash.NewFaker(), vm.Config{}, nil, nil) defer fast.Stop()   headers := make([]*types.Header, len(blocks)) @@ -797,7 +890,8 @@ if err != nil { t.Fatalf("failed to create temp freezer db: %v", err) } defer ancientDb.Close() - ancient, _ := NewBlockChain(ancientDb, nil, gspec, nil, ethash.NewFaker(), vm.Config{}, nil, nil) + + ancient, _ := NewBlockChain(ancientDb, DefaultCacheConfigWithScheme(scheme), gspec, nil, ethash.NewFaker(), vm.Config{}, nil, nil) defer ancient.Stop()   if n, err := ancient.InsertHeaderChain(headers); err != nil { @@ -865,6 +959,11 @@ // Tests that various import methods move the chain head pointers to the correct // positions. func TestLightVsFastVsFullChainHeads(t *testing.T) { + testLightVsFastVsFullChainHeads(t, rawdb.HashScheme) + testLightVsFastVsFullChainHeads(t, rawdb.PathScheme) +} + +func testLightVsFastVsFullChainHeads(t *testing.T, scheme string) { // Configure and generate a sample block chain var ( key, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291") @@ -910,6 +1009,7 @@ defer archiveDb.Close()   archiveCaching := *defaultCacheConfig archiveCaching.TrieDirtyDisabled = true + archiveCaching.StateScheme = scheme   archive, _ := NewBlockChain(archiveDb, &archiveCaching, gspec, nil, ethash.NewFaker(), vm.Config{}, nil, nil) if n, err := archive.InsertChain(blocks); err != nil { @@ -924,7 +1024,7 @@ // Import the chain as a non-archive node and ensure all pointers are updated fastDb := makeDb() defer fastDb.Close() - fast, _ := NewBlockChain(fastDb, nil, gspec, nil, ethash.NewFaker(), vm.Config{}, nil, nil) + fast, _ := NewBlockChain(fastDb, DefaultCacheConfigWithScheme(scheme), gspec, nil, ethash.NewFaker(), vm.Config{}, nil, nil) defer fast.Stop()   headers := make([]*types.Header, len(blocks)) @@ -944,7 +1044,7 @@ // Import the chain as a ancient-first node and ensure all pointers are updated ancientDb := makeDb() defer ancientDb.Close() - ancient, _ := NewBlockChain(ancientDb, nil, gspec, nil, ethash.NewFaker(), vm.Config{}, nil, nil) + ancient, _ := NewBlockChain(ancientDb, DefaultCacheConfigWithScheme(scheme), gspec, nil, ethash.NewFaker(), vm.Config{}, nil, nil) defer ancient.Stop()   if n, err := ancient.InsertHeaderChain(headers); err != nil { @@ -963,7 +1063,7 @@ } // Import the chain as a light node and ensure all pointers are updated lightDb := makeDb() defer lightDb.Close() - light, _ := NewBlockChain(lightDb, nil, gspec, nil, ethash.NewFaker(), vm.Config{}, nil, nil) + light, _ := NewBlockChain(lightDb, DefaultCacheConfigWithScheme(scheme), gspec, nil, ethash.NewFaker(), vm.Config{}, nil, nil) if n, err := light.InsertHeaderChain(headers); err != nil { t.Fatalf("failed to insert header %d: %v", n, err) } @@ -976,6 +1076,11 @@ }   // Tests that chain reorganisations handle transaction removals and reinsertions. func TestChainTxReorgs(t *testing.T) { + testChainTxReorgs(t, rawdb.HashScheme) + testChainTxReorgs(t, rawdb.PathScheme) +} + +func testChainTxReorgs(t *testing.T, scheme string) { var ( key1, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291") key2, _ = crypto.HexToECDSA("8a1f9a8f95be41cd7ccb6168179afb4504aefe388d1e14474d32c45c72ce7b7a") @@ -1031,7 +1136,7 @@ } }) // Import the chain. This runs all block validation rules. db := rawdb.NewMemoryDatabase() - blockchain, _ := NewBlockChain(db, nil, gspec, nil, ethash.NewFaker(), vm.Config{}, nil, nil) + blockchain, _ := NewBlockChain(db, DefaultCacheConfigWithScheme(scheme), gspec, nil, ethash.NewFaker(), vm.Config{}, nil, nil) if i, err := blockchain.InsertChain(chain); err != nil { t.Fatalf("failed to insert original chain[%d]: %v", i, err) } @@ -1090,6 +1195,11 @@ } }   func TestLogReorgs(t *testing.T) { + testLogReorgs(t, rawdb.HashScheme) + testLogReorgs(t, rawdb.PathScheme) +} + +func testLogReorgs(t *testing.T, scheme string) { var ( key1, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291") addr1 = crypto.PubkeyToAddress(key1.PublicKey) @@ -1100,7 +1210,7 @@ gspec = &Genesis{Config: params.TestChainConfig, Alloc: GenesisAlloc{addr1: {Balance: big.NewInt(10000000000000000)}}} signer = types.LatestSigner(gspec.Config) )   - blockchain, _ := NewBlockChain(rawdb.NewMemoryDatabase(), nil, gspec, nil, ethash.NewFaker(), vm.Config{}, nil, nil) + blockchain, _ := NewBlockChain(rawdb.NewMemoryDatabase(), DefaultCacheConfigWithScheme(scheme), gspec, nil, ethash.NewFaker(), vm.Config{}, nil, nil) defer blockchain.Stop()   rmLogsCh := make(chan RemovedLogsEvent) @@ -1145,13 +1255,18 @@ // This test checks that log events and RemovedLogsEvent are sent // when the chain reorganizes. func TestLogRebirth(t *testing.T) { + testLogRebirth(t, rawdb.HashScheme) + testLogRebirth(t, rawdb.PathScheme) +} + +func testLogRebirth(t *testing.T, scheme string) { var ( key1, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291") addr1 = crypto.PubkeyToAddress(key1.PublicKey) gspec = &Genesis{Config: params.TestChainConfig, Alloc: GenesisAlloc{addr1: {Balance: big.NewInt(10000000000000000)}}} signer = types.LatestSigner(gspec.Config) engine = ethash.NewFaker() - blockchain, _ = NewBlockChain(rawdb.NewMemoryDatabase(), nil, gspec, nil, engine, vm.Config{}, nil, nil) + blockchain, _ = NewBlockChain(rawdb.NewMemoryDatabase(), DefaultCacheConfigWithScheme(scheme), gspec, nil, engine, vm.Config{}, nil, nil) ) defer blockchain.Stop()   @@ -1222,12 +1337,17 @@ // This test is a variation of TestLogRebirth. It verifies that log events are emitted // when a side chain containing log events overtakes the canonical chain. func TestSideLogRebirth(t *testing.T) { + testSideLogRebirth(t, rawdb.HashScheme) + testSideLogRebirth(t, rawdb.PathScheme) +} + +func testSideLogRebirth(t *testing.T, scheme string) { var ( key1, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291") addr1 = crypto.PubkeyToAddress(key1.PublicKey) gspec = &Genesis{Config: params.TestChainConfig, Alloc: GenesisAlloc{addr1: {Balance: big.NewInt(10000000000000000)}}} signer = types.LatestSigner(gspec.Config) - blockchain, _ = NewBlockChain(rawdb.NewMemoryDatabase(), nil, gspec, nil, ethash.NewFaker(), vm.Config{}, nil, nil) + blockchain, _ = NewBlockChain(rawdb.NewMemoryDatabase(), DefaultCacheConfigWithScheme(scheme), gspec, nil, ethash.NewFaker(), vm.Config{}, nil, nil) ) defer blockchain.Stop()   @@ -1312,6 +1432,11 @@ } }   func TestReorgSideEvent(t *testing.T) { + testReorgSideEvent(t, rawdb.HashScheme) + testReorgSideEvent(t, rawdb.PathScheme) +} + +func testReorgSideEvent(t *testing.T, scheme string) { var ( key1, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291") addr1 = crypto.PubkeyToAddress(key1.PublicKey) @@ -1321,7 +1446,7 @@ Alloc: GenesisAlloc{addr1: {Balance: big.NewInt(10000000000000000)}}, } signer = types.LatestSigner(gspec.Config) ) - blockchain, _ := NewBlockChain(rawdb.NewMemoryDatabase(), nil, gspec, nil, ethash.NewFaker(), vm.Config{}, nil, nil) + blockchain, _ := NewBlockChain(rawdb.NewMemoryDatabase(), DefaultCacheConfigWithScheme(scheme), gspec, nil, ethash.NewFaker(), vm.Config{}, nil, nil) defer blockchain.Stop()   _, chain, _ := GenerateChainWithGenesis(gspec, ethash.NewFaker(), 3, func(i int, gen *BlockGen) {}) @@ -1392,7 +1517,12 @@ }   // Tests if the canonical block can be fetched from the database during chain insertion. func TestCanonicalBlockRetrieval(t *testing.T) { - _, gspec, blockchain, err := newCanonical(ethash.NewFaker(), 0, true) + testCanonicalBlockRetrieval(t, rawdb.HashScheme) + testCanonicalBlockRetrieval(t, rawdb.PathScheme) +} + +func testCanonicalBlockRetrieval(t *testing.T, scheme string) { + _, gspec, blockchain, err := newCanonical(ethash.NewFaker(), 0, true, scheme) if err != nil { t.Fatalf("failed to create pristine chain: %v", err) } @@ -1436,8 +1566,12 @@ } } pend.Wait() } - func TestEIP155Transition(t *testing.T) { + testEIP155Transition(t, rawdb.HashScheme) + testEIP155Transition(t, rawdb.PathScheme) +} + +func testEIP155Transition(t *testing.T, scheme string) { // Configure and generate a sample block chain var ( key, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291") @@ -1496,7 +1630,7 @@ block.AddTx(tx) } })   - blockchain, _ := NewBlockChain(rawdb.NewMemoryDatabase(), nil, gspec, nil, ethash.NewFaker(), vm.Config{}, nil, nil) + blockchain, _ := NewBlockChain(rawdb.NewMemoryDatabase(), DefaultCacheConfigWithScheme(scheme), gspec, nil, ethash.NewFaker(), vm.Config{}, nil, nil) defer blockchain.Stop()   if _, err := blockchain.InsertChain(blocks); err != nil { @@ -1546,8 +1680,12 @@ if have, want := err, types.ErrInvalidChainId; !errors.Is(have, want) { t.Errorf("have %v, want %v", have, want) } } +func TestEIP161AccountRemoval(t *testing.T) { + testEIP161AccountRemoval(t, rawdb.HashScheme) + testEIP161AccountRemoval(t, rawdb.PathScheme) +}   -func TestEIP161AccountRemoval(t *testing.T) { +func testEIP161AccountRemoval(t *testing.T, scheme string) { // Configure and generate a sample block chain var ( key, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291") @@ -1585,7 +1723,7 @@ } block.AddTx(tx) }) // account must exist pre eip 161 - blockchain, _ := NewBlockChain(rawdb.NewMemoryDatabase(), nil, gspec, nil, ethash.NewFaker(), vm.Config{}, nil, nil) + blockchain, _ := NewBlockChain(rawdb.NewMemoryDatabase(), DefaultCacheConfigWithScheme(scheme), gspec, nil, ethash.NewFaker(), vm.Config{}, nil, nil) defer blockchain.Stop()   if _, err := blockchain.InsertChain(types.Blocks{blocks[0]}); err != nil { @@ -1618,6 +1756,11 @@ // chain return the same latest block/header. // // https://github.com/ethereum/go-ethereum/pull/15941 func TestBlockchainHeaderchainReorgConsistency(t *testing.T) { + testBlockchainHeaderchainReorgConsistency(t, rawdb.HashScheme) + testBlockchainHeaderchainReorgConsistency(t, rawdb.PathScheme) +} + +func testBlockchainHeaderchainReorgConsistency(t *testing.T, scheme string) { // Generate a canonical chain to act as the main dataset engine := ethash.NewFaker() genesis := &Genesis{ @@ -1638,7 +1781,7 @@ forks[i] = fork[0] } // Import the canonical and fork chain side by side, verifying the current block // and current header consistency - chain, err := NewBlockChain(rawdb.NewMemoryDatabase(), nil, genesis, nil, engine, vm.Config{}, nil, nil) + chain, err := NewBlockChain(rawdb.NewMemoryDatabase(), DefaultCacheConfigWithScheme(scheme), genesis, nil, engine, vm.Config{}, nil, nil) if err != nil { t.Fatalf("failed to create tester chain: %v", err) } @@ -1698,10 +1841,10 @@ } } // Dereference all the recent tries and ensure no past trie is left in for i := 0; i < TriesInMemory; i++ { - chain.stateCache.TrieDB().Dereference(blocks[len(blocks)-1-i].Root()) - chain.stateCache.TrieDB().Dereference(forks[len(blocks)-1-i].Root()) + chain.TrieDB().Dereference(blocks[len(blocks)-1-i].Root()) + chain.TrieDB().Dereference(forks[len(blocks)-1-i].Root()) } - if nodes, _ := chain.TrieDB().Size(); nodes > 0 { + if _, nodes, _ := chain.TrieDB().Size(); nodes > 0 { // all memory is returned in the nodes return for hashdb t.Fatalf("stale tries still alive after garbase collection") } } @@ -1709,6 +1852,11 @@ // Tests that doing large reorgs works even if the state associated with the // forking point is not available any more. func TestLargeReorgTrieGC(t *testing.T) { + testLargeReorgTrieGC(t, rawdb.HashScheme) + testLargeReorgTrieGC(t, rawdb.PathScheme) +} + +func testLargeReorgTrieGC(t *testing.T, scheme string) { // Generate the original common chain segment and the two competing forks engine := ethash.NewFaker() genesis := &Genesis{ @@ -1720,7 +1868,10 @@ original, _ := GenerateChain(genesis.Config, shared[len(shared)-1], engine, genDb, 2*TriesInMemory, func(i int, b *BlockGen) { b.SetCoinbase(common.Address{2}) }) competitor, _ := GenerateChain(genesis.Config, shared[len(shared)-1], engine, genDb, 2*TriesInMemory+1, func(i int, b *BlockGen) { b.SetCoinbase(common.Address{3}) })   // Import the shared chain and the original canonical one - chain, err := NewBlockChain(rawdb.NewMemoryDatabase(), nil, genesis, nil, engine, vm.Config{}, nil, nil) + db, _ := rawdb.NewDatabaseWithFreezer(rawdb.NewMemoryDatabase(), t.TempDir(), "", false) + defer db.Close() + + chain, err := NewBlockChain(db, DefaultCacheConfigWithScheme(scheme), genesis, nil, engine, vm.Config{}, nil, nil) if err != nil { t.Fatalf("failed to create tester chain: %v", err) } @@ -1733,7 +1884,7 @@ if _, err := chain.InsertChain(original); err != nil { t.Fatalf("failed to insert original chain: %v", err) } // Ensure that the state associated with the forking point is pruned away - if node, _ := chain.stateCache.TrieDB().Node(shared[len(shared)-1].Root()); node != nil { + if chain.HasState(shared[len(shared)-1].Root()) { t.Fatalf("common-but-old ancestor still cache") } // Import the competitor chain without exceeding the canonical's TD and ensure @@ -1742,7 +1893,7 @@ if _, err := chain.InsertChain(competitor[:len(competitor)-2]); err != nil { t.Fatalf("failed to insert competitor chain: %v", err) } for i, block := range competitor[:len(competitor)-2] { - if node, _ := chain.stateCache.TrieDB().Node(block.Root()); node != nil { + if chain.HasState(block.Root()) { t.Fatalf("competitor %d: low TD chain became processed", i) } } @@ -1751,14 +1902,30 @@ // successfully reprocess all the stashed away blocks. if _, err := chain.InsertChain(competitor[len(competitor)-2:]); err != nil { t.Fatalf("failed to finalize competitor chain: %v", err) } - for i, block := range competitor[:len(competitor)-TriesInMemory] { - if node, _ := chain.stateCache.TrieDB().Node(block.Root()); node != nil { + // In path-based trie database implementation, it will keep 128 diff + 1 disk + // layers, totally 129 latest states available. In hash-based it's 128. + states := TriesInMemory + if scheme == rawdb.PathScheme { + states = states + 1 + } + for i, block := range competitor[:len(competitor)-states] { + if chain.HasState(block.Root()) { + t.Fatalf("competitor %d: unexpected competing chain state", i) + } + } + for i, block := range competitor[len(competitor)-states:] { + if !chain.HasState(block.Root()) { t.Fatalf("competitor %d: competing chain state missing", i) } } }   func TestBlockchainRecovery(t *testing.T) { + testBlockchainRecovery(t, rawdb.HashScheme) + testBlockchainRecovery(t, rawdb.PathScheme) +} + +func testBlockchainRecovery(t *testing.T, scheme string) { // Configure and generate a sample block chain var ( key, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291") @@ -1775,7 +1942,7 @@ if err != nil { t.Fatalf("failed to create temp freezer db: %v", err) } defer ancientDb.Close() - ancient, _ := NewBlockChain(ancientDb, nil, gspec, nil, ethash.NewFaker(), vm.Config{}, nil, nil) + ancient, _ := NewBlockChain(ancientDb, DefaultCacheConfigWithScheme(scheme), gspec, nil, ethash.NewFaker(), vm.Config{}, nil, nil)   headers := make([]*types.Header, len(blocks)) for i, block := range blocks { @@ -1795,7 +1962,7 @@ midBlock := blocks[len(blocks)/2] rawdb.WriteHeadFastBlockHash(ancientDb, midBlock.Hash())   // Reopen broken blockchain again - ancient, _ = NewBlockChain(ancientDb, nil, gspec, nil, ethash.NewFaker(), vm.Config{}, nil, nil) + ancient, _ = NewBlockChain(ancientDb, DefaultCacheConfigWithScheme(scheme), gspec, nil, ethash.NewFaker(), vm.Config{}, nil, nil) defer ancient.Stop() if num := ancient.CurrentBlock().Number.Uint64(); num != 0 { t.Errorf("head block mismatch: have #%v, want #%v", num, 0) @@ -1810,8 +1977,13 @@ }   // This test checks that InsertReceiptChain will roll back correctly when attempting to insert a side chain. func TestInsertReceiptChainRollback(t *testing.T) { + testInsertReceiptChainRollback(t, rawdb.HashScheme) + testInsertReceiptChainRollback(t, rawdb.PathScheme) +} + +func testInsertReceiptChainRollback(t *testing.T, scheme string) { // Generate forked chain. The returned BlockChain object is used to process the side chain blocks. - tmpChain, sideblocks, canonblocks, gspec, err := getLongAndShortChains() + tmpChain, sideblocks, canonblocks, gspec, err := getLongAndShortChains(scheme) if err != nil { t.Fatal(err) } @@ -1842,7 +2014,7 @@ t.Fatalf("failed to create temp freezer db: %v", err) } defer ancientDb.Close()   - ancientChain, _ := NewBlockChain(ancientDb, nil, gspec, nil, ethash.NewFaker(), vm.Config{}, nil, nil) + ancientChain, _ := NewBlockChain(ancientDb, DefaultCacheConfigWithScheme(scheme), gspec, nil, ethash.NewFaker(), vm.Config{}, nil, nil) defer ancientChain.Stop()   // Import the canonical header chain. @@ -1887,6 +2059,11 @@ // Details at: // - https://github.com/ethereum/go-ethereum/issues/18977 // - https://github.com/ethereum/go-ethereum/pull/18988 func TestLowDiffLongChain(t *testing.T) { + testLowDiffLongChain(t, rawdb.HashScheme) + testLowDiffLongChain(t, rawdb.PathScheme) +} + +func testLowDiffLongChain(t *testing.T, scheme string) { // Generate a canonical chain to act as the main dataset engine := ethash.NewFaker() genesis := &Genesis{ @@ -1901,11 +2078,14 @@ b.OffsetTime(-9) })   // Import the canonical chain - chain, err := NewBlockChain(rawdb.NewMemoryDatabase(), nil, genesis, nil, engine, vm.Config{}, nil, nil) + diskdb, _ := rawdb.NewDatabaseWithFreezer(rawdb.NewMemoryDatabase(), t.TempDir(), "", false) + defer diskdb.Close() + + chain, err := NewBlockChain(diskdb, DefaultCacheConfigWithScheme(scheme), genesis, nil, engine, vm.Config{}, nil, nil) if err != nil { t.Fatalf("failed to create tester chain: %v", err) } - defer chain.stopWithoutSaving() + defer chain.Stop()   if n, err := chain.InsertChain(blocks); err != nil { t.Fatalf("block %d: failed to insert into chain: %v", n, err) @@ -2085,11 +2265,20 @@ testSideImport(t, 1, 10, 1) testSideImport(t, 1, -10, 1) }   -func TestInsertKnownHeaders(t *testing.T) { testInsertKnownChainData(t, "headers") } -func TestInsertKnownReceiptChain(t *testing.T) { testInsertKnownChainData(t, "receipts") } -func TestInsertKnownBlocks(t *testing.T) { testInsertKnownChainData(t, "blocks") } +func TestInsertKnownHeaders(t *testing.T) { + testInsertKnownChainData(t, "headers", rawdb.HashScheme) + testInsertKnownChainData(t, "headers", rawdb.PathScheme) +} +func TestInsertKnownReceiptChain(t *testing.T) { + testInsertKnownChainData(t, "receipts", rawdb.HashScheme) + testInsertKnownChainData(t, "receipts", rawdb.PathScheme) +} +func TestInsertKnownBlocks(t *testing.T) { + testInsertKnownChainData(t, "blocks", rawdb.HashScheme) + testInsertKnownChainData(t, "blocks", rawdb.PathScheme) +}   -func testInsertKnownChainData(t *testing.T, typ string) { +func testInsertKnownChainData(t *testing.T, typ string, scheme string) { engine := ethash.NewFaker() genesis := &Genesis{ Config: params.TestChainConfig, @@ -2112,7 +2301,7 @@ t.Fatalf("failed to create temp freezer db: %v", err) } defer chaindb.Close()   - chain, err := NewBlockChain(chaindb, nil, genesis, nil, engine, vm.Config{}, nil, nil) + chain, err := NewBlockChain(chaindb, DefaultCacheConfigWithScheme(scheme), genesis, nil, engine, vm.Config{}, nil, nil) if err != nil { t.Fatalf("failed to create tester chain: %v", err) } @@ -2385,7 +2574,7 @@ asserter(t, blocks2[len(blocks2)-1]) }   // getLongAndShortChains returns two chains: A is longer, B is heavier. -func getLongAndShortChains() (*BlockChain, []*types.Block, []*types.Block, *Genesis, error) { +func getLongAndShortChains(scheme string) (*BlockChain, []*types.Block, []*types.Block, *Genesis, error) { // Generate a canonical chain to act as the main dataset engine := ethash.NewFaker() genesis := &Genesis{ @@ -2397,7 +2586,7 @@ // Offset the time, to keep the difficulty low genDb, longChain, _ := GenerateChainWithGenesis(genesis, engine, 80, func(i int, b *BlockGen) { b.SetCoinbase(common.Address{1}) }) - chain, err := NewBlockChain(rawdb.NewMemoryDatabase(), nil, genesis, nil, engine, vm.Config{}, nil, nil) + chain, err := NewBlockChain(rawdb.NewMemoryDatabase(), DefaultCacheConfigWithScheme(scheme), genesis, nil, engine, vm.Config{}, nil, nil) if err != nil { return nil, nil, nil, nil, fmt.Errorf("failed to create tester chain: %v", err) } @@ -2443,7 +2632,12 @@ // 2. Reorg to shorter but heavier chain [0 ... N ... Y] // 3. Then there should be no canon mapping for the block at height X // 4. The forked block should still be retrievable by hash func TestReorgToShorterRemovesCanonMapping(t *testing.T) { - chain, canonblocks, sideblocks, _, err := getLongAndShortChains() + testReorgToShorterRemovesCanonMapping(t, rawdb.HashScheme) + testReorgToShorterRemovesCanonMapping(t, rawdb.PathScheme) +} + +func testReorgToShorterRemovesCanonMapping(t *testing.T, scheme string) { + chain, canonblocks, sideblocks, _, err := getLongAndShortChains(scheme) if err != nil { t.Fatal(err) } @@ -2481,7 +2675,12 @@ // TestReorgToShorterRemovesCanonMappingHeaderChain is the same scenario // as TestReorgToShorterRemovesCanonMapping, but applied on headerchain // imports -- that is, for fast sync func TestReorgToShorterRemovesCanonMappingHeaderChain(t *testing.T) { - chain, canonblocks, sideblocks, _, err := getLongAndShortChains() + testReorgToShorterRemovesCanonMappingHeaderChain(t, rawdb.HashScheme) + testReorgToShorterRemovesCanonMappingHeaderChain(t, rawdb.PathScheme) +} + +func testReorgToShorterRemovesCanonMappingHeaderChain(t *testing.T, scheme string) { + chain, canonblocks, sideblocks, _, err := getLongAndShortChains(scheme) if err != nil { t.Fatal(err) } @@ -2624,6 +2823,11 @@ } }   func TestSkipStaleTxIndicesInSnapSync(t *testing.T) { + testSkipStaleTxIndicesInSnapSync(t, rawdb.HashScheme) + testSkipStaleTxIndicesInSnapSync(t, rawdb.PathScheme) +} + +func testSkipStaleTxIndicesInSnapSync(t *testing.T, scheme string) { // Configure and generate a sample block chain var ( key, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291") @@ -2682,7 +2886,7 @@ defer ancientDb.Close()   // Import all blocks into ancient db, only HEAD-32 indices are kept. l := uint64(32) - chain, err := NewBlockChain(ancientDb, nil, gspec, nil, ethash.NewFaker(), vm.Config{}, nil, &l) + chain, err := NewBlockChain(ancientDb, DefaultCacheConfigWithScheme(scheme), gspec, nil, ethash.NewFaker(), vm.Config{}, nil, &l) if err != nil { t.Fatalf("failed to create tester chain: %v", err) } @@ -2816,6 +3020,11 @@ // 1. Downloader rollbacks a batch of inserted blocks and exits // 2. Downloader starts to sync again // 3. The blocks fetched are all known and canonical blocks func TestSideImportPrunedBlocks(t *testing.T) { + testSideImportPrunedBlocks(t, rawdb.HashScheme) + testSideImportPrunedBlocks(t, rawdb.PathScheme) +} + +func testSideImportPrunedBlocks(t *testing.T, scheme string) { // Generate a canonical chain to act as the main dataset engine := ethash.NewFaker() genesis := &Genesis{ @@ -2825,7 +3034,7 @@ } // Generate and import the canonical chain _, blocks, _ := GenerateChainWithGenesis(genesis, engine, 2*TriesInMemory, nil)   - chain, err := NewBlockChain(rawdb.NewMemoryDatabase(), nil, genesis, nil, engine, vm.Config{}, nil, nil) + chain, err := NewBlockChain(rawdb.NewMemoryDatabase(), DefaultCacheConfigWithScheme(scheme), genesis, nil, engine, vm.Config{}, nil, nil) if err != nil { t.Fatalf("failed to create tester chain: %v", err) } @@ -2834,15 +3043,20 @@ if n, err := chain.InsertChain(blocks); err != nil { t.Fatalf("block %d: failed to insert into chain: %v", n, err) } - - lastPrunedIndex := len(blocks) - TriesInMemory - 1 + // In path-based trie database implementation, it will keep 128 diff + 1 disk + // layers, totally 129 latest states available. In hash-based it's 128. + states := TriesInMemory + if scheme == rawdb.PathScheme { + states = TriesInMemory + 1 + } + lastPrunedIndex := len(blocks) - states - 1 lastPrunedBlock := blocks[lastPrunedIndex]   // Verify pruning of lastPrunedBlock if chain.HasBlockAndState(lastPrunedBlock.Hash(), lastPrunedBlock.NumberU64()) { t.Errorf("Block %d not pruned", lastPrunedBlock.NumberU64()) } - firstNonPrunedBlock := blocks[len(blocks)-TriesInMemory] + firstNonPrunedBlock := blocks[len(blocks)-states] // Verify firstNonPrunedBlock is not pruned if !chain.HasBlockAndState(firstNonPrunedBlock.Hash(), firstNonPrunedBlock.NumberU64()) { t.Errorf("Block %d pruned", firstNonPrunedBlock.NumberU64()) @@ -2864,6 +3078,11 @@ // The original statedb implementation flushed dirty objects to the tries after // each transaction, so this works ok. The rework accumulated writes in memory // first, but the journal wiped the entire state object on create-revert. func TestDeleteCreateRevert(t *testing.T) { + testDeleteCreateRevert(t, rawdb.HashScheme) + testDeleteCreateRevert(t, rawdb.PathScheme) +} + +func testDeleteCreateRevert(t *testing.T, scheme string) { var ( aa = common.HexToAddress("0x000000000000000000000000000000000000aaaa") bb = common.HexToAddress("0x000000000000000000000000000000000000bbbb") @@ -2915,7 +3134,7 @@ big.NewInt(0), 100000, b.header.BaseFee, nil), types.HomesteadSigner{}, key) b.AddTx(tx) }) // Import the canonical chain - chain, err := NewBlockChain(rawdb.NewMemoryDatabase(), nil, gspec, nil, engine, vm.Config{}, nil, nil) + chain, err := NewBlockChain(rawdb.NewMemoryDatabase(), DefaultCacheConfigWithScheme(scheme), gspec, nil, engine, vm.Config{}, nil, nil) if err != nil { t.Fatalf("failed to create tester chain: %v", err) } @@ -2934,6 +3153,11 @@ // Tx 2: Re-create A, set slots 3 and 4 // Expected outcome is that _all_ slots are cleared from A, due to the selfdestruct, // and then the new slots exist func TestDeleteRecreateSlots(t *testing.T) { + testDeleteRecreateSlots(t, rawdb.HashScheme) + testDeleteRecreateSlots(t, rawdb.PathScheme) +} + +func testDeleteRecreateSlots(t *testing.T, scheme string) { var ( engine = ethash.NewFaker()   @@ -3023,7 +3247,7 @@ big.NewInt(0), 100000, b.header.BaseFee, nil), types.HomesteadSigner{}, key) b.AddTx(tx) }) // Import the canonical chain - chain, err := NewBlockChain(rawdb.NewMemoryDatabase(), nil, gspec, nil, engine, vm.Config{ + chain, err := NewBlockChain(rawdb.NewMemoryDatabase(), DefaultCacheConfigWithScheme(scheme), gspec, nil, engine, vm.Config{ Tracer: logger.NewJSONLogger(nil, os.Stdout), }, nil, nil) if err != nil { @@ -3057,6 +3281,11 @@ // contract with storage, and a recreate of the same contract via a // regular value-transfer // Expected outcome is that _all_ slots are cleared from A func TestDeleteRecreateAccount(t *testing.T) { + testDeleteRecreateAccount(t, rawdb.HashScheme) + testDeleteRecreateAccount(t, rawdb.PathScheme) +} + +func testDeleteRecreateAccount(t *testing.T, scheme string) { var ( engine = ethash.NewFaker()   @@ -3100,7 +3329,7 @@ big.NewInt(1), 100000, b.header.BaseFee, nil), types.HomesteadSigner{}, key) b.AddTx(tx) }) // Import the canonical chain - chain, err := NewBlockChain(rawdb.NewMemoryDatabase(), nil, gspec, nil, engine, vm.Config{ + chain, err := NewBlockChain(rawdb.NewMemoryDatabase(), DefaultCacheConfigWithScheme(scheme), gspec, nil, engine, vm.Config{ Tracer: logger.NewJSONLogger(nil, os.Stdout), }, nil, nil) if err != nil { @@ -3130,6 +3359,11 @@ // Tx 2: Re-create A, set slots 3 and 4 // Expected outcome is that _all_ slots are cleared from A, due to the selfdestruct, // and then the new slots exist func TestDeleteRecreateSlotsAcrossManyBlocks(t *testing.T) { + testDeleteRecreateSlotsAcrossManyBlocks(t, rawdb.HashScheme) + testDeleteRecreateSlotsAcrossManyBlocks(t, rawdb.PathScheme) +} + +func testDeleteRecreateSlotsAcrossManyBlocks(t *testing.T, scheme string) { var ( engine = ethash.NewFaker()   @@ -3270,7 +3504,7 @@ expectations = append(expectations, exp) current = exp }) // Import the canonical chain - chain, err := NewBlockChain(rawdb.NewMemoryDatabase(), nil, gspec, nil, engine, vm.Config{ + chain, err := NewBlockChain(rawdb.NewMemoryDatabase(), DefaultCacheConfigWithScheme(scheme), gspec, nil, engine, vm.Config{ //Debug: true, //Tracer: vm.NewJSONLogger(nil, os.Stdout), }, nil, nil) @@ -3328,7 +3562,14 @@ // The problem being that the snapshotter maintains a destructset, and adds items // to the destructset in case something is created "onto" an existing item. // We need to either roll back the snapDestructs, or not place it into snapDestructs // in the first place. +// + func TestInitThenFailCreateContract(t *testing.T) { + testInitThenFailCreateContract(t, rawdb.HashScheme) + testInitThenFailCreateContract(t, rawdb.PathScheme) +} + +func testInitThenFailCreateContract(t *testing.T, scheme string) { var ( engine = ethash.NewFaker()   @@ -3401,7 +3642,7 @@ nonce++ })   // Import the canonical chain - chain, err := NewBlockChain(rawdb.NewMemoryDatabase(), nil, gspec, nil, engine, vm.Config{ + chain, err := NewBlockChain(rawdb.NewMemoryDatabase(), DefaultCacheConfigWithScheme(scheme), gspec, nil, engine, vm.Config{ //Debug: true, //Tracer: vm.NewJSONLogger(nil, os.Stdout), }, nil, nil) @@ -3439,6 +3680,11 @@ // access list transaction, which specifies a single slot access, and then // checking that the gas usage of a hot SLOAD and a cold SLOAD are calculated // correctly. func TestEIP2718Transition(t *testing.T) { + testEIP2718Transition(t, rawdb.HashScheme) + testEIP2718Transition(t, rawdb.PathScheme) +} + +func testEIP2718Transition(t *testing.T, scheme string) { var ( aa = common.HexToAddress("0x000000000000000000000000000000000000aaaa") engine = ethash.NewFaker() @@ -3486,7 +3732,7 @@ b.AddTx(tx) })   // Import the canonical chain - chain, err := NewBlockChain(rawdb.NewMemoryDatabase(), nil, gspec, nil, engine, vm.Config{}, nil, nil) + chain, err := NewBlockChain(rawdb.NewMemoryDatabase(), DefaultCacheConfigWithScheme(scheme), gspec, nil, engine, vm.Config{}, nil, nil) if err != nil { t.Fatalf("failed to create tester chain: %v", err) } @@ -3516,6 +3762,11 @@ // 5. The coinbase receives only the partially realized tip when // gasFeeCap - gasTipCap < baseFee. // 6. Legacy transaction behave as expected (e.g. gasPrice = gasFeeCap = gasTipCap). func TestEIP1559Transition(t *testing.T) { + testEIP1559Transition(t, rawdb.HashScheme) + testEIP1559Transition(t, rawdb.PathScheme) +} + +func testEIP1559Transition(t *testing.T, scheme string) { var ( aa = common.HexToAddress("0x000000000000000000000000000000000000aaaa") engine = ethash.NewFaker() @@ -3526,8 +3777,9 @@ key2, _ = crypto.HexToECDSA("8a1f9a8f95be41cd7ccb6168179afb4504aefe388d1e14474d32c45c72ce7b7a") addr1 = crypto.PubkeyToAddress(key1.PublicKey) addr2 = crypto.PubkeyToAddress(key2.PublicKey) funds = new(big.Int).Mul(common.Big1, big.NewInt(params.Ether)) + config = *params.AllEthashProtocolChanges gspec = &Genesis{ - Config: params.AllEthashProtocolChanges, + Config: &config, Alloc: GenesisAlloc{ addr1: {Balance: funds}, addr2: {Balance: funds}, @@ -3574,7 +3826,7 @@ tx, _ = types.SignTx(tx, signer, key1)   b.AddTx(tx) }) - chain, err := NewBlockChain(rawdb.NewMemoryDatabase(), nil, gspec, nil, engine, vm.Config{}, nil, nil) + chain, err := NewBlockChain(rawdb.NewMemoryDatabase(), DefaultCacheConfigWithScheme(scheme), gspec, nil, engine, vm.Config{}, nil, nil) if err != nil { t.Fatalf("failed to create tester chain: %v", err) } @@ -3656,6 +3908,11 @@ // Tests the scenario the chain is requested to another point with the missing state. // It expects the state is recovered and all relevant chain markers are set correctly. func TestSetCanonical(t *testing.T) { + testSetCanonical(t, rawdb.HashScheme) + testSetCanonical(t, rawdb.PathScheme) +} + +func testSetCanonical(t *testing.T, scheme string) { //log.Root().SetHandler(log.LvlFilterHandler(log.LvlDebug, log.StreamHandler(os.Stderr, log.TerminalFormat(true))))   var ( @@ -3678,7 +3935,10 @@ panic(err) } gen.AddTx(tx) }) - chain, err := NewBlockChain(rawdb.NewMemoryDatabase(), nil, gspec, nil, engine, vm.Config{}, nil, nil) + diskdb, _ := rawdb.NewDatabaseWithFreezer(rawdb.NewMemoryDatabase(), t.TempDir(), "", false) + defer diskdb.Close() + + chain, err := NewBlockChain(diskdb, DefaultCacheConfigWithScheme(scheme), gspec, nil, engine, vm.Config{}, nil, nil) if err != nil { t.Fatalf("failed to create tester chain: %v", err) } @@ -3735,6 +3995,11 @@ // TestCanonicalHashMarker tests all the canonical hash markers are updated/deleted // correctly in case reorg is called. func TestCanonicalHashMarker(t *testing.T) { + testCanonicalHashMarker(t, rawdb.HashScheme) + testCanonicalHashMarker(t, rawdb.PathScheme) +} + +func testCanonicalHashMarker(t *testing.T, scheme string) { var cases = []struct { forkA int forkB int @@ -3782,7 +4047,7 @@ _, forkA, _ := GenerateChainWithGenesis(gspec, engine, c.forkA, func(i int, gen *BlockGen) {}) _, forkB, _ := GenerateChainWithGenesis(gspec, engine, c.forkB, func(i int, gen *BlockGen) {})   // Initialize test chain - chain, err := NewBlockChain(rawdb.NewMemoryDatabase(), nil, gspec, nil, engine, vm.Config{}, nil, nil) + chain, err := NewBlockChain(rawdb.NewMemoryDatabase(), DefaultCacheConfigWithScheme(scheme), gspec, nil, engine, vm.Config{}, nil, nil) if err != nil { t.Fatalf("failed to create tester chain: %v", err) } @@ -4131,6 +4396,116 @@ t.Fatalf("failed to create tester chain: %v", err) } defer chain.Stop() // Import the blocks + for _, block := range blocks { + if _, err := chain.InsertChain([]*types.Block{block}); err != nil { + t.Fatalf("block %d: failed to insert into chain: %v", block.NumberU64(), err) + } + } +} + +func TestDeleteThenCreate(t *testing.T) { + var ( + engine = ethash.NewFaker() + key, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291") + address = crypto.PubkeyToAddress(key.PublicKey) + factoryAddr = crypto.CreateAddress(address, 0) + funds = big.NewInt(1000000000000000) + ) + /* + contract Factory { + function deploy(bytes memory code) public { + address addr; + assembly { + addr := create2(0, add(code, 0x20), mload(code), 0) + if iszero(extcodesize(addr)) { + revert(0, 0) + } + } + } + } + */ + factoryBIN := common.Hex2Bytes("608060405234801561001057600080fd5b50610241806100206000396000f3fe608060405234801561001057600080fd5b506004361061002a5760003560e01c80627743601461002f575b600080fd5b610049600480360381019061004491906100d8565b61004b565b005b6000808251602084016000f59050803b61006457600080fd5b5050565b600061007b61007684610146565b610121565b905082815260208101848484011115610097576100966101eb565b5b6100a2848285610177565b509392505050565b600082601f8301126100bf576100be6101e6565b5b81356100cf848260208601610068565b91505092915050565b6000602082840312156100ee576100ed6101f5565b5b600082013567ffffffffffffffff81111561010c5761010b6101f0565b5b610118848285016100aa565b91505092915050565b600061012b61013c565b90506101378282610186565b919050565b6000604051905090565b600067ffffffffffffffff821115610161576101606101b7565b5b61016a826101fa565b9050602081019050919050565b82818337600083830152505050565b61018f826101fa565b810181811067ffffffffffffffff821117156101ae576101ad6101b7565b5b80604052505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b600080fd5b600080fd5b600080fd5b600080fd5b6000601f19601f830116905091905056fea2646970667358221220ea8b35ed310d03b6b3deef166941140b4d9e90ea2c92f6b41eb441daf49a59c364736f6c63430008070033") + + /* + contract C { + uint256 value; + constructor() { + value = 100; + } + function destruct() public payable { + selfdestruct(payable(msg.sender)); + } + receive() payable external {} + } + */ + contractABI := common.Hex2Bytes("6080604052348015600f57600080fd5b5060646000819055506081806100266000396000f3fe608060405260043610601f5760003560e01c80632b68b9c614602a576025565b36602557005b600080fd5b60306032565b005b3373ffffffffffffffffffffffffffffffffffffffff16fffea2646970667358221220ab749f5ed1fcb87bda03a74d476af3f074bba24d57cb5a355e8162062ad9a4e664736f6c63430008070033") + contractAddr := crypto.CreateAddress2(factoryAddr, [32]byte{}, crypto.Keccak256(contractABI)) + + gspec := &Genesis{ + Config: params.TestChainConfig, + Alloc: GenesisAlloc{ + address: {Balance: funds}, + }, + } + nonce := uint64(0) + signer := types.HomesteadSigner{} + _, blocks, _ := GenerateChainWithGenesis(gspec, engine, 2, func(i int, b *BlockGen) { + fee := big.NewInt(1) + if b.header.BaseFee != nil { + fee = b.header.BaseFee + } + b.SetCoinbase(common.Address{1}) + + // Block 1 + if i == 0 { + tx, _ := types.SignNewTx(key, signer, &types.LegacyTx{ + Nonce: nonce, + GasPrice: new(big.Int).Set(fee), + Gas: 500000, + Data: factoryBIN, + }) + nonce++ + b.AddTx(tx) + + data := common.Hex2Bytes("00774360000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000a76080604052348015600f57600080fd5b5060646000819055506081806100266000396000f3fe608060405260043610601f5760003560e01c80632b68b9c614602a576025565b36602557005b600080fd5b60306032565b005b3373ffffffffffffffffffffffffffffffffffffffff16fffea2646970667358221220ab749f5ed1fcb87bda03a74d476af3f074bba24d57cb5a355e8162062ad9a4e664736f6c6343000807003300000000000000000000000000000000000000000000000000") + tx, _ = types.SignNewTx(key, signer, &types.LegacyTx{ + Nonce: nonce, + GasPrice: new(big.Int).Set(fee), + Gas: 500000, + To: &factoryAddr, + Data: data, + }) + b.AddTx(tx) + nonce++ + } else { + // Block 2 + tx, _ := types.SignNewTx(key, signer, &types.LegacyTx{ + Nonce: nonce, + GasPrice: new(big.Int).Set(fee), + Gas: 500000, + To: &contractAddr, + Data: common.Hex2Bytes("2b68b9c6"), // destruct + }) + nonce++ + b.AddTx(tx) + + data := common.Hex2Bytes("00774360000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000a76080604052348015600f57600080fd5b5060646000819055506081806100266000396000f3fe608060405260043610601f5760003560e01c80632b68b9c614602a576025565b36602557005b600080fd5b60306032565b005b3373ffffffffffffffffffffffffffffffffffffffff16fffea2646970667358221220ab749f5ed1fcb87bda03a74d476af3f074bba24d57cb5a355e8162062ad9a4e664736f6c6343000807003300000000000000000000000000000000000000000000000000") + tx, _ = types.SignNewTx(key, signer, &types.LegacyTx{ + Nonce: nonce, + GasPrice: new(big.Int).Set(fee), + Gas: 500000, + To: &factoryAddr, // re-creation + Data: data, + }) + b.AddTx(tx) + nonce++ + } + }) + // Import the canonical chain + chain, err := NewBlockChain(rawdb.NewMemoryDatabase(), nil, gspec, nil, engine, vm.Config{}, nil, nil) + if err != nil { + t.Fatalf("failed to create tester chain: %v", err) + } for _, block := range blocks { if _, err := chain.InsertChain([]*types.Block{block}); err != nil { t.Fatalf("block %d: failed to insert into chain: %v", block.NumberU64(), err)
diff --git ethereum/go-ethereum/core/genesis_test.go taikoxyz/taiko-geth/core/genesis_test.go index 723d1e476bf123b2578a0df8eadf72c077e16092..fac88ff373b35d97017009434390d416992d21e9 100644 --- ethereum/go-ethereum/core/genesis_test.go +++ taikoxyz/taiko-geth/core/genesis_test.go @@ -30,18 +30,24 @@ "github.com/ethereum/go-ethereum/core/vm" "github.com/ethereum/go-ethereum/ethdb" "github.com/ethereum/go-ethereum/params" "github.com/ethereum/go-ethereum/trie" + "github.com/ethereum/go-ethereum/trie/triedb/pathdb" )   func TestInvalidCliqueConfig(t *testing.T) { block := DefaultGoerliGenesisBlock() block.ExtraData = []byte{} db := rawdb.NewMemoryDatabase() - if _, err := block.Commit(db, trie.NewDatabase(db)); err == nil { + if _, err := block.Commit(db, trie.NewDatabase(db, nil)); err == nil { t.Fatal("Expected error on invalid clique config") } }   func TestSetupGenesis(t *testing.T) { + testSetupGenesis(t, rawdb.HashScheme) + testSetupGenesis(t, rawdb.PathScheme) +} + +func testSetupGenesis(t *testing.T, scheme string) { var ( customghash = common.HexToHash("0x89c99d90b79719238d2645c7642f2c9295246e80775b38cfd162b696817fbd50") customg = Genesis{ @@ -53,6 +59,7 @@ } oldcustomg = customg ) oldcustomg.Config = &params.ChainConfig{HomesteadBlock: big.NewInt(2)} + tests := []struct { name string fn func(ethdb.Database) (*params.ChainConfig, common.Hash, error) @@ -63,7 +70,7 @@ }{ { name: "genesis without ChainConfig", fn: func(db ethdb.Database) (*params.ChainConfig, common.Hash, error) { - return SetupGenesisBlock(db, trie.NewDatabase(db), new(Genesis)) + return SetupGenesisBlock(db, trie.NewDatabase(db, newDbConfig(scheme)), new(Genesis)) }, wantErr: errGenesisNoConfig, wantConfig: params.AllEthashProtocolChanges, @@ -71,7 +78,7 @@ }, { name: "no block in DB, genesis == nil", fn: func(db ethdb.Database) (*params.ChainConfig, common.Hash, error) { - return SetupGenesisBlock(db, trie.NewDatabase(db), nil) + return SetupGenesisBlock(db, trie.NewDatabase(db, newDbConfig(scheme)), nil) }, wantHash: params.MainnetGenesisHash, wantConfig: params.MainnetChainConfig, @@ -79,8 +86,8 @@ }, { name: "mainnet block in DB, genesis == nil", fn: func(db ethdb.Database) (*params.ChainConfig, common.Hash, error) { - DefaultGenesisBlock().MustCommit(db) - return SetupGenesisBlock(db, trie.NewDatabase(db), nil) + DefaultGenesisBlock().MustCommit(db, trie.NewDatabase(db, newDbConfig(scheme))) + return SetupGenesisBlock(db, trie.NewDatabase(db, newDbConfig(scheme)), nil) }, wantHash: params.MainnetGenesisHash, wantConfig: params.MainnetChainConfig, @@ -88,8 +95,9 @@ }, { name: "custom block in DB, genesis == nil", fn: func(db ethdb.Database) (*params.ChainConfig, common.Hash, error) { - customg.MustCommit(db) - return SetupGenesisBlock(db, trie.NewDatabase(db), nil) + tdb := trie.NewDatabase(db, newDbConfig(scheme)) + customg.Commit(db, tdb) + return SetupGenesisBlock(db, tdb, nil) }, wantHash: customghash, wantConfig: customg.Config, @@ -97,8 +105,9 @@ }, { name: "custom block in DB, genesis == goerli", fn: func(db ethdb.Database) (*params.ChainConfig, common.Hash, error) { - customg.MustCommit(db) - return SetupGenesisBlock(db, trie.NewDatabase(db), DefaultGoerliGenesisBlock()) + tdb := trie.NewDatabase(db, newDbConfig(scheme)) + customg.Commit(db, tdb) + return SetupGenesisBlock(db, tdb, DefaultGoerliGenesisBlock()) }, wantErr: &GenesisMismatchError{Stored: customghash, New: params.GoerliGenesisHash}, wantHash: params.GoerliGenesisHash, @@ -107,8 +116,9 @@ }, { name: "compatible config in DB", fn: func(db ethdb.Database) (*params.ChainConfig, common.Hash, error) { - oldcustomg.MustCommit(db) - return SetupGenesisBlock(db, trie.NewDatabase(db), &customg) + tdb := trie.NewDatabase(db, newDbConfig(scheme)) + oldcustomg.Commit(db, tdb) + return SetupGenesisBlock(db, tdb, &customg) }, wantHash: customghash, wantConfig: customg.Config, @@ -118,16 +128,17 @@ name: "incompatible config in DB", fn: func(db ethdb.Database) (*params.ChainConfig, common.Hash, error) { // Commit the 'old' genesis block with Homestead transition at #2. // Advance to block #4, past the homestead transition block of customg. - genesis := oldcustomg.MustCommit(db) + tdb := trie.NewDatabase(db, newDbConfig(scheme)) + oldcustomg.Commit(db, tdb)   - bc, _ := NewBlockChain(db, nil, &oldcustomg, nil, ethash.NewFullFaker(), vm.Config{}, nil, nil) + bc, _ := NewBlockChain(db, DefaultCacheConfigWithScheme(scheme), &oldcustomg, nil, ethash.NewFullFaker(), vm.Config{}, nil, nil) defer bc.Stop()   - blocks, _ := GenerateChain(oldcustomg.Config, genesis, ethash.NewFaker(), db, 4, nil) + _, blocks, _ := GenerateChainWithGenesis(&oldcustomg, ethash.NewFaker(), 4, nil) bc.InsertChain(blocks)   // This should return a compatibility error. - return SetupGenesisBlock(db, trie.NewDatabase(db), &customg) + return SetupGenesisBlock(db, tdb, &customg) }, wantHash: customghash, wantConfig: customg.Config, @@ -175,7 +186,8 @@ {DefaultGoerliGenesisBlock(), params.GoerliGenesisHash}, {DefaultSepoliaGenesisBlock(), params.SepoliaGenesisHash}, } { // Test via MustCommit - if have := c.genesis.MustCommit(rawdb.NewMemoryDatabase()).Hash(); have != c.want { + db := rawdb.NewMemoryDatabase() + if have := c.genesis.MustCommit(db, trie.NewDatabase(db, trie.HashDefaults)).Hash(); have != c.want { t.Errorf("case: %d a), want: %s, got: %s", i, c.want.Hex(), have.Hex()) } // Test via ToBlock @@ -193,7 +205,7 @@ // difficulty is nil }   db := rawdb.NewMemoryDatabase() - genesisBlock := genesis.MustCommit(db) + genesisBlock := genesis.MustCommit(db, trie.NewDatabase(db, trie.HashDefaults))   if genesis.Difficulty != nil { t.Fatalf("assumption wrong") @@ -219,7 +231,7 @@ alloc = &GenesisAlloc{ {1}: {Balance: big.NewInt(1), Storage: map[common.Hash]common.Hash{{1}: {1}}}, {2}: {Balance: big.NewInt(2), Storage: map[common.Hash]common.Hash{{2}: {2}}}, } - hash, _ = alloc.deriveHash() + hash, _ = alloc.hash() ) blob, _ := json.Marshal(alloc) rawdb.WriteGenesisStateSpec(db, hash, blob) @@ -242,3 +254,10 @@ t.Fatal("Unexpected account") } } } + +func newDbConfig(scheme string) *trie.Config { + if scheme == rawdb.HashScheme { + return trie.HashDefaults + } + return &trie.Config{PathDB: pathdb.Defaults} +}
diff --git ethereum/go-ethereum/core/genesis_alloc.go taikoxyz/taiko-geth/core/genesis_alloc.go index 4703e4519b4f9daf2a4f1db63040a88f14d112aa..94c4ec53588995f17c5a41bbdb01136b15f3caf0 100644 --- ethereum/go-ethereum/core/genesis_alloc.go +++ taikoxyz/taiko-geth/core/genesis_alloc.go @@ -24,3 +24,4 @@ // nolint: misspell const mainnetAllocData = "\xfa\x04]X\u0793\r\x83b\x011\x8e\u0189\x9agT\x06\x908'\x80t2\x80\x89\n\u05ce\xbcZ\xc6 \x00\x00\u0793\x17bC\x0e\xa9\u00e2nWI\xaf\xdbp\xda_x\u077b\x8c\x89\n\u05ce\xbcZ\xc6 \x00\x00\u0793\x1d\x14\x80K9\x9cn\xf8\x0edWoev`\x80O\xec\v\x89\u3bb5sr@\xa0\x00\x00\u07932@5\x87\x94{\x9f\x15b*h\xd1\x04\xd5M3\xdb\xd1\u0349\x043\x87Oc,\xc6\x00\x00\u0793I~\x92\xcd\xc0\xe0\xb9c\xd7R\xb2)j\u02c7\u0682\x8b$\x89\n\x8fd\x9f\xe7\xc6\x18\x00\x00\u0793K\xfb\xe1Tk\xc6\xc6[\\~\xaaU0K8\xbb\xfe\xc6\u04c9lk\x93[\x8b\xbd@\x00\x00\u0793Z\x9c\x03\xf6\x9d\x17\xd6l\xbb\x8a\xd7!\x00\x8a\x9e\xbb\xb86\xfb\x89lk\x93[\x8b\xbd@\x00\x00\u0793]\x0e\xe8\x15^\xc0\xa6\xffh\bU,\xa5\xf1k\xb5\xbe2:\x89\n\xad\xec\x98?\xcf\xf4\x00\x00\u0793v\"\xd8J#K\xb8\xb0x#\x0f\u03c4\xb6z\u9a2c\xae\x89%\xe1\xccQ\x99R\xf8\x00\x00\u0793{\x9f\xc3\x19\x05\xb4\x99K\x04\xc9\xe2\xcf\xdc^'pP?B\x89l]\xb2\xa4\xd8\x15\xdc\x00\x00\u0793\u007fJ#\xca\x00\xcd\x04=%\u0088\x8c\x1a\xa5h\x8f\x81\xa3D\x89)\xf0\xa9[\xfb\xf7)\x00\x00\u0793\x869\u06bb\u3bac\x88{]\xc0\xe4>\x13\xbc\u0487\xd7l\x89\x10\xd0\xe3\xc8}n,\x00\x00\u0793\x89P\x86y\xab\xf8\xc7\x1b\xf6x\x16\x87\x12\x0e>j\x84XM\x89a\x94\x04\x9f0\xf7 \x00\x00\u0793\x8f\xc7\u02ed\xff\xbd\r\u007f\xe4O\x8d\xfd`\xa7\x9dr\x1a\x1c\x9c\x8965\u026d\xc5\u07a0\x00\x00\u0793\x95`\xa3\xdebxh\xf9\x1f\xa8\xbf\xe1\xc1\xb7\xaf\xaf\b\x18k\x89\x1cg\xf5\xf7\xba\xa0\xb0\x00\x00\u0793\x96\x97G\xf7\xa5\xb3\x06E\xfe\x00\xe4I\x01CZ\xce$\xcc7\x89\\(=A\x03\x94\x10\x00\x00\u0793\x9am}\xb3&g\x9bw\xc9\x03\x91\xa7Gm#\x8f;\xa3>\x89\n\xdaUGK\x814\x00\x00\u0793\x9e\xef\n\b\x86\x05n?i!\x18S\xb9\xb7E\u007f7\x82\u4262\xa8x\x06\x9b(\xe0\x00\x00\u0793\x9f\xdb\xf4N\x1fJcb\xb7i\u00daG_\x95\xa9l+\u01c9\x1e\x93\x12\x83\xcc\xc8P\x00\x00\u07d3\xa5y\u007fR\xc9\u054f\x18\x9f6\xb1\xd4]\x1b\xf6\x04\x1f/k\x8a\x01'\u0473F\x1a\xcd\x1a\x00\x00\u0793\xaaS\x81\xb2\x13\x8e\xbe\xff\xc1\x91\xd5\xd8\u00d1u;p\x98\u04895\xab\xb0\x9f\xfe\u07b6\x80\x00\u0793\xaa\xda%\xea\"\x86p\x9a\xbbB-A\x92?\u04c0\xcd\x04\u01c9#=\xf3)\x9far\x00\x00\u0793\xac\xbf\xb2\xf2ZT\x85\xc79\xefp\xa4N\xee\xeb|e\xa6o\x89\x05k\xc7^-c\x10\x00\x00\u07d3\xac\xc6\xf0\x82\xa4B\x82\x87d\xd1\x1fX\u0589J\xe4\b\xf0s\x8a\f\xb4\x9bD\xba`-\x80\x00\x00\u0793\xb2w\xb0\x99\xa8\xe8f\xca\x0e\xc6[\u02c7(O\xd1B\xa5\x82\x89j\xcb=\xf2~\x1f\x88\x00\x00\u0753\xbd\xd4\x01:\xa3\x1c\x04al+\xc9x_'\x88\xf9\x15g\x9b\x88\xb9\xf6]\x00\xf6<\x00\x00\u0793\xc2}c\xfd\xe2K\x92\xee\x8a\x1e~\xd5\xd2m\x8d\xc5\xc8;\x03\x89lk\x93[\x8b\xbd@\x00\x00\u0553\xc4\x0f\xe2\tT#P\x9b\x9f\u0677T21X\xaf#\x10\xf3\x80\u0793\xd7^\xd6\fwO\x8b:ZQs\xfb\x183\xadq\x05\xa2\u0649l\xb7\xe7Hg\xd5\xe6\x00\x00\u07d3\u05cd\x89\xb3_G'\x16\xec\xea\xfe\xbf`\x05'\u04e1\xf9i\x8a\x05\xe0T\x9c\x962\xe1\xd8\x00\x00\u0793\xda\xe2{5\v\xae \xc5e!$\xaf]\x8b\\\xba\x00\x1e\xc1\x89\x02+\x1c\x8c\x12'\xa0\x00\x00\u0793\xdc\x01\xcb\xf4Ix\xa4.\x8d\xe8\xe46\xed\xf9B\x05\u03f6\xec\x89O\x0f\xeb\xbc\u068c\xb4\x00\x00\u07d3\u607c-\x10\xdbb\u0785\x84\x83$I\"P4\x8e\x90\xbf\x8a\x04<3\xc1\x93ud\x80\x00\x00\u07d3\xf4c\xe17\xdc\xf6%\xfb\U000fc8de\u0298\u04b9h\xcf\u007f\x8a\x01@a\xb9\xd7z^\x98\x00\x00\u07d4\x01\x00\a9K\x8bue\xa1e\x8a\xf8\x8c\xe4cI\x915\u05b7\x89\x05k\xc7^-c\x10\x00\x00\u07d4\x01\r\xf1\xdfK\xed#v\r-\x1c\x03x\x15\x86\xdd\xf7\x91\x8eT\x89\x03@\xaa\xd2\x1b;p\x00\x00\xe0\x94\x01\x0fJ\x98\u07e1\xd9y\x9b\xf5\u01d6\xfbU\x0e\xfb\xe7\xec\xd8w\x8a\x01\xb2\xf2\x92#b\x92\xc7\x00\x00\u07d4\x01\x15PW\x00/k\r\x18\xac\xb98\x8d;\xc8\x12\x9f\x8fz \x89H\xa4<T`/p\x00\x00\u07d4\x01\"n\n\xd8\xd6\"w\xb1bb\x1cb\xc9(\xe9n\v\x9a\x8c\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\x01&\xe1.\xbc\x17\x03_5\xc0\xe9\xd1\x1d\xd1H9<@]z\x89lf\x06E\xaaG\x18\x00\x00\u07d4\x01/9j+^\xb85Y\xba\xc5\x15\xe5!\r\xf2\xc8\xc3b\xba\x89\n\u05ce\xbcZ\xc6 \x00\x00\u07d4\x014\xff8\x15_\xab\xae\x94\xfd5\xc4\xff\xe1\u05dd\xe7\xef\x9cY\x895e\x9e\xf9?\x0f\xc4\x00\x00\u07d4\x016\xa5\xafl2\x99\u01b5\xf0\x05\xfd\xad\xdb\x14\x8c\a\v)\x9b\x89\x01\x1a\xa9\xac\x15\xf1(\x00\x00\u07d4\x01H\x8a\xd3\xda`<L\xddl\xb0\xb7\xa1\xe3\r*0\xc8\xfc8\x89\n\u05ce\xbcZ\xc6 \x00\x00\u07d4\x01It\xa1\xf4k\xf2\x04\x94J\x851\x11\xe5/\x16\x02a}\xef\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\x01K\u007fg\xb1O]\x98=\x87\x01OW\f\x8b\x99;\x98r\xb5\x89\n\u05ce\xbcZ\xc6 \x00\x00\u07d4\x01Q\xfa]\x17\xa2\xdc\xe2\xd7\xf1\xeb9\xef\u007f\xe2\xad!=]\x89\x89\xd8\xd7&\xb7\x17z\x80\x00\x00\u07d4\x01Wz\xfdNP\x89\x02G\u0271\rD\xafs\"\x9a\xec\x88O\x89$\xdc\xe5M4\xa1\xa0\x00\x00\xe0\x94\x01_\t}\x9a\xcd\xdc\u076f\xaf*\x10~\xb9:@\xfc\x94\xb0L\x8a\x04<3\xc1\x93ud\x80\x00\x00\u07d4\x01i\xc1\xc2\x10\xea\xe8E\xe5h@A.\x1fe\x99>\xa9\x0f\xb4\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\x01k`\xbbmg\x92\x8c)\xfd\x03\x13\xc6f\u068f\x16\x98\xd9\u0149lk\x93[\x8b\xbd@\x00\x00\u07d4\x01l\x85\xe1a;\x90\x0f\xa3W\xb8(;\x12\x0ee\xae\xfc\xdd\b\x89+]\x97\x84\xa9|\xd5\x00\x00\u07d4\x01\x84\x92H\x8b\xa1\xa2\x924\"G\xb3\x18U\xa5Y\x05\xfe\xf2i\x89\a\x96\xe3\xea?\x8a\xb0\x00\x00\u07d4\x01\x8f \xa2{'\xecD\x1a\xf7#\xfd\x90\x99\xf2\u02f7\x9dbc\x89uy*\x8a\xbd\xef|\x00\x00\u07d4\x01\x91\xebT~{\xf6\x97k\x9b\x1bWuFv\x1d\xe6V\"\xe2\x89lkLM\xa6\u077e\x00\x00\u07d4\x01\x9dp\x95y\xffK\xc0\x9f\xdc\xdd\xe41\xdc\x14G\xd2\xc2`\xbc\x89\x01\x15\x8eF\t\x13\xd0\x00\x00\u07d4\x01\xa2Z_Z\xf0\x16\x9b0\x86L;\xe4\xd7V<\xcdD\xf0\x9e\x89M\x85<\x8f\x89\b\x98\x00\x00\xe0\x94\x01\xa7\xd9\xfa}\x0e\xb1\x18\\g\xe5M\xa8<.u\xdbi\u37ca\x01\x9dJ\xdd\xd0\u063c\x96\x00\x00\u07d4\x01\xa8\x18\x13ZAB\x10\xc3|b\xb6%\xac\xa1\xa5F\x11\xac6\x89\x0e\x189\x8ev\x01\x90\x00\x00\u07d4\x01\xb1\xca\xe9\x1a;\x95Y\xaf\xb3<\xdcmh\x94B\xfd\xbf\xe07\x89\n\u05ce\xbcZ\xc6 \x00\x00\u07d4\x01\xb5\xb5\xbcZ\x11\u007f\xa0\x8b4\xed\x1d\xb9D\x06\bYz\xc5H\x89\n\u05ce\xbcZ\xc6 \x00\x00\u07d4\x01\xbb\xc1Og\xaf\x069\xaa\xb1D\x1ej\b\xd4\xceqb\t\x0f\x89F\xfc\xf6\x8f\xf8\xbe\x06\x00\x00\xe0\x94\x01\xd08\x15\xc6\x1fAkq\xa2a\n-\xab\xa5\x9f\xf6\xa6\xde[\x8a\x02\x05\xdf\xe5\v\x81\xc8.\x00\x00\u07d4\x01\u0559\xee\r_\x8c8\xab-9.,e\xb7L<\xe3\x18 \x89\x1b\xa5\xab\xf9\xe7y8\x00\x00\u07d4\x01\xe4\x05!\x12%0\u066c\x91\x11<\x06\xa0\x19\vmc\x85\v\x89Hz\x9a0E9D\x00\x00\u07d4\x01\xe6A]X{\x06T\x90\xf1\xed\u007f!\xd6\xe0\xf3\x86\xeegG\x89lk\x93[\x8b\xbd@\x00\x00\xe0\x94\x01\xe8d\xd3Tt\x1bB>oB\x85\x17$F\x8ct\xf5\xaa\x9c\x8a\x04<3\xc1\x93ud\x80\x00\x00\u07d4\x01\xed_\xba\x8d.\xabg:\xec\x04-0\xe4\xe8\xa6\x11\xd8\xc5Z\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\x01\xfb\x8e\xc1$%\xa0O\x81>F\xc5L\x05t\x8c\xa6\xb2\x9a\xa9\x89\x0e\x15s\x03\x85F|\x00\x00\u07d4\x01\xff\x1e\xb1\u07adP\xa7\xf2\xf9c\x8f\xde\xe6\xec\xcf:{*\u0209 \x86\xac5\x10R`\x00\x00\u07d4\x02\x03b\u00ed\xe8x\u0290\u05b2\u0609\xa4\xccU\x10\xee\xd5\xf3\x898\x88\xe8\xb3\x11\xad\xb3\x80\x00\u07d4\x02\x03\xae\x01\xd4\xc4\x1c\xae\x18e\xe0K\x1f[S\xcd\xfa\xec\xae1\x896\x89\xcd\u03b2\x8c\xd7\x00\x00\u07d4\x02\b\x93a\xa3\xfetQ\xfb\x1f\x87\xf0\x1a-\x86fS\xdc\v\a\x89\x02*\xc7H2\xb5\x04\x00\x00\u07d4\x02\x1fi\x04=\xe8\x8cI\x17\xca\x10\xf1\x84(\x97\xee\xc0X\x9c|\x89kD\u03f8\x14\x87\xf4\x00\x00\u07d4\x02)\x0f\xb5\xf9\xa5\x17\xf8(E\xac\xde\xca\x0f\xc8F\x03\x9b\xe23\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\x029\xb4\xf2\x1f\x8e\x05\xcd\x01Q++\xe7\xa0\xe1\x8am\x97F\a\x8965\u026d\xc5\u07a0\x00\x00\u07d4\x02Gr\x12\xff\xddu\xe5\x15VQ\xb7e\x06\xb1dfq\xa1\xeb\x89_h\xe8\x13\x1e\u03c0\x00\x00\u07d4\x02J\t\x8a\xe7\x02\xbe\xf5@l\x9c\"\xb7\x8b\xd4\xeb,\u01e2\x93\x89\xd8\xd7&\xb7\x17z\x80\x00\x00\u07d4\x02K\xdd,{\xfdP\x0e\xe7@O\u007f\xb3\xe9\xfb1\xdd \xfb\u0449\t\xc2\x00vQ\xb2P\x00\x00\u07d4\x02Sg\x96\x03\x04\xbe\xee4Y\x11\x18\xe9\xac-\x13X\xd8\x02\x1a\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\x02V\x14\x9f[Pc\xbe\xa1N\x15f\x1f\xfbX\xf9\xb4Y\xa9W\x89&)\xf6n\fS\x00\x00\x00\u07d4\x02`=z;\xb2\x97\xc6|\x87~]4\xfb\u0579\x13\xd4\xc6:\x89\x01\x15\x8eF\t\x13\xd0\x00\x00\u07d4\x02a\xad:\x17*\xbf\x13\x15\xf0\xff\xec2p\x98j\x84\t\xcb%\x89\v\b!;\u03cf\xfe\x00\x00\u07d4\x02d2\xaf7\xdcQ\x13\xf1\xf4mH\nM\u0c80R#~\x89\x13I\xb7\x86\xe4\v\xfc\x00\x00\u07d4\x02f\xab\x1ck\x02\x16#\v\x93\x95D=_\xa7^hEh\u018965\u026d\xc5\u07a0\x00\x00\u07d4\x02u\x1d\u018c\xb5\xbdsp'\xab\xf7\u0777s\x90\xcdw\xc1k\x89\x01\x15\x8eF\t\x13\xd0\x00\x00\xe0\x94\x02w\x8e9\x0f\xa1u\x10\xa3B\x8a\xf2\x87\fBsT}8l\x8a\x03l<f\x17\f\rr\x00\x00\xe0\x94\x02\xad\xe5\xdb\"\xf8\xb7X\xee\x14Cbld\xec/2\xaa\n\x15\x8a\x04<3\xc1\x93ud\x80\x00\x00\u07d4\x02\xaf$Y\xa9=\v?M\x06&6#l\u0532\x9e;\xce\u03c9g\x8a\x93 b\xe4\x18\x00\x00\u07d4\x02\xb1\xafr3\x9b*\"V8\x9f\xd6F\a\xde$\xf0\xde`\n\x89lk\x93[\x8b\xbd@\x00\x00\xe0\x94\x02\xb6C\xd6\xfa\xbdCz\x85\x1a\u033ey\xab\xb7\xfd\xe1&\xdc\u03ca\x01\x86P\x12|\xc3\u0700\x00\x00\xe0\x94\x02\xb6\xd6\\\xb0\v{6\xe1\xfb^\xd3c,L\xb2\n\x89A0\x8a\x04<3\xc1\x93ud\x80\x00\x00\u07d4\x02\xb7\xb1\u05b3L\xe0S\xa4\x0e\xb6\\\u0524\xf7\xdd\xdd\x0e\x9f0\x89%\"H\u07b6\xe6\x94\x00\x00\xe0\x94\x02\xc9\xf7\x94\n{\x8bzA\v\xf8=\xc9\xc2#3\xd4']\u04ca\x01\x0f\f\xf0d\xddY \x00\x00\u07d4\x02\u0523\th\xa3\x9e+4\x98\u00e6\xa4\xedE\xc1\xc6dh\"\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\x02\xdf\xcb\x17\xa1\xb8tA\x03ct\xb7b\xa5\xd3A\x8b\x1c\xb4\u0509H\xb0+\xa9\u047aF\x00\x00\u07d4\x02\xe4\xcb\"\xbeF%\x8a@\xe1mC8\xd8\x02\xff\xfd\x00\xc1Q\x89\x14\x96\x96\xea\u03ba\x81\x00\x00\u07d4\x02\xe8\x16\xaf\xc1\xb5\xc0\xf3\x98R\x13\x19Y\xd9F\xeb;\a\xb5\xad\x8965\u026d\xc5\u07a0\x00\x00\u07d4\x02\xf7\xf6r\t\xb1j\x17U\fiLrX8\x19\xc8\vT\xad\x89\x05U\x93\x06\xa7\x8ap\x00\x00\xe0\x94\x03\ts\x80{/Bi\x14\xad\x00\x18\x12p\xac\xd2{\x8f\xf6\x1f\x8a\x01!\xeah\xc1\x14\xe5\x10\x00\x00\u07d4\x03\ty#\xba\x15^\x16\xd8/:\xd3\xf6\xb8\x15T\b\x84\xb9,\x89b\xa9\x92\xe5:\n\xf0\x00\x00\u07d4\x03\x0f\xb3@\x1fr\xbd4\x18\xb7\xd1\xdau\xbf\x8cQ\x9d\xd7\a\u0709\xa2\xa1]\tQ\x9b\xe0\x00\x00\u07d4\x03\x1e%\xdbQk\x0f\t\x9f\xae\xbf\xd9O\x89\f\xf9f`\x83k\x89lk\x93[\x8b\xbd@\x00\x00\xe0\x94\x03(Q\f\t\xdb\u0345\x19J\x98\xd6|3\xacI\xf2\xf9M`\x8a\x02TO\xaaw\x80\x90\xe0\x00\x00\u07d4\x03)\x18\x8f\b\x06W\xab:*\xfaR$g\x17\x82y\x83 \x85\x89\v\xbfQ\r\xdf\xcb&\x00\x00\u07d4\x031x&\xd1\xf7\n\xa4\xbd\u07e0\x9b\xe0\xc4\x10UR\xd25\x8b\x89\x02\x1auJm\xc5(\x00\x00\u07d4\x033p\x12\xae\x1d\u007f\xf3\xee\u007fi|@>w\x80\x18\x8b\xf0\xef\x89\n\u05ce\xbcZ\xc6 \x00\x00\xe0\x94\x037|\x0eUkd\x01\x03(\x9aa\x89\u1baecI4g\x8a\x04<3\xc1\x93ud\x80\x00\x00\u07d4\x03IcM\u00a9\xe8\f?w!\xee+PF\xae\xaa\xed\xfb\xb5\x89\xd8\xd7&\xb7\x17z\x80\x00\x00\u07d4\x03U\xbc\xac\xbd!D\x1e\x95\xad\xee\xdc0\xc1r\x18\u0224\b\u0389\x15\xaf\x1dx\xb5\x8c@\x00\x00\u07d4\x03n\xef\xf5\xba\x90\xa6\x87\x9a\x14\xdf\xf4\xc5\x04;\x18\xca\x04`\u0249\x05k\xc7^-c\x10\x00\x00\xe0\x94\x03qKA\u04a6\xf7Q\x00\x8e\xf8\xddM+)\xae\u02b8\xf3n\x8a\x01EB\xba\x12\xa37\xc0\x00\x00\xe0\x94\x03r\xe8RX.\t44J\x0f\xed!x0M\xf2]F(\x8a\x04<3\xc1\x93ud\x80\x00\x00\u07d4\x03r\xeeU\b\xbf\x81c\xed(N^\xef\x94\xceMsg\xe5\"\x89\x05k\xc7^-c\x10\x00\x00\u07d4\x03}\xd0V\xe7\xfd\xbdd\x1d\xb5\xb6\xbe\xa2\xa8x\n\x83\xfa\u1009\a\x96\xe3\xea?\x8a\xb0\x00\x00\xe0\x94\x03\x83#\xb1\x84\xcf\xf7\xa8*\xe2\u1f67y?\xe41\x9c\xa0\xbf\x8a\x04<3\xc1\x93ud\x80\x00\x00\u07d4\x03\x87y\xca-\xbef>c\xdb?\xe7V\x83\xea\x0e\xc6.#\x83\x89Z\x87\xe7\xd7\xf5\xf6X\x00\x00\xe0\x94\x03\x8eE\xea\xdd=\x88\xb8\u007f\xe4\u06b0fh\x05\"\xf0\xdf\xc8\xf9\x8a\x02\x1e\x19\xe0\u027a\xb2@\x00\x00\u07d4\x03\x92T\x9ar\u007f\x81eT)\u02d2\x8bR\x9f%\xdfM\x13\x85\x89\x01lC\xa0\xee\xa0t\x00\x00\u07d4\x03\x94\xb9\x0f\xad\xb8`O\x86\xf4?\xc1\xe3]1$\xb3*Y\x89\x89)j\xa1@'\x8ep\x00\x00\u0794\x03\x9ezN\xbc(N,\xcdB\xb1\xbd\xd6\v\xd6Q\x1c\x0fw\x06\x88\xf0\x15\xf2W6B\x00\x00\u07d4\x03\x9e\xf1\xceR\xfeyc\xf1f\u0562u\u0131\x06\x9f\xe3\xa82\x89\x15\xaf9\u4ab2t\x00\x00\u07d4\x03\xa2l\xfcL\x181op\u055e\x9e\x1ay\xee>\x8b\x96/L\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\x03\xaab(\x81#m\xd0\xf4\x94\f$\xc3$\xff\x8b{~!\x86\x89\xadx\xeb\u016cb\x00\x00\x00\u07d4\x03\xafz\xd9\xd5\"<\xf7\xc8\xc1? \xdfg\xeb\xe5\xff\u017bA\x89\n\u05ce\xbcZ\xc6 \x00\x00\u07d4\x03\xb0\xf1|\xd4F\x9d\xdc\u03f7\xdai~\x82\xa9\x1a_\x9ewt\x89\x01\x15\x8eF\t\x13\xd0\x00\x00\u07d4\x03\xb4\x1bQ\xf4\x1d\xf2\r\xd2y\xba\xe1\x8c\x12w_w\xadw\x1c\x8965\u026d\xc5\u07a0\x00\x00\u07d4\x03\xbe[F)\xae\xfb\xbc\xab\x9d\xe2m9Wl\xb7\xf6\x91\xd7d\x89\n\xdf0\xbap\u0217\x00\x00\u07d4\x03\xc6G\xa9\xf9)\xb0x\x1f\xe9\xae\x01\u02a3\xe1\x83\xe8vw~\x89\x18*\xb7\xc2\f\xe5$\x00\x00\u07d4\x03\xc9\x1d\x92\x946\x03\xe7R >\x054\x0eV`\x13\xb9\x00E\x89+|\xc2\xe9\xc3\"\\\x00\x00\u07d4\x03\xcbLOE\x16\xc4\xffy\xa1\xb6$O\xbfW.\x1c\u007f\xeay\x89\x94\x89#z\u06daP\x00\x00\u07d4\x03\u02d8\u05ec\xd8\x17\u079d\x88m\"\xfa\xb3\xf1\xb5}\x92\xa6\b\x89V\xbcu\xe2\xd61\x00\x00\x00\u07d4\x03\u031d-!\xf8k\x84\xac\x8c\xea\xf9q\u06e7\x8a\x90\xe6%p\x89WG=\x05\u06ba\xe8\x00\x00\u07d4\x03\xd1rO\xd0\x0eT\xaa\xbc\xd2\xde*\x91\xe8F+\x10I\xdd:\x89\x8f\x1d\\\x1c\xae7@\x00\x00\u07d4\x03\xde\xdf\xcd\v<.\x17\xc7\x05\xda$\x87\x90\uf626\xbdWQ\x89Hz\x9a0E9D\x00\x00\u07d4\x03\u8c04SuW\xe7\t\xea\xe2\xe1\u1966\xbc\xe1\xef\x83\x14\x89\x01\x15\x8eF\t\x13\xd0\x00\x00\u07d4\x03\xeam&\u0400\xe5z\xee9&\xb1\x8e\x8e\xd7:N[(&\x89\n\u05ce\xbcZ\xc6 \x00\x00\u07d4\x03\xeb<\xb8`\xf6\x02\x8d\xa5T\xd3D\xa2\xbbZP\n\xe8\xb8o\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\x03\xeb\xc6?\xdaf`\xa4e\x04^#_\xben\\\xf1\x95s_\x89\a\xb0l\xe8\u007f\xddh\x00\x00\xe0\x94\x03\xefj\xd2\x0f\xf7\xbdO\x00+\xacX\xd4uD\u03c7\x9a\xe7(\x8a\x01u\xc7X\u0439n\\\x00\x00\u07d4\x03\xf7\xb9 \b\x81:\xe0\xa6v\xeb!(\x14\xaf\xab5\"\x10i\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\x04\x11p\xf5\x81\u0780\xe5\x8b*\x04\\\x8f|\x14\x93\xb0\x01\xb7\u02c90<t\xa1\xa36\x94\x00\x00\u07d4\x04\x13\xd0\xcfx\xc0\x01\x89\x8a7\x8b\x91\x8c\xd6\xe4\x98\xeaw<M\x89\x0f-\xc7\xd4\u007f\x15`\x00\x00\u07d4\x04$\x1bA\xec\xbd\v\xfd\xf1)^\x9dO\xa5\x9e\xa0\x9ela\x86\x89e_v\x94P\xbcx\x00\x00\u07d4\x047\a\a\x1e*\xe2\x1e\xed\x97x\x91\xdcy\xcd]\x8e\xe1\xc2\u0689lk\x93[\x8b\xbd@\x00\x00\u07d4\x04N\x851D\xe36D\x95\u799f\xa1\xd4j\xbe\xa3\xac\td\x89\x02\xab\"T\xb1\u071a\x80\x00\u07d4\x04U\xdc\xec\x8a\u007f\xc4F\x1b\xfd\u007f7Eo\xce?L<\xaa\u01c9\x15\xaf\x1dx\xb5\x8c@\x00\x00\u07d4\x04^\xd7\xf6\xd9\xee\x9f%.\a2h\xdb\x02,c&\xad\xfc[\x89\x05k\xc7^-c\x10\x00\x00\u07d4\x04cw\xf8d\xb0\x14?(!t\xa8\x92\xa7=>\xc8\xeca2\x89\nZ\xa8P\t\xe3\x9c\x00\x00\u07d4\x04i\xe8\xc4@E\v\x0eQ&&\xfe\x81~gT\xa8\x15(0\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\x04m'K\x1a\xf6\x15\xfbPZvJ\xd8\u0767p\xb1\xdb/=\x89lk\x93[\x8b\xbd@\x00\x00\xe0\x94\x04}Z&\u05ed\x8f\x8ep`\x0fp\xa3\x98\u076a\x1c-\xb2o\x8a\x01EB\xba\x12\xa37\xc0\x00\x00\u07d4\x04~\x87\xc8\xf7\xd1\xfc\xe3\xb0\x13S\xa8Xb\xa9H\xac\x04\x9f>\x89P\xc5\xe7a\xa4D\b\x00\x00\u07d4\x04\u007f\x9b\xf1R\x9d\xaf\x87\xd4\a\x17^o\x17\x1b^Y\xe9\xff>\x89#<\x8f\xe4'\x03\xe8\x00\x00\xe0\x94\x04\x85'2\xb4\xc6R\xf6\xc2\u53b3e\x87\xe6\nb\xda\x14\u06ca\x04<3\xc1\x93ud\x80\x00\x00\xe0\x94\x04\x8a\x89p\xeaAE\xc6MU\x17\xb8\xde[F\xd0YZ\xad\x06\x8a\x04<3\xc1\x93ud\x80\x00\x00\u07d4\x04\x9c]K\xc6\xf2]NEli{R\xa0x\x11\xcc\u045f\xb1\x89\x10D\x00\xa2G\x0eh\x00\x00\u07d4\x04\xa1\xca\xda\x1c\xc7Q\b/\xf8\u0692\x8e<\xfa\x00\b \xa9\xe9\x89\x02+\x1c\x8c\x12'\xa0\x00\x00\u07d4\x04\xa8\n\xfa\xd5>\xf1\xf8Ae\xcf\xd8R\xb0\xfd\xf1\xb1\xc2K\xa8\x89\x03$\xe9d\xb3\xec\xa8\x00\x00\u07d4\x04\xaa\xfc\x8a\xe5\xceoI\x03\u021d\u007f\xac\x9c\xb1\x95\x12\"Gw\x89\x1b\x1a\xe4\xd6\xe2\xefP\x00\x00\u07d4\x04\xbaK\xb8q@\x02,!Jo\xacB\xdbZ\x16\u0755@E\x8965\u026d\xc5\u07a0\x00\x00\u07d4\x04\xba\x8a?\x03\xf0\x8b\x89P\x95\x99M\xdaa\x9e\u06ac\xee>z\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\x04\xc2\xc6K\xb5L>\xcc\xd0U\x85\xe1\x0e\xc6\xf9\x9a\f\xdb\x01\xa3\x89\x05k\xc7^-c\x10\x00\x00\u07d4\x04\xceE\xf6\x00\xdb\x18\xa9\u0405\x1b)\xd99>\xbd\xaa\xfe=\u0149\x01\x15\x8eF\t\x13\xd0\x00\x00\u07d4\x04\u05b8\xd4\u0686t\a\xbb\x99wI\u07bb\xcd\xc0\xb3XS\x8a\x8965\u026d\xc5\u07a0\x00\x00\u07d4\x04\xd78\x96\xcfe\x93\xa6\x91\x97*\x13\xa6\xe4\x87\x1f\xf2\xc4+\x13\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\x04\xd8*\xf9\xe0\x1a\x93m\x97\xf8\xf8Y@\xb9p\xf9\xd4\u06d96\x89\n\u05ce\xbcZ\xc6 \x00\x00\u07d4\x04\xe5\xf5\xbc|\x92?\xd1\xe3\x175\xe7.\xf9h\xfdg\x11\fn\x89WU\x1d\xbc\x8ebL\x00\x00\u07d4\x04\xec\xa5\x01c\n\xbc\xe3R\x18\xb1t\x95k\x89\x1b\xa2^\xfb#\x8966\x9e\xd7t}&\x00\x00\u07d4\x05\x05\xa0\x8e\"\xa1\t\x01Z\"\xf6\x850STf*U1\u0549\x8c\xf2?\x90\x9c\x0f\xa0\x00\x00\u07d4\x05\x14\x95L</\xb6W\xf9\xa0oQ\x0e\xa2'H\xf0'\xcd\u04c9\x15\xaf\x1dx\xb5\x8c@\x00\x00\xe0\x94\x05\x163\b\r\a\xa5W\xad\xde1\x92a\xb0t\x99\u007f\x14i-\x8a\x01:k+VHq\xa0\x00\x00\u07d4\x05\x17D\x8d\xad\xa7a\xcc[\xa4\x03>\xe8\x81\xc807\x03d\x00\x89lO\xd1\xee$nx\x00\x00\u07d4\x05\x1dBBv\xb2\x129fQ\x86\x13=e;\xb8\xb1\x86/\x89\x8965\u026d\xc5\u07a0\x00\x00\u07d4\x05!\xbc:\x9f\x87\x11\xfe\xcb\x10\xf5\a\x97\xd7\x10\x83\xe3A\ub749\x01\x15\x8eF\t\x13\xd0\x00\x00\u07d4\x05#mL\x90\xd0e\xf9\u34c3X\xaa\xff\xd7w\xb8j\xecI\x89\x1b\x1a\xe4\xd6\xe2\xefP\x00\x00\u07d4\x05*X\xe05\xf1\xfe\x9c\xdd\x16\x9b\xcf \x97\x03E\xd1+\x9cQ\x89P\xc5\xe7a\xa4D\b\x00\x00\u07d4\x05.\xab\x1fa\xb6\xd4U\x17(?A\xd1D\x18$\x87\x87I\u0409\xd8\xd7&\xb7\x17z\x80\x00\x00\u07d4\x053n\x9ar'(\xd9c\xe7\xa1\xcf'Y\xfd\x02tS\x0f\u02891\xa2D?\x88\x8ay\x80\x00\u07d4\x054q\u035aA\x92[9\x04\xa5\xa8\xff\xca6Y\xe04\xbe#\x89\n\xd2\x01\xa6yO\xf8\x00\x00\u07d4\x056\x1d\x8e\xb6\x94\x1dN\x90\xfb~\x14\x18\xa9Z2\xd5%w2\x89\x01\x15\x8eF\t\x13\xd0\x00\x00\u07d4\x05B:T\xc8\xd0\xf9p~pAs\xd9#\xb9F\xed\xc8\xe7\x00\x89\x06\xea\x03\u00bf\x8b\xa5\x80\x00\u07d4\x05D\f[\a;R\x9bH) \x9d\xff\x88\t\x0e\a\xc4\xf6\xf5\x89E\u04977\xe2/ \x00\x00\u07d4\x05Z\xb6X\xc6\xf0\xedO\x87^\xd6t.K\xc7)-\x1a\xbb\xf0\x89\x04\x86\u02d7\x99\x19\x1e\x00\x00\u07d4\x05[\xd0,\xaf\x19\xd6 +\xbc\u0703m\x18{\xd1\xc0\x1c\xf2a\x89\x05k\xc7^-c\x10\x00\x00\u07d4\x05^\xacO\x1a\xd3\xf5\x8f\v\xd0$\u058e\xa6\r\xbe\x01\u01af\xb3\x89\x05k\xc7^-c\x10\x00\x00\u07d4\x05fQU\xccI\xcb\xf6\xaa\xbd\u056e\x92\xcb\xfa\xad\x82\xb8\xc0\xc1\x89\x15\xaf\x1dx\xb5\x8c@\x00\x00\u07d4\x05f\x86\a\x8f\xb6\xbc\xf9\xba\n\x8a\x8d\xc6:\x90o_\xea\xc0\xea\x89\x1b\x18\x1eK\xf24<\x00\x00\u07d4\x05iks\x91k\xd3\x03>\x05R\x1e2\x11\xdf\xec\x02n\x98\xe4\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\x05k\x15F\x89O\x9a\x85\xe2\x03\xfb3m\xb5i\xb1l%\xe0O\x89\t.\xdb\t\xff\b\u0600\x00\u07d4\x05yI\xe1\xca\x05pF\x9eL\xe3\u0190\xaea:k\x01\xc5Y\x89\n\u05ce\xbcZ\xc6 \x00\x00\u07d4\x05}\u049f-\x19\xaa=\xa4#'\xeaP\xbc\xe8o\xf5\xc9\x11\u0649\xd8\xd7&\xb7\x17z\x80\x00\x00\u07d4\x05\u007f\u007f\x81\xcdz@o\xc4Y\x94@\x8bPI\x91,Vdc\x89\\(=A\x03\x94\x10\x00\x00\u07d4\x05\x91]N\"Zf\x81b\xae\xe7\xd6\xc2_\xcf\xc6\xed\x18\xdb\x03\x89\x03\x98\xc3ry%\x9e\x00\x00\u07d4\x05\x96\xa2}\xc3\xee\x11_\xce/\x94\xb4\x81\xbc z\x9e&\x15%\x8965\u026d\xc5\u07a0\x00\x00\u07d4\x05\xa80rC\x02\xbc\x0fn\xbd\xaa\x1e\xbe\xee\xb4nl\xe0\v9\x89\x05V\xf6L\x1f\xe7\xfa\x00\x00\u07d4\x05\xae\u007f\u053b\u0300\xca\x11\xa9\n\x1e\u01e3\x01\xf7\xcc\u0303\u06c91T\xc9r\x9d\x05x\x00\x00\u07d4\x05\xbbd\xa9\x16\xbef\xf4`\xf5\xe3\xb6C2\x11\r \x9e\x19\xae\x89\u3bb5sr@\xa0\x00\x00\xe0\x94\x05\xbfO\xcf\xe7r\xe4[\x82dC\x85.l5\x13P\xcer\xa2\x8a\x01\xb1\xaeMn.\xf5\x00\x00\x00\xe0\x94\x05\xc6@\x04\xa9\xa8&\xe9N^N\xe2g\xfa*v2\xddNo\x8a\x03m\xc4.\xbf\xf9\v\u007f\x80\x00\xe0\x94\x05\xc76\xd3e\xaa7\xb5\xc0\xbe\x9c\x12\u022d\\\xd9\x03\xc3,\xf9\x8a\x01E^{\x80\n\x86\x88\x00\x00\xe0\x94\x05\xcbl;\x00r\xd3\x11ga\xb52\xb2\x18D;S\xe8\xf6\u014a\x1e\x02\xc3\xd7\xfc\xa9\xb6(\x00\x00\u07d4\x05\xd0\xf4\xd7(\xeb\xe8.\x84\xbfYu\x15\xadA\xb6\v\xf2\x8b9\x89\u3bb5sr@\xa0\x00\x00\u07d4\x05\u058d\xada\u04fb\u07f3\xf7y&\\IGJ\xff?\xcd0\x89\x02\"\xc5]\xc1Q\x9d\x80\x00\u07d4\x05\xe6q\xdeU\xaf\xec\x96K\aM\xe5t\xd5\x15\x8d]!\xb0\xa3\x89\u0556{\xe4\xfc?\x10\x00\x00\u07d4\x05\xe9{\tI,\u058fc\xb1+\x89.\xd1\xd1\x1d\x15,\x0e\u02897\b\xba\xed=h\x90\x00\x00\u07d4\x05\xf3c\x1fVd\xbd\xad]\x012\xc88\x8d6\xd7\u0612\t\x18\x89\x01\x15\x8eF\t\x13\xd0\x00\x00\xe0\x94\x06\t\xd8:l\xe1\xff\u0276\x90\xf3\xe9\xa8\x1e\x98>\x8b\xdcM\x9d\x8a\x0e\u04b5%\x84\x1a\xdf\xc0\x00\x00\u07d4\x06\x1e\xa4\x87|\u0409D\xebd\u0096n\x9d\xb8\xde\xdc\xfe\xc0k\x8965\u026d\xc5\u07a0\x00\x00\u07d4\x06%\xd0`V\x96\x8b\x00\"\x06\xff\x91\x98\x01@$+\xfa\xa4\x99\x8965\u026d\xc5\u07a0\x00\x00\u07d4\x06(\xbf\xbeU5x/\xb5\x88@k\xc9f`\xa4\x9b\x01\x1a\xf5\x89Rf<\u02b1\xe1\xc0\x00\x00\u07d4\x061\u044b\xbb\xbd0\xd9\xe1s+\xf3n\xda\xe2\u0389\x01\xab\x80\x89\xa3\xf9\x88U\xec9\x90\x00\x00\u07d4\x061\xdc@\xd7NP\x95\xe3r\x9e\xdd\xf4\x95D\xec\xd49og\x89\b\xacr0H\x9e\x80\x00\x00\xe0\x94\x067Y\xdd\x1cN6.\xb1\x93\x98\x95\x1f\xf9\xf8\xfa\xd1\xd3\x10h\x8a\x02\x1e\x19\xe0\u027a\xb2@\x00\x00\u07d4\x06_\xf5u\xfd\x9c\x16\xd3\xcbo\u058f\xfc\x8fH?\xc3.\xc85\x89\n\u05ce\xbcZ\xc6 \x00\x00\u07d4\x06a\x8e\x9dWb\xdfb\x02\x86\x01\xa8\x1dD\x87\u05a0\xec\xb8\x0e\x89Hz\x9a0E9D\x00\x00\xe0\x94\x06fG\xcf\xc8]#\xd3v\x05W= \x8c\xa1T\xb2D\xd7l\x8a\x02\x1e\x19\xe0\u027a\xb2@\x00\x00\u07d4\x06xeJ\xc6v\x1d\xb9\x04\xa2\xf7\xe8Y^\xc1\xea\xacsC\b\x89/\x98\xb2\x9c(\x18\xf8\x00\x00\u07d4\x06\x86\n\x93RYU\xffbI@\xfa\xdc\xff\xb8\xe1I\xfdY\x9c\x89lh\xcc\u041b\x02,\x00\x00\xe0\x94\x06\x8c\xe8\xbdn\x90*E\u02c3\xb5\x15A\xb4\x0f9\xc4F\x97\x12\x8a\x01\x1c\x0f\x9b\xadJF\xe0\x00\x00\u07d4\x06\x8e)\xb3\xf1\x91\xc8\x12\xa699\x18\xf7\x1a\xb93\xaehG\xf2\x89lj\xccg\u05f1\xd4\x00\x00\u07d4\x06\x8eeWf\xb9D\xfb&6\x19e\x87@\xb8P\xc9J\xfa1\x89\x01\xe8\u007f\x85\x80\x9d\xc0\x00\x00\u0794\x06\x96N-\x17\xe9\x18\x9f\x88\xa8 96\xb4\n\xc9nS<\x06\x88\xfc\x93c\x92\x80\x1c\x00\x00\u07d4\x06\x99L\xd8:\xa2d\n\x97\xb2`\vA3\x9d\x1e\r>\xdel\x89\r\x8drkqw\xa8\x00\x00\u07d4\x06\x9e\u042bz\xa7}\xe5q\xf1a\x06\x05\x1d\x92\xaf\xe1\x95\xf2\u0409\n\u05ce\xbcZ\xc6 \x00\x00\u07d4\x06\xac&\xad\x92\u02c5\x9b\u0550]\xdc\xe4&j\xa0\xecP\xa9\u0149*\x03I\x19\u07ff\xbc\x00\x00\u07d4\x06\xb0\xc1\xe3\u007fZ^\u013b\xf5\b@T\x8f\x9d:\xc0(\x88\x97\x89\xd8\u0602\u148e}\x00\x00\u07d4\x06\xb0\xff\x83@s\xcc\xe1\xcb\xc9\xeaU~\xa8{`Yc\u8d09\x10CV\x1a\x88)0\x00\x00\xe0\x94\x06\xb1\x06d\x9a\xa8\xc4!\xdd\xcd\x1b\x8c2\xcd\x04\x18\xcf0\xda\x1f\x8a\bxg\x83&\xea\xc9\x00\x00\x00\u07d4\x06\xb5\xed\xe6\xfd\xf1\xd6\xe9\xa3G!7\x9a\xea\xa1|q=\xd8*\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\x06\xcb\xfa\b\xcd\xd4\xfb\xa77\xba\xc4\a\xbe\x82$\xf4\xee\xf3X(\x89 +\xe5\xe88.\x8b\x80\x00\u07d4\x06\xd6\xcb0\x84\x81\xc36\xa6\xe1\xa2%\xa9\x12\xf6\xe65Y@\xa1\x89_h\xe8\x13\x1e\u03c0\x00\x00\u07d4\x06\xdc\u007f\x18\xce\xe7\xed\xab[yS7\xb1\xdfj\x9e\x8b\u062eY\x89\x15\xaf\x1dx\xb5\x8c@\x00\x00\u07d4\x06\xf6\x8d\xe3\xd79\xdbA\x12\x1e\xac\xf7y\xaa\xda=\xe8v!\a\x89\x01\x84\x93\xfb\xa6N\xf0\x00\x00\u07d4\x06\xf7\u070d\x1b\x94b\xce\xf6\xfe\xb13h\xa7\xe3\x97K\t\u007f\x9f\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\a\x01\xf9\xf1G\xecHhV\xf5\xe1\xb7\x1d\xe9\xf1\x17\xe9\x9e!\x05\x89\te\xdaq\u007f\u0578\x00\x00\u07d4\a\r]6L\xb7\xbb\xf8\"\xfc,\xa9\x1a5\xbd\xd4A\xb2\x15\u0549lk\x93[\x8b\xbd@\x00\x00\xe0\x94\a\x1d\xd9\r\x14\xd4\x1fO\xf7\xc4\x13\xc2B8\xd35\x9c\xd6\x1a\a\x8a\a\xb5?y\xe8\x88\xda\xc0\x00\x00\u07d4\a&\xc4.\x00\xf4T\x04\x83n\xb1\xe2\x80\xd0s\xe7\x05\x96\x87\xf5\x89X\x00>?\xb9G\xa3\x80\x00\xe0\x94\a'\xbe\n*\x00! H\xb5R\x0f\xbe\xfb\x95>\xbc\x9dT\xa0\x8a\x02\x1e\x19\xe0\u027a\xb2@\x00\x00\xe0\x94\a)\xa8\xa4\xa5\xba#\xf5y\xd0\x02[\x1a\xd0\xf8\xa0\xd3\\\xdf\u048a\x02\r\u058a\xaf2\x89\x10\x00\x00\u07d4\a)\xb4\xb4|\t\xeb\x16\x15\x84d\u022a\u007f\xd9i\vC\x889\x89lh\xcc\u041b\x02,\x00\x00\u0794\a4\xa0\xa8\x1c\x95b\xf4\xd9\xe9\xe1\n\x85\x03\xda\x15\xdbF\xd7n\x88\xfc\x93c\x92\x80\x1c\x00\x00\xe0\x94\a<g\xe0\x9b\\q<R!\u0220\xc7\xf3\xf7Df\xc3G\xb0\x8a\x04\x1b\xad\x15^e\x12 \x00\x00\u07d4\a?\x1e\xd1\xc9\xc3\xe9\xc5*\x9b\x02I\xa5\xc1\u02a0W\x1f\xdf\x05\x89\x03\xd0\xff\v\x01;\x80\x00\x00\u07d4\aHq1E\xef\x83\xc3\xf0\xefM1\xd8#xo~\x9c\u0189\x89\xf3\xf2\v\x8d\xfai\xd0\x00\x00\u07d4\a]\x15\xe2\xd3=\x8bO\xa7\u06e8\xb9\xe6\a\xf0J&\x1e4\v\x89g\x8a\x93 b\xe4\x18\x00\x00\u07d4\aea\xa8VE]~\xf8nc\xf8|s\u06f6(\xa5_E\x890\xca\x02O\x98{\x90\x00\x00\u07d4\an\xe9\x9d5Hb:\x03\xb5\xf9\x98Y\xd2\u05c5\xa1w\x8dH\x89\n\u05ce\xbcZ\xc6 \x00\x00\u07d4\ap\xb4=\xba\xe4\xb1\xf3Z\x92{O\xa8\x12M8f\xca\xf9{\x897\x19>\xa7\xef[G\x00\x00\xe0\x94\ap\xc6\x1b\xe7\x87r#\f\xb5\xa3\xbb$)\xa7&\x14\xa0\xb36\x8a\x01n\u0899\xb7\x13A\x80\x00\u07d4\ar><0\xe8\xb71\xeeEj)\x1e\xe0\u7630 Jw\x89lk\x93[\x8b\xbd@\x00\x00\xe0\x94\as\xee\xac\xc0P\xf7G \xb4\xa1\xbdW\x89[\x1c\xce\xebI]\x8a\x02\x1e\x19\xe0\u027a\xb2@\x00\x00\xe0\x94\a\x80\r/\x80h\xe4H\u01daOi\xb1\xf1^\xf6\x82\xaa\xe5\xf6\x8a\x04\x1b\xad\x15^e\x12 \x00\x00\u07d4\a\xa8\xda\xde\xc1BW\x1a}S\xa4)pQxm\a,\xbaU\x89\x01;m\xa1\x13\x9b\u0680\x00\u07d4\a\xaf\x93\x8c\x127\xa2|\x900\tM\xcf$\aP$n=,\x89\x1b\x1a\xe4\xd6\xe2\xefP\x00\x00\xe0\x94\a\xb1\xa3\x06\xcbC\x12\xdffH,,\xaer\xd1\xe0a@\x0f\u034a\x04<3\xc1\x93ud\x80\x00\x00\u07d4\a\xb7\xa5p3\xf8\xf1\x130\xe4f^\x18]#N\x83\xec\x14\v\x89\xea~\xe9*\f\x9a\v\x80\x00\u07d4\a\xbc,\xc8\xee\xdc\x01\x97\a\x00\xef\xc9\xc4\xfb6s^\x98\xcdq\x89\xd8\xd7&\xb7\x17z\x80\x00\x00\u07d4\a\xd4\x12\x17\xba\u0725\xe0\xe6\x03'\xd8E\xa3FO\x0f'\xf8J\x89\xd8\xd7&\xb7\x17z\x80\x00\x00\u07d4\a\xd43N\u00c5\xe8\xaaT\xee\xda\xea\xdb0\x02/\f\u07e4\xab\x89\x8e\x91\xd5 \xf2\xeby\x00\x00\u07d4\a\xda\xe6\"c\r\x1168\x193\u04adk\"\xb89\xd8!\x02\x89\n\u05ce\xbcZ\xc6 \x00\x00\u07d4\a\xdc+\xf8;\u01af\x19\xa8B\xff\xeaf\x1a\xf5\xb4\x1bg\xfd\xa1\x89QP\xae\x84\xa8\xcd\xf0\x00\x00\u07d4\a\u070c\x8b\x92z\xdb\xed\xfa\x8f]c\x9bCR5\x1f/6\u0489\x11\n\xed;U0\xdb\x00\x00\u07d4\a\xdd\xd0B,\x86\xefe\xbf\f\u007f\xc3E(b\xb1\"\x8b\b\xb8\x89o\xf5\u04aa\x8f\x9f\xcf\x00\x00\u07d4\a\xe1\x16,\xea\xe3\xcf!\xa3\xf6-\x10Y\x900.0\u007fN;\x89R\xf1\x03\xed\xb6k\xa8\x00\x00\u07d4\a\xe2\xb4\xcd\xee\xd9\u0407\xb1.Um\x9ew\f\x13\xc0\x99a_\x89$=M\x18\"\x9c\xa2\x00\x00\u07d4\a\xfe\xefT\xc16\x85\b)\xba\xdcKI\xc3\xf2\xa7<\x89\xfb\x9e\x89\x06hZ\xc1\xbf\xe3,\x00\x00\u07d4\b\x05FP\x8a=&\x82\u0239\x88O\x13c{\x88G\xb4M\xb3\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\b\t\bv\xba\xad\xfe\xe6\\=6;\xa5S\x12t\x8c\xfa\x87=\x89\\*\x997\x1c\xff\xe1\x00\x00\u07d4\b\x16o\x021?\xea\u12f0D\xe7\x87|\x80\x8bU\xb5\xbfX\x89j\xcb=\xf2~\x1f\x88\x00\x00\u07d4\b)\xd0\xf7\xbb|Dl\xfb\xb0\u07ad\xb29M\x9d\xb7$\x9a\x87\x89\x02,\xa3X|\xf4\xeb\x00\x00\u07d4\b0m\xe5\x19\x81\u7b21\x85hY\xb7\xc7xijki\xf9\x89\xadx\xeb\u016cb\x00\x00\x00\xe0\x94\b7S\x9b_jR*H,\xdc\u04e9\xbbpC\xaf9\xbd\u048a\x01EB\xba\x12\xa37\xc0\x00\x00\u07d4\b8\xa7v\x8d\x9c*\u028b\xa2y\xad\xfe\xe4\xb1\xf4\x91\xe3&\xf1\x89\n\u05ce\xbcZ\xc6 \x00\x00\u07d4\bA\x16R\xc8qq6\t\xaf\x00b\xa8\xa1(\x1b\xf1\xbb\xcf\u0649K\xe4\xe7&{j\xe0\x00\x00\xe0\x94\bM\x102Tu\x9b4<\xb2\xb9\xc2\xd8\xff\x9e\x1a\xc5\xf1E\x96\x8a\x01\x9b\xff/\xf5yh\xc0\x00\x00\u07d4\bPO\x05d?\xabY\x19\xf5\xee\xa5Y%\u05e3\xed}\x80z\x89\x01\x15\x8eF\t\x13\xd0\x00\x00\u07d4\b[J\xb7]\x83b\xd9\x14C\\\xed\xee\x1d\xaa+\x1e\xe1\xa2;\x89\xd2U\xd1\x12\xe1\x03\xa0\x00\x00\u07d4\b[\xa6_\xeb\xe2>\xef\xc2\xc8\x02fj\xb1&#\x82\xcf\u0114\x89\x15\xaf\x1dx\xb5\x8c@\x00\x00\u07d4\bt\x98\xc0FFh\xf3\x11P\xf4\xd3\u013c\u0765\"\x1b\xa1\x02\x89\x01\x15\x8eF\t\x13\xd0\x00\x00\u07d4\bw\uebabx\xd5\xc0\x0e\x83\xc3+-\x98\xfay\xadQH/\x89\x17\xd2-q\xdab&\x00\x00\u0794\b\x93j7\u07c5\xb3\xa1X\xca\xfd\x9d\xe0!\xf5\x817h\x13G\x88\xfc\x93c\x92\x80\x1c\x00\x00\u07d4\b\xa9\xa4N\x1fA\xde=\xbb\xa7\xa3c\xa3\xabA,\x12L\xd1^\x89\n\u05ce\xbcZ\xc6 \x00\x00\u07d4\b\xb7\xbd\u03d4MUp\x83\x8b\xe7\x04`$:\x86\x94HXX\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\b\xb8E6\xb7L\x8c\x01T=\xa8\x8b\x84\u05cb\xb9WG\xd8\"\x89\n\u05ce\xbcZ\xc6 \x00\x00\u07d4\b\xc2\xf26\xacJ\xdc\xd3\xfd\xa9\xfb\xc6\xe4S\"S\xf9\xda;\xec\x89\x01\x15\x8eF\t\x13\xd0\x00\x00\u07d4\b\xc8\x02\xf8wX4\x9f\xa0>k\xc2\xe2\xfd\a\x91\x19~\ua689lk\x93[\x8b\xbd@\x00\x00\u07d4\b\xc9\U0007fd89\xfd\xf8\x04\xd7i\xf8!#6\x02\x15\xaf\xf9;\x89j\xcb=\xf2~\x1f\x88\x00\x00\u07d4\b\xca\u0215&A\xd8\xfcRn\xc1\xabO-\xf8&\xa5\xe7q\x0f\x89\x10CV\x1a\x88)0\x00\x00\xe0\x94\b\xcc\xdaP\xe4\xb2j\x0f\xfc\x0e\xf9.\x92\x051\a\x06\xbe\xc2\u01ca\x01Iul8W\xc6\x00\x00\x00\u07d4\b\u0406M\xc3/\x9a\xcb6\xbfN\xa4G\xe8\xddg&\x90j\x15\x89lnY\xe6|xT\x00\x00\u07d4\b\xd4&\u007f\xeb\x15\u0697\x00\xf7\xcc\xc3\xc8J\x89\x18\xbf\x17\xcf\u0789a\t=|,m8\x00\x00\xe0\x94\b\xd41\x1c\x9c\x1b\xba\xf8\u007f\xab\xe1\xa1\xd0\x14c\x82\x8d]\x98\u038a\x13\x0e\xe8\xe7\x17\x90D@\x00\x00\u07d4\b\xd5N\x83\xadHj\x93L\xfa\xea\u20e3>\xfd\"|\x0e\x99\x898S\x05\x83$^\xdc\x00\x00\u07d4\b\xd9~\xad\xfc\xb7\xb0d\xe1\xcc\xd9\u0217\x9f\xbe\xe5\xe7z\x97\x19\x89\x0el]\xa8\xd6z\xc1\x80\x00\u07d4\b\xda:z\x0fE!a\u03fc\xec1\x1b\xb6\x8e\xbf\xde\xe1~\x88\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\b\xe3\x8e\xe0\xceH\xc9\xcad\\\x10\x19\xf7;SUX\x1cV\xe6\x89V\xbcu\xe2\xd61\x00\x00\x00\u07d4\b\xef?\xa4\xc4<\xcd\xc5{\"\xa4\xb9\xb23\x1a\x82\xe58\x18\xf2\x89\xd8\xd7&\xb7\x17z\x80\x00\x00\u07d4\t\td\x8c\x18\xa3\xce[\xaez\x04~\xc2\xf8h\xd2L\u0768\x1d\x89\xcf\x15&@\xc5\xc80\x00\x00\u07d4\t\f\xd6{`\xe8\x1dT\xe7\xb5\xf6\a\x8f>\x02\x1b\xa6[\x9a\x1e\x8965\u026d\xc5\u07a0\x00\x00\u07d4\t\f\xeb\xef),>\xb0\x81\xa0_\u062a\xf7\u04db\xf0{\x89\u0509\xd8\xd7&\xb7\x17z\x80\x00\x00\u07d4\t\x0f\xa96{\xdaW\xd0\xd3%:\n\x8f\xf7l\xe0\xb8\xe1\x9as\x8965\u026d\xc5\u07a0\x00\x00\u07d4\t\x14n\xa3\x88Qv\xf0w\x82\xe1\xfe0\xdc\xe3\xce$\u011e\x1f\x89\x01\x15\x8eF\t\x13\xd0\x00\x00\u07d4\t!`_\x99\x16N;\xcc(\xf3\x1c\xae\xcex\x971\x82V\x1d\x89+\ai*\x90e\xa8\x00\x00\xe0\x94\t&\x1f\x9a\xcbE\x1c7\x88\x84O\f\x14Q\xa3[\xadP\x98\xe3\x8a\x01\u056d'P) `\x00\x00\xe0\x94\t'\"\x04\x92\x19K.\u069f\u013b\xe3\x8f%\u0581\xdf\xd3l\x8a\x01EB\xba\x12\xa37\xc0\x00\x00\u0794\t*\xcbbK\b\xc0U\x10\x18\x9b\xbb\xe2\x1ee$\xd6D\u032d\x88\xfc\x93c\x92\x80\x1c\x00\x00\u07d4\t.\x81UX@-g\xf9\rk\xfem\xa0\xb2\xff\xfa\x91EZ\x89\x03@\xaa\xd2\x1b;p\x00\x00\u07d4\tP0\xe4\xb8&\x92\xdc\xf8\xb8\u0411$\x94\xb9\xb3x\xec\x93(\x89H\xa4<T`/p\x00\x00\u07d4\tRp\xccB\x14\x1d\u0658\xad(b\xdb\xd1\xfe\x9bD\xe7\xe6P\x89A\rXj \xa4\xc0\x00\x00\u07d4\tTW\xf8\xef\x8e+\xdc6!\x96\xb9\xa9\x12]\xa0\x9cg\u3ac9\n\u05ce\xbcZ\xc6 \x00\x00\u07d4\tT\xa8\xcb]2\x1f\xc35\x1au#\xa6\x17\xd0\xf5\x8d\xa6v\xa7\x89\x87\u067cz\xa4\x98\xe8\x00\x00\xe0\x94\t[\x0e\xa2\xb2\x18\xd8.\n\xea|(\x89#\x8a9\u027f\x90w\x8a\x04<3\xc1\x93ud\x80\x00\x00\u07d4\t[\x94\x9d\xe33:7}P\x19\u0613uJ^FV\xff\x97\x89\x12nr\xa6\x9aP\xd0\x00\x00\xe0\x94\t^\x01t\x82\x9f4\xc3x\x1b\xe1\xa5\xe3\x8d\x15A\xeaC\x9b\u007f\x8a\x01EB\xba\x12\xa37\xc0\x00\x00\u07d4\t_ZQ\xd0oc@\xd8\vm)\xea.\x88\x11\x8a\xd70\xfe\x89lnY\xe6|xT\x00\x00\u07d4\th\xeeZ7\x8f\x8c\xad\xb3\xba\xfd\xbe\xd1\u045a\xaa\u03d3g\x11\x8965\u026d\xc5\u07a0\x00\x00\u07d4\tw\xbf\xba\x03\x8aD\xfbI\xb09p\xd8\xd8\xcf,\xb6\x1f\x8b%\x89\x16\u012b\xbe\xbe\xa0\x10\x00\x00\u07d4\t}\xa1,\xfc\x1f|\x1a$d\xde\xf0\x8c)\xbe\xd5\xe2\xf8Q\xe9\x89\x01\x15\x8eF\t\x13\xd0\x00\x00\u07d4\t~\u0362%g\xc2\xd9\x1c\xb0?\x8cR\x15\xc2.\x9d\u0369I\x89\x01\x16Q\xac>zu\x80\x00\u07d4\t\x89\xc2\x00D\v\x87\x89\x91\xb6\x9d`\x95\xdf\xe6\x9e3\xa2.p\x89g\x8a\x93 b\xe4\x18\x00\x00\u07d4\t\x90\xe8\x1c\u05c5Y\x9e\xa26\xbd\x19f\xcfRc\x02\xc3[\x9c\x8965\u026d\xc5\u07a0\x00\x00\u07d4\t\x98\xd8'1\x15\xb5j\xf4<P^\bz\xff\x06v\xed6Y\x89\xd8\xd6\xed\xdf-.\x18\x00\x00\u07d4\t\xa0%1o\x96\u007f\xa8\xb9\xa1\xd6\a\x00\x06?Zh\x00\x1c\xaa\x89\x02\x12!\xa9\x9b\x93\xec\x00\x00\u0794\t\xa9(\xd5(\xec\x1b>%\xff\xc8>!\x8c\x1e\n\xfe\x89(\u01c8\xfc\x93c\x92\x80\x1c\x00\x00\u07d4\t\xaeI\xe3\u007f\x12\x1d\xf5\xdc\x15\x8c\xfd\xe8\x06\xf1s\xa0k\f\u007f\x89\xd80\x9e&\xab\xa1\xd0\x00\x00\u07d4\t\xaf\xa7;\xc0G\xefF\xb9w\xfd\x97c\xf8r\x86\xa6\xbeh\u0189\x1b/\xb5\xe8\xf0jf\x00\x00\u07d4\t\xb4f\x86\x96\xf8j\b\x0f\x8b\xeb\xb9\x1d\xb8\xe6\xf8p\x15\x91Z\x89#\x8f\xf7\xb3O`\x01\x00\x00\xe0\x94\t\xb5\x9b\x86\x98\xa7\xfb\xd3\xd2\xf8\xc7:\x00\x89\x88\xde>@k+\x8a\bxg\x83&\xea\xc9\x00\x00\x00\xe0\x94\t\xb7\xa9\x88\xd1?\xf8\x91\x86so\x03\xfd\xf4au\xb5=\x16\xe0\x8a\x01EB\xba\x12\xa37\xc0\x00\x00\xe0\x94\t\xc1w\xf1\xaeD$\x11\u076c\xf1\x87\xd4m\xb9V\x14\x83`\xe7\x8a\x01\xe5.3l\xde\"\x18\x00\x00\xe0\x94\t\u020f\x91~Mj\xd4s\xfa\x12\u93a3\xc4G*^\xd6\u068a\x02\x1e\x19\xe0\u027a\xb2@\x00\x00\u07d4\t\u0438\xcd\a|i\xd9\xf3-\x9c\xcaC\xb3\xc2\b\xa2\x1e\u050b\x89\b!\xd2!\xb5)\x1f\x80\x00\xe0\x94\t\xd6\xce\xfdu\xb0\u0133\xf8\xf1\u0587\xa5\"\xc9a#\xf1\xf59\x8a\x01EB\xba\x12\xa37\xc0\x00\x00\xe0\x94\t\xe47\xd4H\x86\x12(\xa22\xb6.\xe8\xd3ye\xa9\x04\ud70a\x04\x98\xcf@\x1d\xf8\x84.\x80\x00\u07d4\t\xee\x12\xb1\xb4+\x05\xaf\x9c\xf2\a\xd5\xfc\xac%[.\xc4\x11\xf2\x89\x031\xcd\xddG\xe0\xfe\x80\x00\u07d4\t\xf3\xf6\x01\xf6\x05D\x11@Xl\xe0eo\xa2J\xa5\xb1\u066e\x89Sswo\xe8\xc4T\x00\x00\u07d4\t\xf9W[\xe5}\x00G\x93\u01e4\ub137\x15\x87\xf9|\xbbj\x89\n\u05ce\xbcZ\xc6 \x00\x00\u07d4\n\x06P\x86\x1fx^\xd8\xe4\xbf\x10\x05\xc4P\xbb\xd0n\xb4\x8f\xb6\x89\xa6A;y\x14N~\x00\x00\u07d4\n\x06\xfa\xd7\xdc\u05e4\x92\xcb\xc0S\xee\xab\xdei4\xb3\x9d\x867\x89\x01\x15\x8eF\t\x13\xd0\x00\x00\u07d4\n\a}\xb1?\xfe\xb0\x94\x84\xc2\x17p\x9dX\x86\xb8\xbf\x9cZ\x8b\x89\xd8\xd7&\xb7\x17z\x80\x00\x00\u07d4\n\x0e\u0366cow\x16\xef\x19saF\x87\xfd\x89\xa8 \xa7\x06\x89\x15[\xd90\u007f\x9f\xe8\x00\x00\u07d4\n)\xa8\xa4\xd5\xfd\x95\x00u\xff\xb3Mw\xaf\xeb-\x82;\u0589\x89\n\u05ce\xbcZ\xc6 \x00\x00\u07d4\n*\u0795\xb2\xe8\xc6m\x8a\xe6\xf0\xbad\xcaW\u05c3\xbemD\x89\xd8\xd7&\xb7\x17z\x80\x00\x00\u07d4\n+O\xc5\xd8\x1a\xceg\xdcK\xba\x03\xf7\xb4UA=F\xfe=\x89\n\xad\xec\x98?\xcf\xf4\x00\x00\u07d4\n-\xcbzg\x17\x01\u06f8\xf4\x95r\x80\x88&Xs5l\x8e\x89\b?\x16\xce\b\xa0l\x00\x00\u07d4\n=\xe1U\xd5\xec\xd8\xe8\x1c\x1f\xf9\xbb\xf07\x83\x01\xf8\xd4\xc6#\x89\xd8\xd7&\xb7\x17z\x80\x00\x00\u07d4\nG\xad\x90Y\xa2I\xfc\x93k&b5=\xa6\x90_u\u00b9\x89lk\x93[\x8b\xbd@\x00\x00\xe0\x94\nH)ov1p\x8c\x95\u04b7Iu\xbcJ\xb8\x8a\xc19*\x8a\x01\x0f\f\xf0d\xddY \x00\x00\xe0\x94\nJ\x01\x19\x95\u0181\xbc\x99\x9f\xddyuN\x9a2J\xe3\xb3y\x8a\b\xc1\x9a\xb0n\xb8\x9a\xf6\x00\x00\u07d4\nX\xfd\xddq\x89\x8d\xe7s\xa7O\xda\xe4^{\xd8N\xf46F\x89\x01\x15\x8eF\t\x13\xd0\x00\x00\u07d4\n[y\xd8\xf2;d\x83\xdb\u2f6ab\xb1\x06L\xc7cf\xae\x89j\u0202\x10\tR\u01c0\x00\u07d4\ne.*\x8bw\xbd\x97\xa7\x90\xd0\xe9\x13a\u0248\x90\u06f0N\x8965\u026d\xc5\u07a0\x00\x00\u07d4\nn\xber;n\xd1\xf9\xa8ji\xdd\xdah\xdcGF\\+\x1b\x89@=-\xb5\x99\xd5\xe4\x00\x00\u07d4\nw\xe7\xf7+C{WO\x00\x12\x8b!\xf2\xac&Q3R\x8c\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\n\x91\u007f;\\\xb0\xb8\x83\x04\u007f\u0676Y=\xbc\xd5W\xf4S\xb9\x8965\u026d\xc5\u07a0\x00\x00\u07d4\n\x93\x1bD\x9e\xa8\xf1,\xdb\xd5\xe2\xc8\xccv\xba\xd2\xc2|\x069\x89\x01?\x9e\x8cy\xfe\x05\x80\x00\u0794\n\x98\x04\x13x\x03\xbahh\xd9:U\xf9\x98_\xcdT\x04Q\u4239\x8b\xc8)\xa6\xf9\x00\x00\u07d4\n\x9a\xb2c\x8b\x1c\xfdeM%\u06b0\x18\xa0\xae\xbd\u07c5\xfdU\x89\x01.\x8c\xb5\xfeLJ\x80\x00\u07d4\n\xb3f\xe6\xe7\u056b\xbc\xe6\xb4JC\x8di\xa1\u02bb\x90\xd13\x89\x11X\xe4`\x91=\x00\x00\x00\u07d4\n\xb4(\x1e\xbb1\x85\x90\xab\xb8\x9a\x81\xdf\a\xfa:\xf9\x04%\x8a\x89\x1b\x1a\xe4\xd6\xe2\xefP\x00\x00\u0794\n\xb5\x9d9\a\x02\xc9\xc0Y\xdb\x14\x8e\xb4\xf3\xfc\xfa}\x04\xc7\xe7\x88\xfc\x93c\x92\x80\x1c\x00\x00\xe0\x94\n\xbf\xb3\x9b\x11HmyW(f\x19[\xa2lc\vg\x84\u06ca\x19\xba\x877\xf9i(\xf0\x00\x00\u07d4\n\u029aV&\x91;\b\xcf\u0266m@P\x8d\xceR\xb6\x0f\x87\x89g\x8a\x93 b\xe4\x18\x00\x00\u07d4\n\xd3\xe4M<\x00\x1f\xa2\x90\xb3\x93ap0TA\b\xacn\xb9\x89j\xbd\xa0\xbc0\xb2\u07c0\x00\u07d4\n\xec.Bn\xd6\xcc\f\xf3\xc2I\xc1\x89~\xacG\xa7\xfa\xa9\xbd\x89\n\u05ce\xbcZ\xc6 \x00\x00\u07d4\n\xf6_\x14xNU\xa6\xf9Vg\xfds%*\x1c\x94\a-*\x89\nv;\x8e\x02\xd4O\x80\x00\u07d4\n\xf6\xc8\xd59\xc9mP%\x9e\x1b\xa6q\x9e\x9c\x80`\xf3\x88\u008965\u026d\xc5\u07a0\x00\x00\u07d4\v\x069\x0f$7\xb2\x0e\u0123\xd3C\x1b2y\xc6X>^\u05c9\n\x84Jt$\xd9\xc8\x00\x00\u07d4\v\v8b\x11*\xee\u00e04\x92\xb1\xb0_D\x0e\xcaT%n\x89\xd8\xd7&\xb7\x17z\x80\x00\x00\u07d4\v\x0e\x05[(\xcb\xd0=\xc5\xffD\xaad\xf3\xdc\xe0O^c\xfb\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\v\x11\x9d\xf9\x9ck\x8d\xe5\x8a\x1e,?)zgD\xbfU\"w\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\v\x14\x89\x19\x99\xa6\\\x9e\xf73\b\xef\xe3\x10\f\xa1\xb2\x0e\x81\x92\x89+^:\xf1k\x18\x80\x00\x00\u07d4\v!\x13PE4d*\x1d\xaf\x10.\xee\x10\xb9\xeb\xdev\xe2a\x89\x94,\xdd|\x95\xf2\xbd\x80\x00\xe0\x94\v(\x8aZ\x8bu\xf3\xdcA\x91\xeb\x04W\xe1\xc8=\xbd M%\x8a\x01\a\x14\xe7{\xb4:\xb4\x00\x00\u07d4\v6\x9e\x00.\x1bLy\x13\xfc\xf0\x0f-^\x19\u0141eG\x8f\x89\x03\u007fe\x16(\x8c4\x00\x00\u07d4\vC\xbd#\x91\x02U\x81\u0615l\xe4*\a%y\u02ff\xcb\x14\x89\x01\x04\xe7\x04d\xb1X\x00\x00\u07d4\vP|\xf5SV\x8d\xaa\xf6U\x04\xaeN\xaa\x17\xa8\xea<\xdb\xf5\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\v]f\xb1<\x87\xb3\x92\xe9M\x91\xd5\xf7l\rE\nU(C\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\v^ \x11\xeb\xc2Z\x00\u007f!6)`I\x8a\xfb\x8a\xf2\x80\xfb\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\vd\x9d\xa3\xb9j\x10,\xdcm\xb6R\xa0\xc0}e\xb1\xe4C\xe6\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\vi \xa6K6;\x8d]\x90\x80$\x94\xcfVKT|C\r\x89A\rXj \xa4\xc0\x00\x00\u07d4\vp\x11\x01\xa4\x10\x9f\x9c\xb3`\xdcW\xb7tBg=^Y\x83\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\vq\xf5T\x12$i\uf5ce/\x1f\xef\xd7\u02f4\x10\x98'r\x89\xd2U\xd1\x12\xe1\x03\xa0\x00\x00\xe0\x94\v{\xb3B\xf0\x1b\u0248\x8ej\x9a\xf4\xa8\x87\xcb\xf4\xc2\xdd,\xaf\x8a\x03c\\\x9a\xdc]\xea\x00\x00\x00\u07d4\v}3\x93q\xe5\xbeg'\xe6\xe31\xb5\x82\x1f\xa2K\u06ddZ\x89.\u007f\x81\x86\x82b\x01\x00\x00\u07d4\v\u007f\xc9\xdd\xf7\x05v\xf63\x06i\xea\xaaq\xb6\xa81\xe9\x95(\x89\a\x96\xe3\xea?\x8a\xb0\x00\x00\u07d4\v\x80\xfcp(,\xbd\xd5\xfd\xe3[\xf7\x89\x84\xdb;\xdb\x12\x01\x88\x8968\x02\x1c\xec\u06b0\x00\x00\u07d4\v\x92M\xf0\a\xe9\xc0\x87\x84\x17\xcf\xe6;\x97n\xa1\xa3\x82\xa8\x97\x89\x02+\x1c\x8c\x12'\xa0\x00\x00\u07d4\v\x93\xfc\xa4\xa4\xf0\x9c\xac \xdb`\xe0e\xed\xcc\xcc\x11\u0976\x89\n\u05ce\xbcZ\xc6 \x00\x00\u07d4\v\x9d\xf8\x0f\xbe# \t\xda\xcf\n\xa8\xca\u0153v\xe2Gb\x03\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\v\xa6\xe4j\xf2Z\x13\xf5qi%Z4\xa4\xda\xc7\xce\x12\xbe\x04\x89\x1b\x1a\xe4\xd6\xe2\xefP\x00\x00\u07d4\v\xa8p[\xf5\\\xf2\x19\xc0\x95k^?\xc0\x1cDt\xa6\xcd\xc1\x89\x05%\xe0Y]Mk\x80\x00\u07d4\v\xafn\u0379\x1a\xcb6\x06\xa85|\v\xc4\xf4\\\xfd-~o\x8965\u026d\xc5\u07a0\x00\x00\u07d4\v\xb0_r$\xbbX\x04\x85eV\xc0~\xea\xdb\ud1fa\x8f|\x89\x15\xbeat\xe1\x91.\x00\x00\u07d4\v\xb0\xc1&\x82\xa2\xf1\\\x9bWA\xb28\\\xbeA\xf04\x06\x8e\x89QP\xae\x84\xa8\xcd\xf0\x00\x00\u07d4\v\xb2\\\xa7\u0448\xe7\x1eMi={\x17\a\x17\xd6\xf8\xf0\xa7\n\x89\x12C\x02\xa8/\xad\xd7\x00\x00\u07d4\v\xb2e\x0e\xa0\x1a\xcau[\xc0\xc0\x17\xb6K\x1a\xb5\xa6m\x82\xe3\x89Hz\x9a0E9D\x00\x00\u07d4\v\xb5Lr\xfdf\x10\xbf\xa463\x97\xe0 8K\x02+\fI\x89Hz\x9a0E9D\x00\x00\u07d4\v\xb7\x16\n\xba)7b\xf8sO>\x03&\xff\u0264\xca\xc1\x90\x8965\u026d\xc5\u07a0\x00\x00\u07d4\v\xc9\\\xb3-\xbbWL\x83/\xa8\x17J\x815m8\xbc\x92\xac\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\v\xd6}\xbd\xe0z\x85n\xbd\x89;^\xdcO:[\xe4 &\x16\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\v\xdb\xc5L\u023d\xbb\xb4\x02\xa0\x89\x11\xe2#*T`\u0386k\x89\xa2\xa1]\tQ\x9b\xe0\x00\x00\u07d4\v\xddX\xb9n|\x91m\xd2\xfb05o*\xeb\xfa\xaf\x1d\x860\x89lk\x93[\x8b\xbd@\x00\x00\xe0\x94\v\u1f39\x03C\xfa\xe501s\xf4a\xbd\x91JH9\x05l\x8a\x01EB\xba\x12\xa37\xc0\x00\x00\u07d4\v\xe1\xfd\xf6&\xeea\x89\x10-p\xd1;1\x01,\x95\xcd\x1c\u0589lk\x93[\x8b\xbd@\x00\x00\u07d4\v\xe2\xb9J\xd9P\xa2\xa6&@\xc3[\xfc\xcdlg\xda\xe4P\xf6\x89i*\xe8\x89p\x81\xd0\x00\x00\xe0\x94\v\u681eC\a\xfeH\xd4\x12\xb8\u0461\xa8(M\xceHba\x8a\x04\x0f\xbf\xf8\\\x0180\x00\x00\u07d4\v\xef\xb5G\a\xf6\x1b,\x9f\xb0G\x15\xab\x02n\x1b\xb7 B\xbd\x89\xd8\xd7&\xb7\x17z\x80\x00\x00\u07d4\v\xf0dB\x8f\x83bg\"\xa7\xb5\xb2j\x9a\xb2\x04!\xa7r>\x89\a?u\u0460\x85\xba\x00\x00\u07d4\v\xfb\xb6\x92]\xc7^R\xcf&\x84\"K\xbe\x05P\xfe\xa6\x85\u04c9j\xcb=\xf2~\x1f\x88\x00\x00\u07d4\f\b\x80\x06\xc6K0\xc4\u076f\xbc6\xcb_\x05F\x9e\xb6(4\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\f s\xbaD\xd3\u077d\xb69\xc0N\x19\x109\xa7\x17\x16#\u007f\x89M\x85<\x8f\x89\b\x98\x00\x00\xe0\x94\f\",|A\u0270H\xef\xcc\xe0\xa22CCb\xe1-g;\x8a\x02\x1e\x83Yivw8\x00\x00\xe0\x94\f(\b\xb9Q\ud787-{2y\x0f\xccY\x94\xaeA\xff\u070a\x15\x99n[<\u05b3\xc0\x00\x00\u07d4\f(\x84~O\t\xdf\xce_\x9b%\xaf|NS\x0fY\u0200\xfe\x8965\u026d\xc5\u07a0\x00\x00\u07d4\f-\\\x92\x058\xe9S\u02af$\xf0s\u007fUL\u0192wB\x8965\u026d\xc5\u07a0\x00\x00\u07d4\f0\xca\xcc?r&\x9f\x8bO\x04\xcf\a=+\x05\xa8=\x9a\u0449lyt\x12?d\xa4\x00\x00\u07d4\f29\xe2\xe8A$-\xb9\x89\xa6\x15\x18\xc2\"G\xe8\xc5R\b\x89\x0eJ\xf6G\x174d\x00\x00\xe0\x94\fH\r\xe9\xf7F\x10\x02\x90\x8bI\xf6\x0f\xc6\x1e+b\xd3\x14\v\x8a\x02\x1e\x19\xe0\u027a\xb2@\x00\x00\u07d4\fH\xaeb\xd1S\x97\x88\xeb\xa0\x13\xd7^\xa6\vd\xee\xbaN\x80\x89w\xfb\xdcC\xe00\x99\x80\x00\u07d4\fU\x89\xa7\xa8\x9b\x9a\xd1[\x02u\x190AYH\xa8u\xfb\xef\x89\x06\u0519\xeclc8\x00\x00\u07d4\fg\x03=\xd8\xee\u007f\f\x8a\xe54\xd4*Q\xf7\xd9\xd4\xf7\x97\x8f\x89\n\u05ce\xbcZ\xc6 \x00\x00\u07d4\fhE\xbfA\xd5\xee'<>\u6d70\u059fo\xd5\xea\xbb\xf7\x89\xa2\xa1\xb9h.X\t\x00\x00\xe0\x94\f\u007f\x86\x9f\x8e\x90\xd5?\xdc\x03\u8c81\x9b\x01k\x9d\x18\xeb&\x8a\x04<3\xc1\x93ud\x80\x00\x00\u07d4\f\x86\x92\xee\xff*S\xd6\xd1h\x8e\xd5j\x9d\u06fdh\u06bb\xa1\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\f\x8ff\xc6\x01{\xce[ 4r\x04\xb6\x02\xb7C\xba\u05cd`\x89lk\x93[\x8b\xbd@\x00\x00\xe0\x94\f\x8f\xd7w^T\xa6\xd9\u0263\xbf\x89\x0ev\x1fewi?\xf0\x8a\x02\x15\xf85\xbcv\x9d\xa8\x00\x00\u07d4\f\x92Z\xd5\xeb5,\x8e\xf7m\f\"-\x11[\a\x91\xb9b\xa1\x89\xacc]\u007f\xa3N0\x00\x00\u07d4\f\x96~0a\xb8zu>\x84P~\xb6\t\x86x,\x8f0\x13\x89\x05k\xc7^-c\x10\x00\x00\xe0\x94\f\xa1*\xb0\xb9fl\xf0\xce\xc6g\x1a\x15)/&SGj\xb2\x8a,x'\xc4-\"\xd0|\x00\x00\u07d4\f\xa6p\xeb,\x8b\x96\u02e3y!\u007fY)\u00b8\x92\xf3\x9e\xf6\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\f\xae\x10\x8em\xb9\x9b\x9ecxv\xb0d\xc60>\u068ae\u0209\xa2\xa1]\tQ\x9b\xe0\x00\x00\u07d4\f\xbd\x92\x1d\xbe\x12\x15c\xb9\x8ahq\xfe\xcb\x14\xf1\xcc~\x88\u05c9\n\u05ce\xbcZ\xc6 \x00\x00\u07d4\f\xbf\x87p\xf0\xd1\b.\\ \u016e\xad4\xe5\xfc\xa9\xaez\xe2\x8965\u026d\xc5\u07a0\x00\x00\u07d4\f\xc6\u007f\x82s\xe1\xba\xe0\x86\u007f\xd4.\x8b\x81\x93\xd7&y\xdb\xf8\x89\x1b\x1a\xe4\xd6\xe2\xefP\x00\x00\u07d4\f\u05a1A\x91\x8d\x12k\x10m\x9f.\xbfi\xe1\x02\xdeM2w\x89\x01\x15\x8eF\t\x13\xd0\x00\x00\xe0\x94\f\xda\x12\xbfr\xd4a\xbb\xc4y\xeb\x92\xe6I\x1d\x05~kZ\u044a\x02\x1e\x19\xe0\u027a\xb2@\x00\x00\u07d4\f\u0716\v\x99\x8c\x14\x19\x98\x16\r\xc1y\xb3l\x15\u0484p\xed\x89\x1b\x1bk\u05efd\xc7\x00\x00\xe0\x94\f\xfb\x17#5\xb1l\x87\xd5\x19\xcd\x14uS\r W\u007f^\x0e\x8a\x15-\x02\xc7\xe1J\xf6\x80\x00\x00\xe0\x94\r\x1f*Wq>\xbcn\x94\xde)\x84n\x88D\xd3vfWc\x8a\x01\x0f\f\xf0d\xddY \x00\x00\u07d4\r2e\xd3\u7f79=^\x8e\x8b\x1c\xa4\u007f!\ny>\u030e\x89\n\u05ce\xbcZ\xc6 \x00\x00\u07d4\r5@\x8f\"ef\x11o\xb8\xac\u06a9\xe2\xc9\u055bvh?\x892\xf5\x1e\u06ea\xa30\x00\x00\u07d4\rU\x1e\xc1\xa2\x13<\x98\x1d_\u01a8\xc8\x17?\x9e|OG\xaf\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\r]\x98V\\d|\xa5\xf1w\xa2\xad\xb9\xd3\x02/\xac(\u007f!\x89\n\u05ce\xbcZ\xc6 \x00\x00\xe0\x94\re\x80\x14\xa1\x99\x06\x1c\xf6\xb3\x943\x14\x03\x03\xc2\x0f\xfdNZ\x8a\x01\xbc\x85\xdc*\x89\xbb \x00\x00\u07d4\rg\x87\x06\xd07\x18\u007f>\"\xe6\xf6\x9b\x99\xa5\x92\xd1\x1e\xbcY\x89U\xa6\xe7\x9c\xcd\x1d0\x00\x00\u07d4\ri\x10\f9\\\xe6\xc5\xea\xad\xf9]\x05\xd8r\x83~\xde\xdd!\x89\x15\xaf\x1dx\xb5\x8c@\x00\x00\xe0\x94\rt~\u559b\xf7\x9dW8\x1do\xe3\xa2@l\xd0\xd8\xce'\x8a\x15-\x02\xc7\xe1J\xf6\x80\x00\x00\u07d4\r\x80#\x92\x9d\x91r4\xae@Q+\x1a\xab\xb5\xe8\xa4Q'q\x89\b\x05\xe9\x9f\xdc\xc5\xd0\x00\x00\xe0\x94\r\x8a\xab\x8ft\xea\x86,\xdfvh\x05\x00\x9d?>B\xd8\xd0\v\x8a\x01;\x80\xb9\x9cQ\x85p\x00\x00\u07d4\r\x8c@\xa7\x9e\x18\x99O\xf9\x9e\xc2Q\xee\x10\u0408\u00d1.\x80\x89\x066d\xfc\u04bb\xc4\x00\x00\u07d4\r\x8e\xd7\xd0\xd1V83\x0e\xd7\xe4\xea\u032b\x8aE\x8dus~\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\r\x92X/\u06e0^\xab\xc3\xe5\x158\xc5m\xb8\x817\x85\xb3(\x89\nZ\xa8P\t\xe3\x9c\x00\x00\u07d4\r\x94C\xa7\x94h\xa5\xbb\xf7\xc1<n\"]\x1d\xe9\x1a\xee\a\u07c9\x03\xcbq\xf5\x1f\xc5X\x00\x00\xe0\x94\r\x9a\x82_\xf2\xbc\u04d7\u02ed[q\x1d\x9d\u0315\xf1\xcc\x11-\x8a\x02\xb5\xe3\xaf\x16\xb1\x88\x00\x00\x00\u07d4\r\x9d?\x9b\u0124\xc6\xef\xbdYg\x9bi\x82k\xc1\xf6=\x99\x16\x89 \x86\xac5\x10R`\x00\x00\u07d4\r\xa52\xc9\x10\xe3\xac\r\xfb\x14\xdba\xcds\x9a\x935?\xd0_\x89Hx\xbe\x1f\xfa\xf9]\x00\x00\u07d4\r\xa7@\x12b8N.\x8bK&\xdd\x15G\x99\xb5QE\uf809\x10CV\x1a\x88)0\x00\x00\u07d4\r\xae>\xe5\xb9\x15\xb3d\x87\xf9\x16\x1f\x19\x84m\x10\x1431\x8a\x89g\x8a\x93 b\xe4\x18\x00\x00\u07d4\r\xbdA|7+\x8b\r\x01\xbc\xd9Dpk\xd3.`\xae(\u0449\x12nr\xa6\x9aP\xd0\x00\x00\u07d4\r\xc1\x00\xb1\a\x01\x1c\u007f\xc0\xa13\x96\x12\xa1l\xce\xc3(R\b\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\r\u03dd\x8c\x98\x04E\x9fd|\x14\x13\x8e\xd5\x0f\xadV;AT\x89\t`\xdbwh\x1e\x94\x00\x00\u07d4\r\xcf\xe87\xea\x1c\xf2\x8ce\xfc\xce\u00fe\xf1\xf8NY\xd1P\xc0\x89\n\u05ce\xbcZ\xc6 \x00\x00\u07d4\r\xd4\xe6t\xbb\xad\xb1\xb0\u0702D\x98q=\xce;QV\xda)\x89\t79SM(h\x00\x00\u07d4\r\xfb\u0501pP\xd9\x1d\x9db\\\x02\x05<\xf6\x1a>\xe2\x85r\x89\x12nr\xa6\x9aP\xd0\x00\x00\u07d4\x0e\x02N\u007f\x02\x9cj\xaf:\x8b\x91\x0f^\b\bs\xb8W\x95\xaa\x8965\u026d\xc5\u07a0\x00\x00\u07d4\x0e\tdl\x99\xafC\x8e\x99\xfa'L\xb2\xf9\xc8V\xcbe\xf76\x89g\x8a\x93 b\xe4\x18\x00\x00\u07d4\x0e\f\x9d\x00^\xa0\x16\u0095\xcdy\\\xc9!>\x87\xfe\xbc3\xeb\x89\n\xbb\xcdN\xf3wX\x00\x00\u07d4\x0e\rf3\xdb\x1e\f\u007f#Jm\xf1c\xa1\x0e\n\xb3\x9c \x0f\x89\n\u05ce\xbcZ\xc6 \x00\x00\u07d4\x0e\x11\xd7z\x89w\xfa\xc3\r&\x84E\xe51\x14\x9b1T\x1a$\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\x0e\x12=}\xa6\xd1\xe6\xfa\xc2\u072d\xd2p)$\v\xb3\x90R\xfe\x8965\u026d\xc5\u07a0\x00\x00\u07d4\x0e\x18\x01\xe7\vbb\x86\x1b\x114\u033c9\x1fV\x8a\xfc\x92\xf7\x89\xd8\xd7&\xb7\x17z\x80\x00\x00\u07d4\x0e \x94\xac\x16T\xa4k\xa1\xc4\u04e4\v\xb8\xc1}\xa7\U000d6209\x13h?\u007f<\x15\xd8\x00\x00\u07d4\x0e!\xaf\x1b\x8d\xbf'\xfc\xf6?7\xe0G\xb8z\x82\\\xbe|'\x89\xa2\xa1]\tQ\x9b\xe0\x00\x00\u07d4\x0e.PJ-\x11\"\xb5\xa9\xfe\xee\\\xb1E\x1b\xf4\u00ac\xe8{\x89\u0556{\xe4\xfc?\x10\x00\x00\u07d4\x0e/\x8e(\xa6\x81\xf7|X;\xd0\xec\xde\x16cK\xdd~\x00\u0349\x05'8\xf6Y\xbc\xa2\x00\x00\u07d4\x0e2\x02\x19\x83\x8e\x85\x9b/\x9f\x18\xb7.=@s\xcaP\xb3}\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\x0e3\xfc\xbb\xc0\x03Q\v\xe3W\x85\xb5*\x9c]!k\xc0\x05\xf4\x89e\xea=\xb7UF`\x00\x00\u07d4\x0e6\x96\xcf\x1fB\x17\xb1c\u047c\x12\xa5\xeas\x0f\x1c2\xa1J\x89\xd8\xd7&\xb7\x17z\x80\x00\x00\u07d4\x0e9\x0fD\x05=\xdf\xce\xf0\xd6\b\xb3^M\x9c,\xbe\x98q\xbb\x89j\xcb=\xf2~\x1f\x88\x00\x00\u07d4\x0e:(\xc1\u07ef\xb0P[\xdc\xe1\x9f\xe0%\xf5\x06\xa6\xd0\x1c\xeb\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\x0e=\xd7\xd4\xe4)\xfe90\xa6A@5\xf5+\xdcY\x9dxM\x89\x02,\xa3X|\xf4\xeb\x00\x00\u07d4\x0eGey\x03Rek\xc6Vh,$\xfc^\xf3\xe7j#\u01c9\x02\x86\xd7\xfc\f\xb4\xf5\x00\x00\u07d4\x0eI\x88\x00Dqw\xb8\u022f\xc3\xfd\xfa\u007fi\xf4\x05\x1b\xb6)\x89t\x05\xb6\x9b\x8d\xe5a\x00\x00\u07d4\x0ek\xaa\xa3\u07b9\x89\xf2\x89b\x00vf\x86\x18\xe9\xac3(e\x89\n\u05ce\xbcZ\xc6 \x00\x00\xe0\x94\x0el\xd6d\xad\x9c\x1e\xd6K\xf9\x87I\xf4\x06D\xb6&\xe3y,\x8a\f\xb4\x9bD\xba`-\x80\x00\x00\xe0\x94\x0em\xfdU;.\x87=*\xec\x15\xbd_\xbb?\x84r\xd8\u04d4\x8a\x02\x8a\x85t%Fo\x80\x00\x00\u07d4\x0en\xc3\x137bq\xdf\xf5T#\xabT\"\xcc:\x8b\x06\xb2+\x89\xd8\xd7&\xb7\x17z\x80\x00\x00\xe0\x94\x0en\u0399\x11\x1c\xad\x19a\xc7H\xed=\xf5\x1e\xddi\u04a3\xb1\x8a\x15-\x02\xc7\xe1J\xf6\x80\x00\x00\u07d4\x0e\x83\xb8PH\x1a\xb4MI\xe0\xa2)\xa2\xe4d\x90,iS\x9b\x89\x05k\xc7^-c\x10\x00\x00\u07d4\x0e\x89\xed\xdd?\xa0\xd7\x1d\x8a\xb0\xff\x8d\xa5X\x06\x86\xe3\xd4\xf7O\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\x0e\x90\x96\xd3C\xc0`\xdbX\x1a\x12\x01\x12\xb2x`~\xc6\xe5+\x89\x01\x15\x8eF\t\x13\xd0\x00\x00\xe0\x94\x0e\x9cQ\x18d\xa1w\xf4\x9b\xe7\x82\x02w?`H\x9f\xe0NR\x8a\x01EB\xba\x12\xa37\xc0\x00\x00\xe0\x94\x0e\xa2\xa2\x101+>\x86~\xe0\xd1\xcch,\xe1\xd6f\xf1\x8e\u054a\x02\x1e\x19\xe0\u027a\xb2@\x00\x00\u07d4\x0e\xb1\x89\xef,-Wb\xa9c\u05b7\xbd\xf9i\x8e\xa8\u7d0a\x89Hz\x9a0E9D\x00\x00\xe0\x94\x0e\xb5\xb6b\xa1\xc7\x18`\x8f\xd5/\f%\xf97\x880\x17\x85\x19\x8a\x01J7(\x1aa.t\x00\x00\xe0\x94\x0e\xc4f\x96\xff\xac\x1fX\x00_\xa8C\x98$\xf0\x8e\xed\x1d\xf8\x9b\x8a\x02\x1e\x19\xe0\u027a\xb2@\x00\x00\xe0\x94\x0e\xc5\n\xa8#\xf4e\xb9FK\v\xc0\u0125w$\xa5U\xf5\u058a\f\x83\xd1Bj\u01f1\xf0\x00\x00\u07d4\x0e\xc50\x8b1(.!\x8f\xc9\xe7Y\xd4\xfe\xc5\xdb7\b\xce\u01096C\xaady\x86\x04\x00\x00\u07d4\x0e\xcc\xf6\x17\x84O\xd6\x1f\xbab\xcb\x0eD[z\u018b\xcc\x1f\xbe\x89\x14\xfeO\xe65e\xc6\x00\x00\u07d4\x0e\u04fb:N\xb5T\xcf\u0297\x94}WU\a\xcd\xfdm!\u0609\x1d\xb3 _\xcc#\u0540\x00\u07d4\x0e\xd7l,;]P\xff\x8f\xb5\v>\xea\xcdh\x15\x90\xbe\x1c-\x89\x05k\xc7^-c\x10\x00\x00\u07d4\x0e\u0680\xf4\xed\aJ\xeaiz\xed\xdf(;c\xdb\xca=\xc4\u0689lk\x93[\x8b\xbd@\x00\x00\u07d4\x0e\xddKX\x0f\xf1\x0f\xe0lJ\x03\x11b9\xef\x96b+\xae5\x89\n\xad\xec\x98?\xcf\xf4\x00\x00\u07d4\x0e\xe3\x91\xf0<v[\x11\u0590&\xfd\x1a\xb3S\x95\xdc8\x02\xa0\x89\n\u05ce\xbcZ\xc6 \x00\x00\u07d4\x0e\xe4\x14\x94\x04\x87\xfd$\xe3\x907\x82\x85\xc5\u05f93M\x8be\x89\x91Hx\xa8\xc0^\xe0\x00\x00\u07d4\x0e\xf5J\xc7&M\"T\xab\xbb_\x8bA\xad\u0787QW\xdb|\x89\x02+\x1c\x8c\x12'\xa0\x00\x00\u07d4\x0e\xf8[I\u040au\x19\x86\x92\x91N\u0774\xb2,\xf5\xfaDP\x89l\xae0b\x1dG \x00\x00\u07d4\x0e\xfd\x17\x89\xeb\x12D\xa3\xde\xde\x0f]\xe5\x82\u0616<\xb1\xf3\x9f\x89QP\xae\x84\xa8\xcd\xf0\x00\x00\xe0\x94\x0f\x04,\x9c/\xb1\x87f\xf86\xbbY\xf75\xf2}\xc3)\xfe<\x8a\x02\x1e\x19\xe0\u027a\xb2@\x00\x00\u07d4\x0f\x04\x9a\x8b\xdf\xd7a\u078e\xc0,\xee()\xc4\x00[#\xc0k\x89\r\xa93\xd8\xd8\xc6p\x00\x00\xe0\x94\x0f\x05\xf1 \u021e\x9f\xbc\x93\u052b\f^+J\r\xf0\x92\xb4$\x8a\x06ZM\xa2]0\x16\xc0\x00\x00\u07d4\x0f\x12{\xbf\x8e1\x1c\xae\xa2\xbaP*3\xfe\xce\xd3\xf70\xbaB\x89\n1\x06+\xee\xedp\x00\x00\u07d4\x0f\x1c$\x9c\xd9b\xb0\x0f\xd1\x14\xa94\x9fjl\xc7x\xd7lM\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\x0f n\x1a\x1d\xa7 ~\xa5\x18\xb1\x12A\x8b\xaa\x8b\x06&\x03(\x89 \x86\xac5\x10R`\x00\x00\u07d4\x0f$\x10Z\xbb\u06a0?\xa60\x9e\xf6\xc1\x88\xe5\x1fqJnY\x89\n\u05ce\xbcZ\xc6 \x00\x00\u07d4\x0f&H\n\x15\ta\xb8\xe3\aPq:\x94\xeeo.G\xfc\x00\x8965\u026d\xc5\u07a0\x00\x00\xe0\x94\x0f-\x8d\xaf\x04\xb5AJ\x02a\xf5I\xffdw\xb8\x0f/\x1d\a\x8a*Z\x05\x8f\u0095\xed\x00\x00\x00\u07d4\x0f/\xb8\x84\u022a\xffoT:\xc6\"\x8b\u040eO`\xb0\xa5\xfd\x89\xaa}\xa4\x85\x13k\x84\x00\x00\u07d4\x0f2\xd9\xcbM\x0f\u06a0\x15\x06V\xbb`\x8d\xccC\xed}\x93\x01\x89(\u07cb\xf4@\xdby\x00\x00\u07d4\x0f6e\u050e\x9f\x14\x19\u0358O\xc7\xfa\x92x\x87\x10\xc8\xf2\xe4\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\x0f:\x10#\xca\xc0M\xbfD\xf5\xa5\xfaj\x9c\xf8P\x8c\xd4\xfd\u07c9b\xa9\x92\xe5:\n\xf0\x00\x00\xe0\x94\x0f@s\xc1\xb9\x9d\xf6\n\x15I\u0597\x89\xc71\x8d\x94\x03\xa8\x14\x8a\x04<3\xc1\x93ud\x80\x00\x00\xe0\x94\x0fF\xc8\x1d\xb7\x80\xc1gJ\xc7=1O\x06S\x9e\xe5n\xbc\x83\x8a\x02\x15\xf85\xbcv\x9d\xa8\x00\x00\u07d4\x0fO\x94\xb9\x19\x1b\xb7\xbbUj\xaa\xd7\xc7M\xdb(\x84\x17\xa5\v\x89K\xe4\xe7&{j\xe0\x00\x00\u07d4\x0f`\x00\xde\x15xa\x93 \xab\xa5\xe3\x92pk\x13\x1f\xb1\xdeo\x89\x1b\x1a\xb3\x19\xf5\xecu\x00\x00\u07d4\x0fn\x84\n?*$d}\x8eC\xe0\x9dE\xc7\xc35\xdfBH\x89\x87\x86x2n\xac\x90\x00\x00\u07d4\x0fu\x15\xff\x0e\x80\x8fi^\f H_\xf9n\xd2\xf7\xb7\x93\x10\x8968\"\x16`\xa5\xaa\x80\x00\u07d4\x0fx\x9e09|S\xbf%o\xc3d\xe6\xef9\xf8SPA\x14\x89\xc5S%\xcat\x15\xe0\x00\x00\u07d4\x0f{a\u015b\x01c\"\xe8\"l\xaf\xae\xe9\xd9\xe7mP\xa1\xb3\x89\xd8\xd7&\xb7\x17z\x80\x00\x00\u07d4\x0f{\xeaN\xf3\xf7:\xe0#=\xf1\xe1\x00q\x8c\xbe)1\v\xb0\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\x0f{\xf67?w\x1aF\x01v,M\xae_\xbb\xf4\xfe\u075c\u0249lk\x93[\x8b\xbd@\x00\x00\u07d4\x0f\x83*\x93\u07dd\u007ft\xcd\x0f\xb8Tkq\x98\xbfSw\xd9%\x89\a\xc0\x86\x0eZ\x80\xdc\x00\x00\u07d4\x0f\x83F\x1b\xa2$\xbb\x1e\x8f\u075d\xaeSQr\xb75\xac\xb4\xe0\x89\n\u05ce\xbcZ\xc6 \x00\x00\u07d4\x0f\x85\xe4+\x1d\xf3!\xa4\xb3\xe85\xb5\f\x00\xb0as\x96\x846\x895e\x9e\xf9?\x0f\xc4\x00\x00\xe0\x94\x0f\x88\xaa\xc94l\xb0\xe74\u007f\xbap\x90Tu\xba\x8b>^\u038a\x02\x1e\x19\xe0\u027a\xb2@\x00\x00\u07d4\x0f\x92\x9c\xf8\x95\xdb\x01z\xf7\x9f>\xad\"\x16\xb1\xbdi\xc3}\u01c9lk\x93[\x8b\xbd@\x00\x00\u07d4\x0f\xa0\x10\xce\fs\x1d;b\x8e6\xb9\x1fW\x13\x00\u477e\xab\x8963\x03\"\xd5#\x8c\x00\x00\u07d4\x0f\xa5\xd8\u0173\xf2\x94\xef\u0515\xabi\xd7h\xf8\x18rP\x85H\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\x0f\xa6\u01f0\x97=\v\xae)@T\x0e$}6'\xe3|\xa3G\x8965\u026d\xc5\u07a0\x00\x00\u07d4\x0f\xad\x05P|\u070f$\xb2\xbeL\xb7\xfa]\x92}\u06d1\x1b\x88\x89\xa2\xdf\x13\xf4A\xf0\t\x80\x00\u07d4\x0f\xb5\xd2\xc6s\xbf\xb1\xdd\xca\x14\x1b\x98\x94\xfdm?\x05\xdag \x89\x05k\xc7^-c\x10\x00\x00\u07d4\x0f\u0260\xe3AE\xfb\xfd\xd2\xc9\u04a4\x99\xb6\x17\u05e0)i\xb9\x89\t\xc2\x00vQ\xb2P\x00\x00\xe0\x94\x0f\xcf\xc4\x06P\b\xcf\xd3#0_b\x86\xb5zM\xd7\xee\xe2;\x8a\x04<3\xc1\x93ud\x80\x00\x00\xe0\x94\x0f\xdde@#\x95\u07db\u045f\xeeE\a\xefSE\xf7E\x10L\x8a\x01\x0f\f\xf0d\xddY \x00\x00\u07d4\x0f\xecN\xe0\xd7\xca\x18\x02\x90\xb6\xbd \xf9\x99#B\xf6\x0f\xf6\x8d\x89\x12 \u007f\x0e\xdc\xe9q\x80\x00\u07d4\x0f\ue06c3\x1e\xfd\x8f\x81\x16\x1cW8+\xb4P{\xb9\xeb\xec\x89\x15\xaf\x88\r\x8c\u06c3\x00\x00\u07d4\x0f\xfe\xa0mq\x13\xfbj\xec(i\xf4\xa9\u07f0\x90\a\xfa\xce\xf4\x89\f8F\x81\xb1\xe1t\x00\x00\u07d4\x10\tq\x98\xb4\xe7\xee\x91\xff\x82\xcc/;\xd9_\xeds\xc5@\xc0\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\x10\vM\tw\xfc\xba\xd4\u07bd^d\xa0Iz\xea\xe5\x16\x8f\xab\x89\x11\f\x90s\xb5$Z\x00\x00\xe0\x94\x10\x1a\nd\xf9\xaf\xccD\x8a\x8a\x13\rM\xfc\xbe\xe8\x957\xd8T\x8a\x037\xfe_\xea\xf2\u0440\x00\x00\u07d4\x10,G}i\xaa\u06e9\xa0\xb0\xf6+tY\xe1\u007f\xbb\x1c\x15a\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\x101\xe0\xec\xb5I\x85\xae!\xaf\x17\x93\x95\r\xc8\x11\x88\x8f\xde|\x89\x01\x15\x8eF\t\x13\xd0\x00\x00\u07d4\x104d\x14\xbe\xc6\xd3\xdc\xc4NP\xe5MT\u00b8\xc3sN>\x89\xd8\xd7&\xb7\x17z\x80\x00\x00\u07d4\x108\x98X\xb8\x00\xe8\xc0\xec2\xf5\x1e\xd6\x1a5YF\xcc@\x9b\x89\n\u05ce\xbcZ\xc6 \x00\x00\xe0\x94\x10Y\xcb\xc6>6\xc4>\x88\xf3\x00\b\xac\xa7\xce\x05\x8e\ua816\x8a\x15-\x02\xc7\xe1J\xf6\x80\x00\x00\xe0\x94\x10n\xd5\xc7\x19\xb5&\x14w\x89\x04%\xaeuQ\xdcY\xbd%\\\x8a\x02\x89jX\xc9[\xe5\x88\x00\x00\u07d4\x10q\x1c=\xda21x\x85\xf0\xa2\xfd\x8a\xe9.\x82\x06\x9b\r\v\x89\xd8\xd7&\xb7\x17z\x80\x00\x00\u07d4\x10sy\xd4\xc4gFO#[\xc1\x8eU\x93\x8a\xad>h\x8a\u05c9\x02\xb5\xe3\xaf\x16\xb1\x88\x00\x00\xe0\x94\x10v!-Ou\x8c\x8e\xc7\x12\x1c\x1c}t%I&E\x92\x84\x8a\ai[Y\xb5\xc1{L\x00\x00\u07d4\x10x\xd7\xf6\x1b\x0eV\xc7N\xe6c[.\x18\x19\xef\x1e=\x87\x85\x8965\u026d\xc5\u07a0\x00\x00\u07d4\x10z\x03\xcf\bB\xdb\u07b0a\x8f\xb5\x87\xcai\x18\x9e\xc9/\xf5\x89j\xcb=\xf2~\x1f\x88\x00\x00\u07d4\x10\x80\xc1\xd85\x8a\x15\xbc\x84\xda\xc8%<h\x831\x90 \xdf,\x89\x90\xf54`\x8ar\x88\x00\x00\xe0\x94\x10\x8a+|3oxGy\u0635M\x02\xa8\xd3\x1d\x9a\x13\x9c\n\x8a\x02\x1e\x19\xe0\u027a\xb2@\x00\x00\u07d4\x10\x8b\xa7\u0089\\P\xe0r\xdco\x96I2\xd5\f(-04\x89\x1b\x1a\xe4\xd6\xe2\xefP\x00\x00\u07d4\x10\x8f\xe8\xee*\x13\xdaH{\"\u01abmX.\xa7\x10d\u064c\x89\x15\xacV\xed\xc4\xd1,\x00\x00\xe0\x94\x10\x91\x17k\u16d9d\xa8\xf7.\x0e\xcek\xf8\xe3\u03edn\x9c\x8a\x02\x1f/o\x0f\xc3\xc6\x10\x00\x00\u07d4\x10\x98\xc7t\xc2\f\xa1\u06ac]\xdbb\x03e1m5?\x10\x9c\x89\x05k\xc7^-c\x10\x00\x00\u0794\x10\x98\xcc \uf13a\xd5\x14f9\xc4\xcd\x1c\xa6\u00d9l\xb9\x9b\x88\xfc\x93c\x92\x80\x1c\x00\x00\u07d4\x10\xa1\xc4-\xc1\xbati\x86\xb9\x85\xa5\"\xa7<\x93\xea\xe6Lc\x8965\u026d\xc5\u07a0\x00\x00\u07d4\x10\xa94WIo\x11\b\u0358\xe1@\xa1\xec\u06ee^m\xe1q\x89\x15\xa9\x90b\xd4\x16\x18\x00\x00\u07d4\x10\xb5\xb3M\x12H\xfc\xf0\x17\xf8\xc8\xff\xc4\b\u0389\x9c\xee\xf9/\x89\x0e~\xeb\xa3A\vt\x00\x00\xe0\x94\x10\xcfV\td\xff\x83\xc1\xc9gLx<\x0fs\xfc\u0619C\xfc\x8a\bxg\x83&\xea\xc9\x00\x00\x00\u07d4\x10\xd3$\x16r,\xa4\xe6Hc\x05H\xea\xd9\x1e\xddy\xc0j\xff\x89\x05k\xc7^-c\x10\x00\x00\u07d4\x10\xd9E3N\xcd\xe4{\ub723\x81l\x17=\xfb\xbd\vS3\x89K\xe4\xe7&{j\xe0\x00\x00\u07d4\x10\xdfh\x15\x06\xe3I0\xacz\\g\xa5L>\x89\u0392\xb9\x81\x89t\xc1\xfa\xb8\xad\xb4T\x00\x00\u07d4\x10\xe1\xe37x\x85\xc4-}\xf2\x18R.\xe7vh\x87\xc0^j\x89\x10C\xc4<\xde\x1d9\x80\x00\u07d4\x10\u342d+\xa3=\x82\xb3s\x88\u041cED\u01b0\"]\xe5\x89\n\u05ce\xbcZ\xc6 \x00\x00\u07d4\x10\xf4\xbf\xf0\u02a5\x02|\nj-\xcf\xc9R\x82M\xe2\x94\t\t\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\x11\x00\x1b\x89\xed\x87>:\xae\xc1\x15V4\xb4h\x16C\x98c#\x8965\u026d\xc5\u07a0\x00\x00\u07d4\x11\x027\u03d1\x17\xe7g\x92/\u0121\xb7\x8dyd\u0682\xdf \x89\u0556{\xe4\xfc?\x10\x00\x00\u07d4\x11\x11\xe5\xdb\xf4^o\x90mb\x86o\x17\b\x10\x17\x88\xdd\xd5q\x89F{\xe6S>\xc2\xe4\x00\x00\xe0\x94\x11\x17+'\x8d\xddD\xee\xa2\xfd\xf4\xcb\x1d\x16\x96#\x91\xc4S\u064a\xc6/=\x9b\xfdH\x95\xf0\x00\x00\u07d4\x11&4\xb4\xec0\xffxn\x02AY\xf7\x96\xa5y9\xea\x14N\x89lj\xccg\u05f1\xd4\x00\x00\u07d4\x110l}WX\x867x\x0f\xc9\xfd\xe8\xe9\x8e\xcb\x00\x8f\x01d\x89lj\xccg\u05f1\xd4\x00\x00\xe0\x94\x116\x12\xbc;\xa0\xeeH\x98\xb4\x9d\xd2\x023\x90_/E\x8fb\x8a\x02\xf6\xf1\a\x80\xd2,\xc0\x00\x00\u07d4\x11A_\xaba\xe0\xdf\u0539\x06v\x14\x1aUz\x86\x9b\xa0\xbd\xe9\x89o\x05\xb5\x9d; \x00\x00\x00\u07d4\x11L\xbb\xbfo\xb5*\xc4\x14\xbe~\xc6\x1f{\xb7\x14\x95\xce\x1d\xfa\x89\xa2\xa1]\tQ\x9b\xe0\x00\x00\u07d4\x11L\xfe\xfeP\x17\r\xd9z\xe0\x8f\nDTIx\u0159T\x8d\x89.\u0207\xe7\xa1J\x1c\x00\x00\u07d4\x11a\b\xc1 \x84a.\xed\xa7\xa9=\xdc\xf8\xd2`.'\x9e\\\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\x11d\u02aa\x8c\u0157z\xfe\x1f\xad\x8a}`(\xce-W)\x9b\x89\x15\xaf\x1dx\xb5\x8c@\x00\x00\u07d4\x11gZ%UF\a\xa3\xb6\xc9*\x9e\xe8\xf3ou\xed\xd3\xe36\x89\b\xa9\xab\xa5W\xe3l\x00\x00\u07d4\x11j\t\xdff\xcb\x15\x0e\x97W\x8e)\u007f\xb0n\x13\x04\f\x89<\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\x11o\xef^`\x16B\xc9\x18\u02c9\x16\x0f\xc2);\xa7\x1d\xa96\x89+|\xc2\xe9\xc3\"\\\x00\x00\u07d4\x11xP\x1f\xf9J\xdd\x1cX\x81\xfe\x88a6\xf6\xdf\xdb\xe6\x1a\x94\x89\b\x90\xb0\xc2\xe1O\xb8\x00\x00\u07d4\x11y\xc6\r\xbd\x06\x8b\x15\v\aM\xa4\xbe#\x03; \u0185X\x89$\xdc\xe5M4\xa1\xa0\x00\x00\u07d4\x11}\x9a\xa3\xc4\xd1;\xee\x12\xc7P\x0f\t\xf5\xdd\x1cf\xc4e\x04\x89\v*\xd3\x04\x90\xb2x\x00\x00\xe0\x94\x11}\xb867\u007f\xe1TU\xe0,.\xbd\xa4\v\x1c\xebU\x1b\x19\x8a\x01EB\xba\x12\xa37\xc0\x00\x00\xe0\x94\x11\x8c\x18\xb2\xdc\xe1p\xe8\xf4Eu;\xa5\xd7Q<\xb7cm-\x8a\x01\xdd\f\x88_\x9a\r\x80\x00\x00\u07d4\x11\x8f\xbdu;\x97\x929Z\xefzMx\xd2c\xcd\u02ab\xd4\xf7\x8963\x03\"\xd5#\x8c\x00\x00\xe0\x94\x11\x92\x83x\xd2}U\xc5 \xce\xed\xf2L\xeb\x1e\x82-\x89\r\xf0\x8a\x01\xb1\xaeMn.\xf5\x00\x00\x00\u07d4\x11\x9a\xa6M[}\x18\x1d\xae\x9d<\xb4I\x95\\\x89\xc1\xf9c\xfa\x89%\xf2s\x93=\xb5p\x00\x00\xe0\x94\x11\xc05\x8a\xa6G\x9d\xe2\x18f\xfe!\a\x19$\xb6^p\xf8\xb9\x8a\a\xb5?y\xe8\x88\xda\xc0\x00\x00\xe0\x94\x11\xd2$z\"\x1ep\xc2\xd6m\x17\xee\x13\x8d8\xc5_\xfb\x86@\x8a\x02\x1e\x19\xe0\u027a\xb2@\x00\x00\xe0\x94\x11\u05c4JG\x1e\xf8\x9a\x8d\x87uUX<\xee\xbd\x149\xea&\x8a\x02#i\u6e80\u0188\x00\x00\u07d4\x11\xdda\x85\u0668\xd7=\xdf\u06a7\x1e\x9bwtC\x1cM\xfe\u008965\u026d\xc5\u07a0\x00\x00\u07d4\x11\xe7\x99~\u0750E\x03\xd7}\xa6\x03\x8a\xb0\xa4\xc84\xbb\xd5c\x89\x15\b\x94\xe8I\xb3\x90\x00\x00\u07d4\x11\xec\x00\xf8I\xb61\x9c\xf5\x1a\xa8\u074ff\xb3U)\xc0\xbew\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\x11\ufe22\x04Q\x16\x1bdJ\x8c\u03bb\xc1\xd3C\xa3\xbb\xcbR\x89\xadx\xeb\u016cb\x00\x00\x00\xe0\x94\x11\xfe\xfb]\xc1\xa4Y\x8a\xa7\x12d\fQwu\u07e1\xd9\x1f\x8c\x8a\x02\x1e\x19\xe0\u027a\xb2@\x00\x00\u07d4\x12\x0f\x9d\xe6\xe0\xaf~\xc0*\a\xc6\t\u0284G\xf1W\xe64L\x89\x0e~\xeb\xa3A\vt\x00\x00\u07d4\x12\x10\xf8\v\u06c2l\x17Tb\xab\a\x16\xe6\x9eF\xc2J\xd0v\x89\x05k\xc7^-c\x10\x00\x00\u07d4\x12\x13N\u007fk\x01{\xf4\x8e\x85Z9\x9c\xa5\x8e.\x89/\xa5\u020965\u026d\xc5\u07a0\x00\x00\u07d4\x12\x170t\x98\x01S\xae\xaaK\r\xcb\xc7\x13.\xad\xce\xc2\x1bd\x89\r\x02\xabHl\xed\xc0\x00\x00\u07d4\x12\x1f\x85[p\x14\x9a\xc84s\xb9po\xb4MG\x82\x8b\x98;\x89K\xe4\xe7&{j\xe0\x00\x00\u07d4\x12'\xe1\nM\xbf\x9c\xac\xa3\x1b\x17\x80#\x9fUv\x15\xfc5\xc1\x89\n\u05ce\xbcZ\xc6 \x00\x00\u07d4\x12-\xcf\xd8\x1a\u0779}\x1a\x0eI%\u0135I\x80n\x9f;\xeb\x89R 5\xccn\x01!\x00\x00\u07d4\x12/V\x12%I\xd1h\xa5\xc5\xe2g\xf5&b\xe5\xc5\xcc\xe5\u0209\n\ad\a\xd3\xf7D\x00\x00\xe0\x94\x121o\xc7\xf1x\xea\xc2.\xb2\xb2Z\xed\xea\xdf=u\xd0\x01w\x8a\x04<3\xbe\x05\xf6\xbf\xb9\x80\x00\xe0\x94\x127Y\xf33\xe1>0i\xe2\x03KO\x059\x89\x18\x11\x9d6\x8a\x04<3\xc1\x93ud\x80\x00\x00\u07d4\x12\\\xc5\xe4\xd5k+\xcc.\xe1\xc7\t\xfb\x9eh\xfb\x17t@\xbd\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\x12c#\x88\xb2v^\xe4E+P\x16\x1d\x1f\xff\xd9\x1a\xb8\x1fJ\x89(\x1d\x90\x1fO\xdd\x10\x00\x00\u07d4\x12h\x97\xa3\x11\xa1J\xd4;x\xe0\x92\x01\x00\xc4Bk\xfdk\u07494\xc7&\x89?-\x94\x80\x00\u07d4\x12m\x91\xf7\xad\x86\u07bb\x05W\xc6\x12\xca'n\xb7\xf9m\x00\xa1\x89\x05k\xc7^-c\x10\x00\x00\u07d4\x12}?\xc5\x00;\xf6<\r\x83\xe99W\x83e\x15\xfd'\x90E\x89\x06\x10\xc9\".nu\x00\x00\xe0\x94\x12}\xb1\xca\xdf\x1bw\x1c\xbdtu\xe1\xb2ri\x0fU\x8c\x85e\x8a\x02\xf6\xf1\a\x80\xd2,\xc0\x00\x00\u07d4\x12\x84\xf0\xce\xe9\xd2\xff)\x89\xb6Ut\xd0o\xfd\x9a\xb0\xf7\xb8\x05\x89\x15\xaf\x1dx\xb5\x8c@\x00\x00\u07d4\x12\x8b\x90\x8f\xe7C\xa44 =\xe2\x94\xc4A\xc7\xe2\n\x86\xeag\x89&\xab\x14\xe0\xc0\xe1<\x00\x00\xe0\x94\x12\x93\u01cc}jD;\x9dt\xb0\xba^\xe7\xbbG\xfdA\x85\x88\x8a\x01je\x02\xf1Z\x1eT\x00\x00\u07d4\x12\x96\xac\xde\xd1\xe0c\xaf9\xfe\x8b\xa0\xb4\xb6=\xf7\x89\xf7\x05\x17\x89\x05k\xf9\x1b\x1ae\xeb\x00\x00\u07d4\x12\xaa}\x86\xdd\xfb\xad0\x16\x92\xfe\xac\x8a\b\xf8A\xcb!\\7\x89\amA\xc6$\x94\x84\x00\x00\xe0\x94\x12\xaf\xbc\xba\x14'\xa6\xa3\x9e{\xa4\x84\x9fz\xb1\xc45\x8a\xc3\x1b\x8a\x04<3\xc1\x93ud\x80\x00\x00\xe0\x94\x12\xb5\xe2\x89E\xbb)i\xf9\xc6Lc\xcc\x05\xb6\xf1\xf8\xd6\xf4\u054a\x01\xa2\x9e\x86\x91;t\x05\x00\x00\u0794\x12\u03cb\x0eFR\x13!\x1a[S\u07f0\xdd'\x1a(,\x12\u0248\xd2\xf1?w\x89\xf0\x00\x00\u07d4\x12\xd2\a\x90\xb7\xd3\xdb\u060c\x81\xa2y\xb8\x12\x03\x9e\x8a`;\u0409V\xf9\x85\u04c6D\xb8\x00\x00\xe0\x94\x12\xd6\re\xb7\xd9\xfcH\x84\v\xe5\xf8\x91\xc7E\xcev\xeeP\x1e\x8a\x04\x85\xe58\x8d\fv\x84\x00\x00\u0794\x12\xd9\x1a\x92\xd7O\xc8a\xa7)dm\xb1\x92\xa1%\xb7\x9fSt\x88\xfc\x93c\x92\x80\x1c\x00\x00\xe0\x94\x12\u992d*\xd5t\x84\xddp\x05e\xbd\xdbFB;\u067d1\x8a\x04<0\xfb\b\x84\xa9l\x00\x00\u07d4\x12\xf3,\n\x1f-\xaa\xb6v\xfei\xab\xd9\xe0\x185-L\xcdE\x89\x02\xb5\xe3\xaf\x16\xb1\x88\x00\x00\u07d4\x12\xf4`\xaedl\xd2x\x0f\xd3\\P\xa6\xafK\x9a\xcc\xfa\x85\u018965\u026d\xc5\u07a0\x00\x00\u07d4\x12\xff\xc1\x12\x86\x05\xcb\f\x13p\x9ar\x90Po&\x90\x97q\x93\x89\xb5\x0f\u03ef\xeb\xec\xb0\x00\x00\u07d4\x13\x03$F\xe7\xd6\x10\xaa\x00\xec\x8cV\u0275t\xd3l\xa1\xc0\x16\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\x13\x1cy,\x19}\x18\xbd\x04]p$\x93|\x1f\x84\xb6\x0fD8\x89\xd8\xd7&\xb7\x17z\x80\x00\x00\u07d4\x13\x1d\xf8\xd30\xeb|\xc7\x14}\nUWo\x05\u078d&\xa8\xb7\x89\n1\x06+\xee\xedp\x00\x00\u07d4\x13\x1f\xae\xd1%a\xbbz\xee\x04\xe5\x18Z\xf8\x02\xb1\xc3C\x8d\x9b\x89\v\xdf<K\xb02\x8c\x00\x00\u07d4\x13!\xb6\x05\x02oO\xfb)j>\x0e\u0733\x90\xc9\xc8V\b\xb7\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\x13!\xcc\xf2\x979\xb9t\xe5\xa5\x16\xf1\x8f:\x846q\xe3\x96B\x89\xd8\xd7&\xb7\x17z\x80\x00\x00\u07d4\x13'\xd7Y\xd5n\n\xb8z\xf3~\xcfc\xfe\x01\xf3\x10\xbe\x10\n\x89#\xbc<\xdbh\xa1\x80\x00\x00\u07d4\x13)\xdd\x19\xcdK\xaa\x9f\xc6C\x10\xef\xec\xea\xb2!\x17%\x1f\x12\x89\n\u05ce\xbcZ\xc6 \x00\x00\u07d4\x137\x1f\x92\xa5n\xa88\x1eC\x05\x9a\x95\x12\x8b\xdcMC\u0166\x8965\u026d\xc5\u07a0\x00\x00\u07d4\x13<I\x0f\xa5\xbf\u007f7(\x88\xe6\a\xd9X\xfa\xb7\xf9U\xba\xe1\x89U\xa6\xe7\x9c\xcd\x1d0\x00\x00\u07d4\x13>O\x15\xe1\xe3\x9cSCY0\xaa\xed\xf3\xe0\xfeV\xfd\xe8C\x89\x01\x15\x8eF\t\x13\xd0\x00\x00\u07d4\x13Ac\xbe\x9f\xbb\xe1\xc5in\xe2U\xe9\v\x13%C\x95\xc3\x18\x89\n\u05ce\xbcZ\xc6 \x00\x00\xe0\x94\x13\\\xec\xd9U\xe5y\x83pv\x920\x15\x93\x03\u0671\x83\x9ff\x8a\x01\x0f\f\xf0d\xddY \x00\x00\u07d4\x13]\x17\x19\xbf\x03\xe3\xf8f1$y\xfe3\x81\x18\xcd8~p\x89lk\x93[\x8b\xbd@\x00\x00\xe0\x94\x13^\xb8\xc0\xe9\xe1\x01\xde\xed\xec\x11\xf2\xec\xdbf\xae\x1a\xae\x88g\x8a\x04<3\xc1\x93ud\x80\x00\x00\u07d4\x13`\xe8}\xf2Li\xeemQ\xc7nsv\u007f\xfe\x19\xa2\x13\x1c\x89\x04\xfc\xc1\xa8\x90'\xf0\x00\x00\u07d4\x13l\x83K\xf1\x112m s\x95)[.X>\xa7\xf35r\x89\x05k\xc7^-c\x10\x00\x00\u07d4\x13mKf+\xbd\x10\x80\xcf\xe4D[\x0f\xa2\x13\x86D5\xb7\xf1\x89\xd8\xd7&\xb7\x17z\x80\x00\x00\u07d4\x13oI\a\u02b4\x1e'\bK\x98E\x06\x9f\xf2\xfd\f\x9a\xdey\x89\xd8\xd7&\xb7\x17z\x80\x00\x00\u07d4\x13t\xfa\xcd{?\x8dhd\x9d`\xd4U\x0e\xe6\x9f\xf0HA3\x89\x0e\x9e\xd6\xe1\x11r\xda\x00\x00\u07d4\x13|\xf3A\xe8Ql\x81X\x14\xeb\xcds\xe6V\x9a\xf1L\xf7\xbc\x8965\u026d\xc5\u07a0\x00\x00\xe0\x94\x13\x84\x8bF\xeau\xbe\xb7\xea\xa8_Y\xd8f\xd7\u007f\xd2L\xf2\x1a\x8a\n\x96\x81c\xf0\xa5{@\x00\x00\u07d4\x13\x9d51\u0252*\xd5bi\xf60\x9a\xa7\x89\xfb$\x85\xf9\x8c\x89\xd8\xd7&\xb7\x17z\x80\x00\x00\u07d4\x13\x9eG\x97d\xb4\x99\xd6f \x8cJ\x8a\x04z\x97\x041c\u0749 w!*\xffm\xf0\x00\x00\u07d4\x13\xa5\xee\xcb80]\xf9Iq\xef-\x9e\x17\x9a\xe6\u03ba\xb37\x89\x11\u3ac3\x95\xc6\xe8\x00\x00\u07d4\x13\xac\xad\xa8\x98\n\xff\xc7PI!\xbe\x84\xebID\xc8\xfb\xb2\xbd\x89V\u04aa:\\\t\xa0\x00\x00\u07d4\x13\xb9\xb1\a\x15qL\t\xcf\xd6\x10\u03dc\x98F\x05\x1c\xb1\xd5\x13\x89j\xcb=\xf2~\x1f\x88\x00\x00\u07d4\x13\xce3-\xffe\xa6\xab\x938\x97X\x8a\xa2>\x00\t\x80\xfa\x82\x89\x0e\x02\x056\xf0(\xf0\x00\x00\u07d4\x13\xd6z~%\xf2\xb1,\u06c5XP\t\xf8\xac\u011b\x96s\x01\x89lj\xccg\u05f1\xd4\x00\x00\u07d4\x13\xde\xe0>7\x99\x95-\a8\x84=K\xe8\xfc\n\x80?\xb2\x0e\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\x13\xe0/\xb4H\xd6\xc8J\xe1}\xb3\x10\xad(m\x05a`\u0695\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\x13\xe3!r\x8c\x9cWb\x80X\xe9?\xc8f\xa02\xdd\v\u0690\x89&\xbc\xca#\xfe.\xa2\x00\x00\u07d4\x13\xec\x81\"\x84\x02n@\x9b\xc0f\xdf\xeb\xf9\u0564\xa2\xbf\x80\x1e\x89WG=\x05\u06ba\xe8\x00\x00\xe0\x94\x14\x01)\xea\xa7f\xb5\xa2\x9f[:\xf2WND\t\xf8\xf6\xd3\xf1\x8a\x01Z\xf1\u05cbX\xc4\x00\x00\x00\u07d4\x14\x05\x18\xa3\x19K\xad\x13P\xb8\x94\x9ee\x05e\u07bem\xb3\x15\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\x14\x06\x85M\x14\x9e\b\x1a\xc0\x9c\xb4\xcaV\r\xa4c\xf3\x120Y\x89Hz\x9a0E9D\x00\x00\u07d4\x14\f\xa2\x8f\xf3;\x9ff\xd7\xf1\xfc\x00x\xf8\xc1\xee\xf6\x9a\x1b\xc0\x89V\xbcu\xe2\xd61\x00\x00\x00\u07d4\x14\x0f\xbaX\xdb\xc0H\x03\xd8L!0\xf0\x19x\xf9\xe0\xc71)\x89\x15\xaf\x1dx\xb5\x8c@\x00\x00\xe0\x94\x14\x1a^9\xee/h\n`\x0f\xbfo\xa2\x97\u0790\xf3\"\\\u074a\x02\x1e\x19\xe0\u027a\xb2@\x00\x00\u07d4\x14%N\xa1&\xb5-\x01B\xda\n~\x18\x8c\xe2U\xd8\xc4qx\x89*\x03I\x19\u07ff\xbc\x00\x00\u07d4\x14+\x87\xc5\x04?\xfbZ\x91\xdf\x18\xc2\xe1\t\xce\xd6\xfeJq\u06c9\n\u05ce\xbcZ\xc6 \x00\x00\u07d4\x14<c\x97R\xca\xee\xcfj\x99}9p\x9f\xc8\xf1\x98x\xc7\xe8\x89j\xcb=\xf2~\x1f\x88\x00\x00\u07d4\x14=Sk\x8b\x1c\xb8OV\xa3\x9e\v\xc8\x1f\xd5D+\xca\xcc\xe1\x89\x05k\xc7^-c\x10\x00\x00\u07d4\x14?_\x16X\xd9\xe5x\xf4\xf3\xd9_\x80\xc0\xb1\xbd93\xcb\u0689P\xc5\xe7a\xa4D\b\x00\x00\u07d4\x14A\x0f\xb3\x10q\x1b\xe0t\xa8\b\x83\xc65\xd0\xefj\xfb%9\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\x14K\x19\xf1\xf6l\xbe1\x83G\u4344\xb1@9FlY\t\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\x14RP\xb0nO\xa7\xcb'IB.\xb8\x17\xbd\u068bT\xde_\x89\v\xdf<K\xb02\x8c\x00\x00\u07d4\x14^\x06\x00\xe2\xa9'\xb2\u074d7\x93V\xb4Z.}Q\u04ee\x89\x8a\x02\xab@\v\xb2\u02c0\x00\u07d4\x14^\x1d\xe0\x14y\x11\xcc\u0600\x87_\xbb\xeaa\xf6\xa1B\xd1\x1d\x89\xd8\xd7&\xb7\x17z\x80\x00\x00\xe0\x94\x14c\xa8sU[\xc09~W\\$q\xcfw\xfa\x9d\xb1F\xe0\x8a\x02\x1e\x19\xe0\u027a\xb2@\x00\x00\u07d4\x14y\xa9\xect\x80\xb7K]\xb8\xfcI\x9b\xe3R\xda\u007f\x84\ue70965\u026d\xc5\u07a0\x00\x00\u07d4\x14z\xf4j\xe9\xcc\u044b\xb3\\\xa0\x1b5;Q\x99\x0eI\xdc\xe1\x89\xd8\xd7&\xb7\x17z\x80\x00\x00\u07d4\x14\u007fB\x10\xabX\x04\x94\n\v}\xb8\xc1L(9kb\xa6\xbf\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\x14\x83\a\x04\u96aa\xd5\xc5^\x1fP+'\xb2,\x12\xc9\x193\x89!\x9c:{\x19f0\x00\x00\xe0\x94\x14\x9bm\xbd\xe62\xc1\x9fZ\xf4|\xb4\x93\x11K\xeb\u0670<\x1f\x8a\x02\x8a\x85t%Fo\x80\x00\x00\xe0\x94\x14\x9b\xa1\x0f\r\xa2r]\xc7\x04s>\x87\xf5\xa5$\u0288Q^\x8a\x01\xab,\xf7\xc9\xf8~ \x00\x00\u07d4\x14\xa75 f6D\x04\xdbP\xf0\xd0\u05cduJ\"\x19\x8e\xf4\x89e\xea=\xb7UF`\x00\x00\u07d4\x14\xab\x16K;RL\x82\u05ab\xfb\xc0\u0783\x11&\xae\x8d\x13u\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\x14\xb1`>\xc6+ \x02 3\xee\xc4\xd6\xd6eZ\xc2J\x01Z\x89\x02\xb5\xe3\xaf\x16\xb1\x88\x00\x00\xe0\x94\x14\xc6;\xa2\u0731\xddM\xf3=\u06b1\x1cO\x00\a\xfa\x96\xa6-\x8a\x03HA\xb6\x05z\xfa\xb0\x00\x00\xe0\x94\x14\xcd\u077c\x8b\t\xe6gZ\x9e\x9e\x05\t\x1c\xb9\"8\u00de\x1e\x8a\x01\x14x\xb7\xc3\n\xbc0\x00\x00\u07d4\x14\xd0\n\xad9\xa0\xa7\u045c\xa0SP\xf7\xb07'\xf0\x8d\xd8.\x89\x1b\x1a\xe4\xd6\xe2\xefP\x00\x00\u07d4\x14\xee\xc0\x9b\xf0>5+\xd6\xff\x1b\x1e\x87k\xe6d\xce\xff\xd0\u03c9\x01\x16\xdc:\x89\x94\xb3\x00\x00\u07d4\x14\xf2!\x15\x95\x18x;\u0127\x06go\xc4\xf3\xc5\xee@X)\x89\n\u05ce\xbcZ\xc6 \x00\x00\u07d4\x14\xfc\xd19\x1e}s/Avl\xda\u0344\xfa\x1d\xeb\x9f\xfd\u0489lk\x93[\x8b\xbd@\x00\x00\u07d4\x15\x0e=\xbc\xbc\xfc\x84\xcc\xf8\x9bsBwc\xa5e\xc2>`\u0409\x02+\x1c\x8c\x12'\xa0\x00\x00\xe0\x94\x15\x18b{\x885\x1f\xed\xe7\x96\xd3\xf3\b3d\xfb\u0508{\f\x8a\x03c\\\x9a\xdc]\xea\x00\x00\x00\u0794\x15\"J\xd1\xc0\xfa\xceF\xf9\xf5V\xe4wJ0%\xad\x06\xbdR\x88\xb9\x8b\xc8)\xa6\xf9\x00\x00\u07d4\x15/+\xd2)\xdd\xf3\xcb\x0f\xda\xf4U\xc1\x83 \x9c\x0e\x1e9\xa2\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\x15/N\x86\x0e\xf3\xee\x80jP'w\xa1\xb8\xdb\xc9\x1a\x90vh\x89 \x86\xac5\x10R`\x00\x00\u07d4\x15<\b\xaa\x8b\x96\xa6\x11\xefc\xc0%>*C4\x82\x9eW\x9d\x89\x15[\xd90\u007f\x9f\xe8\x00\x00\u07d4\x15<\xf2\x84,\xb9\u0787l'o\xa6Gg\u0468\xec\xf5s\xbb\x89lk\x93[\x8b\xbd@\x00\x00\xe0\x94\x15>\xf5\x8a\x1e.z>\xb6\xb4Y\xa8\n\xb2\xa5G\xc9A\x82\xa2\x8a\x14T+\xa1*3|\x00\x00\x00\u07d4\x15DY\xfa/!1\x8e44D\x97\x89\xd8&\xcd\xc1W\f\xe5\x89lk\x93[\x8b\xbd@\x00\x00\xe0\x94\x15G\xb9\xbfz\xd6bt\xf3A8'#\x1b\xa4\x05\ue308\xc1\x8a\x03\xa9\u057a\xa4\xab\xf1\xd0\x00\x00\u07d4\x15H\xb7p\xa5\x11\x8e\u0787\u06e2\xf6\x903\u007fam\u60eb\x89\x1c\x99V\x85\u0fc7\x00\x00\u07d4\x15R\x83P\xe0\xd9g\n.\xa2\u007f{J3\xb9\xc0\xf9b\x1d!\x89\xd8\xd8X?\xa2\xd5/\x00\x00\u07d4\x15[7y\xbbmV4./\u0681{[-\x81\xc7\xf4\x13'\x89\x02\xb8\xaa:\al\x9c\x00\x00\u07d4\x15e\xaf\x83~\xf3\xb0\xbdN+#V\x8dP#\xcd4\xb1d\x98\x89\x15Q\xe9rJ\u013a\x00\x00\u07d4\x15f\x91\x80\xde\u2558\x86\x9b\b\xa7!\xc7\xd2LL\x0e\xe6?\x8965\u026d\xc5\u07a0\x00\x00\xe0\x94\x15r\xcd\xfa\xb7*\x01\u0396\x8ex\xf5\xb5D\x8d\xa2\x98S\xfb\u074a\x01\x12blI\x06\x0f\xa6\x00\x00\xe0\x94\x15uY\xad\xc5Wd\xccm\xf7\x93#\t%4\xe3\xd6dZf\x8a\x01EB\xba\x12\xa37\xc0\x00\x00\u07d4\x15x\xbd\xbc7\x1bM$8E3\x05V\xff\xf2\xd5\xefM\xffg\x89\x05k\xc7^-c\x10\x00\x00\u07d4\x15~\xb3\xd3\x11;\u04f5\x97qM:\x95N\xdd\x01\x89\x82\xa5\u02c9lk\x93[\x8b\xbd@\x00\x00\u07d4\x15\x84\xa2\xc0f\xb7\xa4U\xdb\u05ae(\a\xa73N\x83\xc3_\xa5\x89\a\f\x1c\xc7;\x00\xc8\x00\x00\u07d4\x15\x87F\x86\xb6s=\x10\xd7\x03\xc9\xf9\xbe\xc6\xc5.\xb8b\x8dg\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\x15\x8a\ra\x92S\xbfD2\xb5\xcd\x02\u01f8b\xf7\u00b7V6\x89\a[\xac|[\x12\x18\x80\x00\u07d4\x15\x98\x12y\x82\xf2\xf8\xad;k\x8f\xc3\xcf'\xbfax\x01\xba+\x89\t`\xdbwh\x1e\x94\x00\x00\xe0\x94\x15\x9a\xdc\xe2z\xa1\vG#d)\xa3JZ\xc4,\xad[d\x16\x8a\x06\xbf\x90\xa9n\xdb\xfaq\x80\x00\u07d4\x15\xa0\xae\xc3\u007f\xf9\xff=T\t\xf2\xa4\xf0\xc1!*\xac\xcb\x02\x96\x8965\u026d\xc5\u07a0\x00\x00\u07d4\x15\xaaS\r\xc3iX\xb4\xed\xb3\x8e\xeem\xd9\xe3\xc7}L\x91E\x89lk\x93[\x8b\xbd@\x00\x00\xe0\x94\x15\xac\xb6\x15h\xecJ\xf7\xea(\x198a\x81\xb1\x16\xa6\xc5\xeep\x8a\x06\x90\x83l\n\xf5\xf5`\x00\x00\u07d4\x15\xb9o0\xc2;\x86d\xe7I\x06Q\x06k\x00\xc49\x1f\xbf\x84\x89\x16B\xe9\xdfHv)\x00\x00\u07d4\x15\xc7\xed\xb8\x11\x8e\xe2{4\"\x85\xebY&\xb4z\x85[\u01e5\x89\x01\x15\x8eF\t\x13\xd0\x00\x00\u07d4\x15\u0654hPz\xa0A?\xb6\r\xca*\xdc\u007fV\x9c\xb3kT\x89lk\x93[\x8b\xbd@\x00\x00\xe0\x94\x15\u06f4\x8c\x980\x97d\xf9\x9c\xed6\x92\xdc\xca5\xee0k\xac\x8a\x1f\u00c4+\xd1\xf0q\xc0\x00\x00\xe0\x94\x15\u072f\xcc+\xac\xe7\xb5[T\xc0\x1a\x1cQF&\xbfa\xeb\u060a\x01\xfd\x934\x94\xaa_\xe0\x00\x00\u07d4\x15\u3d44\x05kb\xc9s\xcf^\xb0\x96\xf1s>T\xc1\\\x91\x892\xc7Z\x02#\xdd\xf3\x00\x00\u07d4\x15\xeb\xd1\xc7\xca\u04af\xf1\x92u\xc6W\xc4\xd8\b\xd0\x10\xef\xa0\xf5\x89\n\xdf0\xbap\u0217\x00\x00\u07d4\x15\xee\x0f\xc6>\xbf\x1b\x1f\u011d{\xb3\x8f\x88c\x82:.\x17\u0489g\x8a\x93 b\xe4\x18\x00\x00\u07d4\x15\xf1\xb3R\x11\rh\x90\x1d\x8fg\xaa\xc4jl\xfa\xfe\x03\x14w\x89\n\u05ce\xbcZ\xc6 \x00\x00\u07d4\x15\xf2\xb7\xb1d2\xeeP\xa5\xf5[A#/c4\xedX\xbd\xc0\x89\x15\xaf\x1dx\xb5\x8c@\x00\x00\u07d4\x16\x01\x9aM\xaf\xabC\xf4\u067fAc\xfa\xe0\x84}\x84\x8a\xfc\xa2\x89\x01[\xc7\x019\xf7J\x00\x00\u07d4\x16\x02&\xef\xe7\xb5:\x8a\xf4b\xd1\x17\xa0\x10\x80\x89\xbd\xec\xc2\u0449\n\xdf0\xbap\u0217\x00\x00\u07d4\x16\f\xebo\x98\x0e\x041_S\xc4\xfc\x98\x8b+\xf6\x9e(M}\x89\x01\t\x10\xd4\xcd\xc9\xf6\x00\x00\xe0\x94\x16\x1c\xafZ\x97*\u0383y\xa6\u0420J\xe6\xe1c\xfe!\xdf+\x8a\x15-\x02\xc7\xe1J\xf6\x80\x00\x00\u07d4\x16\x1d&\xefgY\xba[\x9f \xfd\xcdf\xf1a2\xc3RA^\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\x16!\x10\xf2\x9e\xac_}\x02\xb5C\xd8\xdc\u057bY\xa5\xe3;s\x89lk\x93[\x8b\xbd@\x00\x00\xe0\x94\x16+\xa5\x03'b\x14\xb5\t\xf9u\x86\xbd\x84!\x10\xd1\x03\xd5\x17\x8a\x01\xe7\xff\u0609\\\"h\x00\x00\u07d4\x16-v\xc2\xe6QJ:\xfbo\xe3\xd3\u02d3\xa3\\Z\xe7\x83\xf1\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\x16;\xadJ\x12+E}d\xe8\x15\nA>\xaeM\a\x02>k\x89\x01\x04\xe7\x04d\xb1X\x00\x00\u07d4\x16<\u023e\"vF\xcb\tq\x91Y\xf2\x8e\u041c]\xc0\xdc\xe0\x89Hz\x9a0E9D\x00\x00\u07d4\x16=\xcas\xd7\xd6\xea?>`b2*\x874\x18\f\vx\uf25ft \x03\xcb}\xfc\x00\x00\u07d4\x16Mz\xac>\xec\xba\uc86dQ\x91\xb7S\xf1s\xfe\x12\xec3\x89(VR\xb8\xa4hi\x00\x00\u07d4\x16Rl\x9e\u07d4>\xfaOm\x0f\v\xae\x81\xe1\x8b1\xc5@y\x895e\x9e\xf9?\x0f\xc4\x00\x00\u07d4\x16S\x05\xb7\x872.%\xdcj\xd0\xce\xfelo3Fx\xd5i\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\x16e\xab\x179\xd7\x11\x19\xeea2\xab\xbd\x92j'\x9f\xe6yH\x89\x05k\xc7^-c\x10\x00\x00\xe0\x94\x16k\xf6\u06b2-\x84\x1bHl8\xe7\xbaj\xb3:\x14\x87\ud30a\x04<3\xc1\x93ud\x80\x00\x00\u07d4\x16v\x99\xf4\x8ax\xc6\x15Q%\x15s\x99X\x993\x12WO\a\x89\x02\x1d;\xd5^\x80<\x00\x00\u07d4\x16x\xc5\xf2\xa5\"92%\x19ca\x89OS\xccu/\xe2\xf3\x89h\xf3e\xae\xa1\xe4@\x00\x00\u07d4\x16|\xe7\xdee\xe8G\bYZRT\x97\xa3\xeb^ZfPs\x89\x1f1Gsfo\xc4\x00\x00\u07d4\x16~>:\xe2\x003HE\x93\x92\xf7\xdf\xceD\xaf|!\xadY\x89\x1b\x1a\xe4\xd6\xe2\xefP\x00\x00\xe0\x94\x16\x80\xce\xc5\x02\x1e\xe90P\xf8\xae\x12rQ\x83\x9et\xc1\xf1\xfd\x8a\x02\xc6\x14a\xe5\xd7C\u0580\x00\u07d4\x16\x81j\xac\x0e\xde\r-<\xd4B\xday\xe0c\x88\x0f\x0f\x1dg\x89lk\x93[\x8b\xbd@\x00\x00\xe0\x94\x16\x8bP\x19\xb8\x18i\x16D\x83_\xe6\x9b\xf2)\xe1q\x12\xd5,\x8a\x05\xed\xe2\x0f\x01\xa4Y\x80\x00\x00\u07d4\x16\x8b\xde\xc8\x18\xea\xfcm)\x92\xe5\xefT\xaa\x0e\x16\x01\xe3\xc5a\x8967Pz0\xab\xeb\x00\x00\u07d4\x16\x8d0\xe5?\xa6\x81\t+R\xe9\xba\xe1Z\r\xcbA\xa8\u027b\x89\x05k\xc7^-c\x10\x00\x00\u07d4\x16\x9b\xbe\xfcA\xcf\xd7\xd7\u02f8\xdf\xc60 \xe9\xfb\x06\u0515F\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\x16\xa5\x8e\x98]\xcc\xd7\a\xa5\x94\u0453\xe7\u0327\x8b]\x02xI\x89I\xb9\u029aiC@\x00\x00\u07d4\x16\xa9\xe9\xb7:\u92c6M\x17(y\x8b\x87f\xdb\xc6\xea\x8d\x12\x893\xe7\xb4K\r\xb5\x04\x00\x00\u07d4\x16\xaaR\xcb\vUG#\xe7\x06\x0f!\xf3'\xb0\xa6\x83\x15\xfe\xa3\x89\r\x8drkqw\xa8\x00\x00\u07d4\x16\xab\xb8\xb0!\xa7\x10\xbd\u01ce\xa54\x94\xb2\x06\x14\xffN\xaf\xe8\x89\b\x90\xb0\xc2\xe1O\xb8\x00\x00\u07d4\x16\xaf\xa7\x87\xfc\x9f\x94\xbd\xffiv\xb1\xa4/C\n\x8b\xf6\xfb\x0f\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\x16\xba\xe5\xd2N\xff\x91w\x8c\u064bM:\x1c\xc3\x16/D\xaaw\x89\x15\xbeat\xe1\x91.\x00\x00\u07d4\x16\xbc@!Z\xbb\u066e](\v\x95\xb8\x01\vE\x14\xff\x12\x92\x89\n\u05ce\xbcZ\xc6 \x00\x00\xe0\x94\x16\xbeu\u9299Z9R\"\xd0\v\u05df\xf4\xb6\xe68\u144a\a\x9f\x90\\o\xd3N\x80\x00\x00\u07d4\x16\xc1\xbf[}\xc9\xc8<\x17\x9e\xfa\xcb\xcf.\xb1t\xe3V\x1c\xb3\x8965\u026d\xc5\u07a0\x00\x00\u07d4\x16\u01f3\x1e\x8c7b\x82\xac\"qr\x8c1\xc9^5\xd9R\u00c9lk\x93[\x8b\xbd@\x00\x00\u07d4\x16\xf3\x13\u03ca\xd0\x00\x91J\n\x17m\u01a44+y\xec%8\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\x16\xff\xac\x84\x03)@\xf0\x12\x1a\tf\x8b\x85\x8a~y\xff\xa3\xbb\x89\xd2J\xdan\x10\x87\x11\x00\x00\xe0\x94\x17\x03\xb4\xb2\x92\xb8\xa9\xde\xdd\xed\xe8\x1b\xb2]\x89\x17\x9fdF\xb6\x8a\x04+e\xa4U\xe8\xb1h\x00\x00\u07d4\x17\x04\x93\x11\x10\x1d\x81~\xfb\x1de\x91\x0ff6b\xa6\x99\u024c\x89lh\xcc\u041b\x02,\x00\x00\u07d4\x17\x04\xce\xfc\xfb\x131\xeczx8\x8b)9>\x85\xc1\xafy\x16\x89\x15\xaf\x1dx\xb5\x8c@\x00\x00\u07d4\x17\n\x88\xa8\x99\u007f\x92\xd287\x0f\x1a\xff\xde\xe64pP\xb0\x13\x89\xa2\xacw5\x14\x880\x00\x00\u07d4\x17\x10\x8d\xab,P\xf9\x9d\xe1\x10\u1cf3\xb4\u0342\xf5\xdf(\xe7\x895 ;g\xbc\xca\xd0\x00\x00\xe0\x94\x17\x12[Y\xacQ\xce\xe0)\xe4\xbdx\xd7\xf5\x94}\x1e\xa4\x9b\xb2\x8a\x04\xa8\x9fT\xef\x01!\xc0\x00\x00\u07d4\x17\x1a\u0660K\xed\u0238a\xe8\xedK\xdd\xf5qx\x13\xb1\xbbH\x89\x15\xaf\x1dx\xb5\x8c@\x00\x00\u07d4\x17\x1c\xa0*\x8bmb\xbfL\xa4~\x90i\x14\a\x98a\x97,\xb2\x89\n\u05ce\xbcZ\xc6 \x00\x00\u07d4\x17\"\xc4\xcb\xe7\n\x94\xb6U\x9dBP\x84\xca\xee\xd4\xd6\xe6n!\x89\xd8\xd7&\xb7\x17z\x80\x00\x00\u07d4\x17X\vvotSR\\\xa4\u01a8\x8b\x01\xb5\x05p\xea\b\x8c\x89\x05k\xc7^-c\x10\x00\x00\u07d4\x17X\x9al\x00jT\xca\xd7\x01\x03\x12:\xae\n\x82\x13_\u07b4\x89\xd8\xd7&\xb7\x17z\x80\x00\x00\xe0\x94\x17Z\x18::#_\xfb\xb0;\xa85gRg\"\x94\x17\xa0\x91\x8a\x03c\\\x9a\xdc]\xea\x00\x00\x00\u07d4\x17_\xee\xea*\xa4\xe0\xef\xda\x12\xe1X\x8d/H2\x90\xed\xe8\x1a\x89\n\u05ce\xbcZ\xc6 \x00\x00\xe0\x94\x17e6\x1c.\xc2\xf86\x16\u0383c\xaa\xe2\x10%\xf2Vo@\x8a\x01\x0f\f\xf0d\xddY \x00\x00\u07d4\x17gR\\_Z\"\xed\x80\xe9\xd4\xd7q\x0f\x03b\u049e\xfa3\x89\x15\xaf\x1dx\xb5\x8c@\x00\x00\u07d4\x17v%`\xe8*\x93\xb3\xf5\"\xe0\xe5$\xad\xb8a,:tp\x8965\u026d\xc5\u07a0\x00\x00\u07d4\x17}\xaex\xbc\x01\x13\xd8\u04dcD\x02\xf2\xa6A\xae*\x10Z\xb8\x89b\x92BV \xb4H\x00\x00\xe0\x94\x17\x84\x94\x8b\xf9\x98H\u021eDV8PM\u0598'\x1bY$\x8a\x01GLA\r\x87\xba\xee\x00\x00\u07d4\x17\x88\u069bW\xfd\x05\xed\xc4\xff\x99\xe7\xfe\xf3\x01Q\x9c\x8a\n\x1e\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\x17\x8e\xafk\x85T\xc4]\xfd\xe1kx\xce\f\x15\u007f.\xe3\x13Q\x89\x11X\xe4`\x91=\x00\x00\x00\u07d4\x17\x96\x1dc;\xcf \xa7\xb0)\xa7\xd9K}\xf4\xda.\xc5B\u007f\x89\fo\xf0p\U000532c0\x00\u07d4\x17\x96\xbc\xc9{\x8a\xbcq\u007fKJ|k\x106\xea!\x82c\x9f\x89\x13A\xf9\x1c\xd8\xe3Q\x00\x00\u07d4\x17\x99=1*\xa1\x10iW\x86\x8fjU\xa5\xe8\xf1/w\xc8C\x89\x18e\xe8\x14\xf4\x14.\x80\x00\u07d4\x17\x9a\x82^\x0f\x1fn\x98S\tf\x84e\xcf\xfe\xd46\xf6\xae\xa9\x89\x01\x15\x8eF\t\x13\xd0\x00\x00\u07d4\x17\xb2\xd6\xcfe\xc6\xf4\xa3G\xdd\xc6W&U5M\x8aA+)\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\x17\xb8\a\xaf\xa3\xdd\xd6G\xe7#T.{R\xfe\xe3\x95'\xf3\x06\x89\x15\xaf@\xff\xa7\xfc\x01\x00\x00\u07d4\x17\xc0G\x86W\xe1\xd3\xd1z\xaa3\x1d\xd4)\xce\u03d1\xf8\xae]\x8964\xfb\x9f\x14\x89\xa7\x00\x00\u07d4\x17\xc0\xfe\xf6\x98l\xfb.@A\xf9\x97\x9d\x99@\xb6\x9d\xff=\xe2\x89\xd8\xd7&\xb7\x17z\x80\x00\x00\u07d4\x17\u0511\x8d\xfa\xc1]w\xc4\u007f\x9e\xd4\x00\xa8P\x19\rd\xf1Q\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\x17\xd5!\xa8\xd9w\x90#\xf7\x16M#<;d \xff\xd2#\xed\x89\x01\x15\x8eF\t\x13\xd0\x00\x00\u07d4\x17\xd91\xd4\xc5b\x94\u073ew\xc8e[\xe4i_\x00mJ<\x89lk\x93[\x8b\xbd@\x00\x00\xe0\x94\x17\xdfIQ\x8ds\xb1)\xf0\xda6\xb1\u0274\f\xb6d \xfd\u01ca\x02\x1e\x19\xe0\u027a\xb2@\x00\x00\u07d4\x17\xe4\xa0\xe5+\xac>\xe4N\xfe\tT\xe7S\u0538]dN\x05\x89lk\x93[\x8b\xbd@\x00\x00\xe0\x94\x17\xe5\x84\xe8\x10\xe5gp,a\xd5]CK4\u0375\xee0\xf6\x8a\x01\x0f\f\xf0d\xddY \x00\x00\u07d4\x17\xe8.px\xdcO\xd9\xe8y\xfb\x8aPf\u007fS\xa5\xc5E\x91\x89\n\u05ce\xbcZ\xc6 \x00\x00\u07d4\x17\xe8o;[0\xc0\xbaY\xf2\xb2\xe8XB[\xa8\x9f\n\x10\xb0\x89lk\x93[\x8b\xbd@\x00\x00\xe0\x94\x17\xee\x9fT\xd4\xdd\xc8Mg\x0e\xff\x11\xe5Je\x9f\xd7/DU\x8a\x03c\\\x9a\xdc]\xea\x00\x00\x00\xe0\x94\x17\xefJ\xcc\x1b\xf1G\xe3&t\x9d\x10\xe6w\xdc\xff\xd7o\x9e\x06\x8a\bwQ\xf4\xe0\xe1\xb50\x00\x00\u07d4\x17\xf1F2\xa7\xe2\x82\v\xe6\xe8\xf6\u07c25X(=\xad\xab-\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\x17\xf5#\xf1\x17\xbc\x9f\xe9x\xaaH\x1e\xb4\xf5V\x17\x117\x1b\u0209li\xf7>)\x13N\x00\x00\u07d4\x17\xfd\x9bU\x1a\x98\xcba\xc2\xe0\u007f\xbfA\xd3\xe8\u02650\u02e5\x89\x01v\x8c0\x81\x93\x04\x80\x00\u07d4\x18\x04x\xa6U\u05cd\x0f;\fO +aH[\xc4\x00/\u0549lk\x93[\x8b\xbd@\x00\x00\u07d4\x18\x13l\x9d\xf1g\xaa\x17\xb6\xf1\x8e\"\xa7\x02\u020fK\u0082E\x89\xd8\xd7&\xb7\x17z\x80\x00\x00\xe0\x94\x18\x15'\x9d\xff\x99R\xda;\xe8\xf7rI\xdb\xe2\"C7{\xe7\x8a\x01\x01|\xb7n{&d\x00\x00\u07d4\x18\x1f\xbb\xa8R\xa7\xf5\x01x\xb1\xc7\xf0>\xd9\xe5\x8dT\x16))\x89$\x1a\x9bOaz(\x00\x00\xe0\x94\x18'\x03\x9f\tW\x02\x94\b\x8f\xdd\xf0G\x16\\3\u65a4\x92\x8a\x02\x05\xb4\u07e1\xeetx\x00\x00\u07d4\x18-\xb8R\x93\xf6\x06\u8248\xc3pL\xb3\xf0\xc0\xbb\xbf\xcaZ\x89\a?u\u0460\x85\xba\x00\x00\u07d4\x18H\x00<%\xbf\u052a\x90\xe7\xfc\xb5\u05f1k\xcd\f\xff\xc0\u060965\u026d\xc5\u07a0\x00\x00\xe0\x94\x18JO\v\xebq\xff\xd5X\xa6\xb6\xe8\xf2(\xb7\x87\x96\xc4\xcf>\x8a\x02\x8a\x85t%Fo\x80\x00\x00\xe0\x94\x18M\x86\xf3Fj\xe6h;\x19r\x99\x82\xe7\xa7\u1903G\xb2\x8a\x02\x1e\x19\xe0\u027a\xb2@\x00\x00\u07d4\x18Q\xa0c\xcc\xdb0T\x90w\xf1\xd19\xe7-\xe7\x97\x11\x97\u0549lk\x93[\x8b\xbd@\x00\x00\u07d4\x18UF\xe8v\x8dPhs\x81\x8a\xc9u\x1c\x1f\x12\x11j;\xef\x89\n\u05ce\xbcZ\xc6 \x00\x00\xe0\x94\x18X\xcf\x11\xae\xa7\x9fS\x98\xad+\xb2\"g\xb5\xa3\xc9R\xeat\x8a\x02\x15\xf85\xbcv\x9d\xa8\x00\x00\xe0\x94\x18Z\u007f\u012c\xe3h\xd23\xe6 \xb2\xa4Y5f\x12\x92\xbd\xf2\x8a\x04<3\xc1\x93ud\x80\x00\x00\u07d4\x18d\xa3\u01f4\x81UD\x8cT\u020cp\x8f\x16g\tsm1\x89\a?u\u0460\x85\xba\x00\x00\u07d4\x18j\xfd\xc0\x85\xf2\xa3\xdc\xe4a^\xdf\xfb\xad\xf7\x1a\x11x\x0fP\x89\n\u05ce\xbcZ\xc6 \x00\x00\u07d4\x18k\x95\xf8\xe5\xef\xfd\xdc\xc9O\x1a1[\xf0)];\x1e\xa5\x88\x89lj\xccg\u05f1\xd4\x00\x00\u07d4\x18}\x9f\f\a\xf8\xebt\xfa\xaa\xd1^\xbc{\x80Dt\x17\xf7\x82\x89\x01\x15\x8eF\t\x13\xd0\x00\x00\u07d4\x18\x95\xa0\xebJCrr/\xcb\u016f\xe6\x93o(\x9c\x88\xa4\x19\x891T\xc9r\x9d\x05x\x00\x00\u07d4\x18\x99\xf6\x9fe;\x05\xa5\xa6\xe8\x1fH\a\x11\u041b\xbf\x97X\x8c\x89i\xfb\x13=\xf7P\xac\x00\x00\u07d4\x18\xa6\xd2\xfcR\xbes\b@#\xc9\x18\x02\xf0[\xc2JK\xe0\x9f\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\x18\xb0@|\xda\xd4\xceR`\x06#\xbd^\x1fj\x81\xaba\xf0&\x89\x11Q\xcc\xf0\xc6T\u0180\x00\u07d4\x18\xb8\xbc\xf9\x83!\xdaa\xfbN>\xac\xc1\xecT\x17'-\xc2~\x89/\xb4t\t\x8fg\xc0\x00\x00\u07d4\x18\xc6r:gS)\x9c\xb9\x14G}\x04\xa3\xbd!\x8d\xf8\xc7u\x8965\u026d\xc5\u07a0\x00\x00\u07d4\x18\xe1\x13\xd8\x17|i\x1aa\xbexXR\xfa[\xb4z\uef6f\x89Hz\x9a0E9D\x00\x00\xe0\x94\x18\xe4\xceGH;S\x04\n\u06eb5\x17,\x01\xefdPn\f\x8a\x01\xe7\xe4\x17\x1b\xf4\u04e0\x00\x00\xe0\x94\x18\xe52C\x98\x1a\xab\xc8v}\xa1\fsD\x9f\x13\x91V\x0e\xaa\x8a\x01EB\xba\x12\xa37\xc0\x00\x00\u07d4\x18\xfa\x86%\xc9\u0704<x\u01eb%\x9f\xf8|\x95\x99\xe0\u007f\x10\x8965\u026d\xc5\u07a0\x00\x00\u07d4\x18\xfb\t\x18\x8f'\xf1\x03\x8ee@1\x92Ob\x8a!\x06p=\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\x18\xfc\xcfb\xd2\xc39TS\xb7X{\x9e&\xf5\xcf\xf9\xebt\x82\x8965\u026d\xc5\u07a0\x00\x00\u07d4\x19\x13\x13RR8\xa2\x1cvtW\xa9\x13t\xf0\"\x00\xc5TH\x89\x06O_\xdfIOx\x00\x00\u07d4\x19\x14\xf1\xeb\x95\xd1'~\x93\xb6\xe6\x1bf\x8b}w\xf1:\x11\xa1\x894\x95tD\xb8@\xe8\x00\x00\u07d4\x19#\xcf\u018b\x13\xea~ U\x806E\xc1\xe3 \x15k\u060d\x89Hz\x9a0E9D\x00\x00\u07d4\x193j#m\xeduXrA\x1f.\x04\x91\xd8>>\x00\x15\x9e\x892\xf5\x1e\u06ea\xa30\x00\x00\xe0\x94\x193\xe34\xc4\x0f:\u02ed\f\v\x85\x11X i$\xbe\xca:\x8a\x01\x99^\xaf\x01\xb8\x96\x18\x80\x00\xe0\x94\x197\xc5\xc5\x15\x05uS\u033dF\u0546dU\xcef)\x02\x84\x8a\xd3\xc2\x1b\xce\xcc\xed\xa1\x00\x00\x00\u07d4\x19:\xc6Q\x83e\x18\x00\xe25\x80\xf8\xf0\xea\u04fbY~\xb8\xa4\x89\x02\xb6*\xbc\xfb\x91\n\x00\x00\u07d4\x19=7\xed4}\x1c/N55\r\x9aDK\xc5|\xa4\xdbC\x89\x03@\xaa\xd2\x1b;p\x00\x00\xe0\x94\x19@\u0713d\xa8R\x16_GAN'\xf5\x00$E\xa4\xf1C\x8a\x02L-\xffj<|H\x00\x00\u07d4\x19E\xfe7\u007f\xe6\u0537\x1e>y\x1fo\x17\xdb$<\x9b\x8b\x0f\x89vy\u7fb9\x886\x00\x00\u07d4\x19Jk\xb3\x02\xb8\xab\xa7\xa5\xb5y\u07d3\xe0\xdf\x15t\x96v%\x89\x1b\x1a\xe4\xd6\xe2\xefP\x00\x00\u07d4\x19L\ubd12\x98\x82\xbf;K\xf9\x86L+\x1b\x0fb\u0083\xf9\x89\x1e\xf8aS\x1ft\xaa\x00\x00\u07d4\x19O\xf4J\xef\xc1{\xd2\x0e\xfdz LG\xd1b\f\x86\xdb]\x89\xa2\x99\th\u007fj\xa4\x00\x00\xe0\x94\x19O\xfex\xbb\xf5\xd2\r\u044a\x1f\x01\xdaU.\x00\xb7\xb1\x1d\xb1\x8a\x01{x\x83\xc0i\x16`\x00\x00\u07d4\x19S1>*\xd7F#\x9c\xb2'\x0fH\xaf4\u063b\x9cDe\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\x19W\x1a+\x8f\x81\u01bc\xf6j\xb3\xa1\x00\x83)V\x17\x15\x00\x03\x89\x1a\xb2\xcf|\x9f\x87\xe2\x00\x00\xe0\x94\x19h}\xaa9\xc3h\x13\x9bn{\xe6\r\xc1u:\x9f\f\xbe\xa3\x8a\x01\xb1\xaeMn.\xf5\x00\x00\x00\u07d4\x19l\x02!\nE\n\xb0\xb3cpe_qz\xa8{\xd1\xc0\x04\x89\x0e\x10\xac\xe1W\xdb\xc0\x00\x00\u07d4\x19n\x85\xdf~s+J\x8f\x0e\xd06#\xf4\u06dd\xb0\xb8\xfa1\x89\x01%\xb9/\\\xef$\x80\x00\u07d4\x19s+\xf9s\x05]\xbd\x91\xa4S:\u06a2\x14\x9a\x91\u04c3\x80\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\x19vr\xfd9\xd6\xf2F\xcef\xa7\x90\xd1:\xa9\"\xd7\x0e\xa1\t\x8965\u026d\xc5\u07a0\x00\x00\u07d4\x19y\x8c\xbd\xa7\x15\ua69b\x9dj\xab\x94,U\x12\x1e\x98\xbf\x91\x89A\rXj \xa4\xc0\x00\x00\u07d4\x19\x8b\xfc\xf1\xb0z\xe3\b\xfa,\x02\x06\x9a\xc9\xda\xfeq5\xfbG\x89\x01\x15\x8eF\t\x13\xd0\x00\x00\xe0\x94\x19\x8e\xf1\xec2Z\x96\xcc5Lrf\xa08\xbe\x8b\\U\x8fg\x8a\x80\xd1\xe47>\u007f!\xda\x00\x00\xe0\x94\x19\x91\x8a\xa0\x9e}IN\x98\xff\xa5\xdbP5\b\x92\xf7\x15j\u018a\x02\x1e\x19\xe0\u027a\xb2@\x00\x00\u07d4\x19\xb3k\f\x87\xeafN\xd8\x03\x18\xdcw\xb6\x88\xdd\xe8}\x95\xa5\x89i\x9fI\x98\x020=\x00\x00\u07d4\x19\u07d4E\xa8\x1c\x1b=\x80J\xea\xebon NB6f?\x89\x02\x06\xd9NjI\x87\x80\x00\u07d4\x19\xe5\u07a37\n,tj\xae4\xa3|S\x1fA\xda&N\x83\x89\n\u05ce\xbcZ\xc6 \x00\x00\u07d4\x19\xe7\xf3\xeb{\xf6\u007f5\x99 \x9e\xbe\b\xb6*\xd32\u007f\x8c\u0789lk\x93[\x8b\xbd@\x00\x00\u07d4\x19\xe9Nb\x00P\xaa\xd7f\xb9\xe1\xba\xd91#\x83\x12\u053fI\x89\x81\xe3-\xf9r\xab\xf0\x00\x00\u07d4\x19\xec\xf2\xab\xf4\f\x9e\x85{%/\xe1\xdb\xfd=L]\x8f\x81n\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\x19\xf5\xca\xf4\xc4\x0ei\b\x81<\aE\xb0\xae\xa9Xm\x9d\xd91\x89#\xfe\xd9\xe1\xfa+`\x00\x00\u07d4\x19\xf6C\xe1\xa8\xfa\x04\xae\x16\x00`(\x13\x833\xa5\x9a\x96\u0787\x89\x01\x15\x8eF\t\x13\xd0\x00\x00\u07d4\x19\xf9\x9f,\vF\u0389\x06\x87]\xc9\xf9\n\xe1\x04\xda\xe3U\x94\x89\xf4WZ]M\x16*\x00\x00\u07d4\x19\xff$O\xcf\xe3\xd4\xfa/O\u065f\x87\xe5[\xb3\x15\xb8\x1e\xb6\x89\n\u05ce\xbcZ\xc6 \x00\x00\u07d4\x1a\x04\xce\xc4 \xadC\"\x15$mw\xfe\x17\x8d3\x9e\u0435\x95\x89\x11!a\x85\u009fp\x00\x00\xe0\x94\x1a\x04\xd58\x9e\xb0\x06\xf9\u0388\f0\xd1SS\xf8\xd1\x1cK1\x8a\x03\x9d\x84\xb2\x18m\xc9\x10\x00\x00\u07d4\x1a\bA\xb9*\u007fpuV\x9d\xc4b~kv\u02b0Z\u0791\x89Rf<\u02b1\xe1\xc0\x00\x00\xe0\x94\x1a\b]C\xec\x92AN\xa2{\x91O\xe7g\xb6\xd4k\x1e\xefD\x8a\x06A\xe8\xa15c\xd8\xf8\x00\x00\u07d4\x1a\t\xfd\xc2\u01e2\x0e#WK\x97\u019e\x93\u07bag\xd3r \x89lO\xd1\xee$nx\x00\x00\u07d4\x1a\n\x1d\u07f01\xe5\xc8\xcc\x1dF\xcf\x05\x84-P\xfd\xdcq0\x8965\u026d\xc5\u07a0\x00\x00\xe0\x94\x1a\x1c\x9a&\xe0\xe0$\x18\xa5\xcfh}\xa7Z'\\b,\x94@\x8a\x01\x0f\f\xf0d\xddY \x00\x00\u07d4\x1a \x1bC'\u03a7\xf3\x99\x04bF\xa3\xc8~n\x03\xa3\u0368\x8965\u026d\xc5\u07a0\x00\x00\u07d4\x1a$4\xccwD\"\u050dS\u055c]V,\u0384\a\xc9K\x89\x01\xa0Ui\r\x9d\xb8\x00\x00\u07d4\x1a%\xe1\u017c~_P\xec\x16\xf8\x88_!\x0e\xa1\xb98\x80\x0e\x89\xd8\xd7&\xb7\x17z\x80\x00\x00\u07d4\x1a&\x94\xec\a\xcf^Mh\xba@\xf3\xe7\xa1LS\xf3\x03\x8cn\x8966\xcd\x06\xe2\xdb:\x80\x00\u07d4\x1a5 E5\x82\xc7\x18\xa2\x1cB7[\xc5\as%RS\xe1\x89*\xd3s\xcef\x8e\x98\x00\x00\xe0\x94\x1a7n\x1b-/Y\ai\xbb\x85\x8dEu2\rN\x14\x99p\x8a\x01\x06q%v9\x1d\x18\x00\x00\u07d4\x1a:3\x0eO\xcbi\xdb\xef^i\x01x;\xf5\x0f\xd1\xc1SB\x89\u3bb5sr@\xa0\x00\x00\u07d4\x1aN\u01a0\xae\u007fZ\x94'\xd2=\xb9rL\r\f\xff\xb2\xab/\x89\t\xb4\x1f\xbf\x9e\n\xec\x00\x00\u07d4\x1aP^b\xa7N\x87\xe5wG>O:\xfa\x16\xbe\xdd<\xfaR\x89\x1b\x1a\xe4\xd6\xe2\xefP\x00\x00\u07d4\x1a^\xe53\xac\xbf\xb3\xa2\xd7m[hRw\xb7\x96\xc5j\x05+\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\x1adJP\xcb\u00ae\xe8#\xbd+\xf2C\xe8%\xbeMG\xdf\x02\x89\x05k\xe0<\xa3\xe4}\x80\x00\u07d4\x1apD\xe28?\x87\b0[I[\xd1\x17k\x92\xe7\xef\x04:\x89\n\u05ce\xbcZ\xc6 \x00\x00\u07d4\x1ay\xc7\xf4\x03\x9cg\xa3\x9du\x13\x88L\xdc\x0e,4\"$\x90\x89\x01\x15\x8eF\t\x13\xd0\x00\x00\u07d4\x1a\x89\x89\x9c\xbe\xbd\xbbd\xbb&\xa1\x95\xa6<\bI\x1f\u035e\xee\x89lk\x93[\x8b\xbd@\x00\x00\xe0\x94\x1a\x8a\\\xe4\x14\u079c\xd1r\x93~7\xf2\u055c\xffq\xceW\xa0\x8a\x02\x1e\x19\xe0\u027a\xb2@\x00\x00\u07d4\x1a\x95\xa8\xa8\b.FR\xe4\x17\r\xf9'\x1c\xb4\xbbC\x05\xf0\xb2\x89\x02\xb5\xe3\xaf\x16\xb1\x88\x00\x00\u07d4\x1a\x95\u0277Tk]\x17\x86\u00c5\x8f\xb1#dF\xbc\f\xa4\u0389j\xcb=\xf2~\x1f\x88\x00\x00\u07d4\x1a\x98~?\x83\xdeu\xa4/\x1b\xde|\x99|\x19!{J_$\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\x1a\x9ep/8]\xcd\x10^\x8b\x9f\xa4(\xee\xa2\x1cW\xffR\x8a\x89K\xe4\xe7&{j\xe0\x00\x00\u07d4\x1a\xa1\x02\x1fU\n\xf1X\xc7Gf\x8d\xd1;F1`\xf9Z@\x89O\xb0Y\x1b\x9b08\x00\x00\u07d4\x1a\xa2v\x99\xca\u068d\u00e7oy3\xaaf\xc7\x19\x19\x04\x0e\x88\x89\x15\xaf\x1dx\xb5\x8c@\x00\x00\u07d4\x1a\xa4\x02p\xd2\x1e\\\u0786\xb61m\x1a\xc3\xc53IKy\xed\x89\x01\x15\x8eF\t\x13\xd0\x00\x00\u07d4\x1a\xb5:\x11\xbc\xc6=\u07ea@\xa0+\x9e\x18d\x96\u037b\x8a\xff\x89l?*\xac\x80\f\x00\x00\x00\u07d4\x1a\xbcN%;\b\n\xebCy\x84\xab\x05\xbc\xa0\x97\x9a\xa4>\x1c\x8965\u026d\xc5\u07a0\x00\x00\u07d4\x1a\xc0\x89\u00fcM\x82\xf0j \x05\x1a\x9ds-\xc0\xe74\xcba\x89%\xf6\x9dc\xa6\xce\x0e\x00\x00\xe0\x94\x1a\xd4V>\xa5xk\xe1\x15\x995\xab\xb0\xf1\u0547\x9c>sr\x8a\x01EB\xba\x12\xa37\xc0\x00\x00\u07d4\x1a\xd7- \xa7n\u007f\xcckv@X\xf4\x8dA}Io\xa6\u0349lk\x93[\x8b\xbd@\x00\x00\xe0\x94\x1a\xda\xf4\xab\xfa\x86}\xb1\u007f\x99\xafj\xbe\xbfpz<\xf5]\xf6\x8a\x01EB\xba\x12\xa37\xc0\x00\x00\u07d4\x1a\xf6\x03C6\x0e\v-u%R\x107W \xdf!\xdb\\}\x8965\u026d\xc5\u07a0\x00\x00\u07d4\x1a\xfc\u0145\x89l\xd0\xed\xe1)\xee-\xe5\xc1\x9e\xa8\x11T\vd\x89\xaf*\xba\f\x8e[\xef\x80\x00\u07d4\x1b\x05\xeajj\u022f|\xb6\xa8\xb9\x11\xa8\xcc\xe8\xfe\x1a*\xcf\u0209lk\x93[\x8b\xbd@\x00\x00\u07d4\x1b\v1\xaf\xffKm\xf3e:\x94\xd7\xc8yx\xae5\xf3J\xae\x89\x139\x10E?\xa9\x84\x00\x00\u07d4\x1b\r\ah\x17\xe8\u058e\xe2\xdfN\x1d\xa1\xc1\x14-\x19\x8cD5\x89T\x06\x923\xbf\u007fx\x00\x00\u07d4\x1b\x13\ro\xa5\x1d\\H\xec\x8d\x1dR\u070a\"{\xe8s\\\x8a\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\x1b#\u02c6cUHq\xfb\xbe\r\x9e`9~\xfbo\xae\xdc>\x89\n\u05ce\xbcZ\xc6 \x00\x00\u07d4\x1b&9X\x8bU\xc3D\xb0#\xe8\xde_\xd4\b{\x1f\x04\x03a\x89QP\xae\x84\xa8\xcd\xf0\x00\x00\u07d4\x1b9 \xd0\x01\xc4>r\xb2N|\xa4o\x0f\xd6\xe0\xc2\n_\xf2\x89lk\x93[\x8b\xbd@\x00\x00\xe0\x94\x1b<\xb8\x1eQ\x01\x1bT\x9dx\xbfr\v\r\x92J\xc7c\xa7\u008av\x95\xa9, \xd6\xfe\x00\x00\x00\u07d4\x1bC#,\xcdH\x80\xd6\xf4o\xa7Q\xa9l\xd8$s1XA\x89\x04V9\x18$O@\x00\x00\u07d4\x1bK\xbc\xb1\x81e!\x1b&[(\a\x16\xcb?\x1f!!v\xe8\x89\x19\x9a\xd3}\x03\xd0`\x80\x00\u07d4\x1bM\a\xac\u04c1\x83\xa6\x1b\xb2x=+{\x17\x8d\xd5\x02\xac\x8d\x89\n\u05ce\xbcZ\xc6 \x00\x00\u07d4\x1bckzIo\x04MsYYn5:\x10F\x16Cok\x89\x13\x88\xea\x95\xc3?\x1d\x00\x00\u07d4\x1bd\x95\x89\x12@\xe6NYD\x93\xc2f!q\xdb^0\xce\x13\x89\tX\x87\u0595\xedX\x00\x00\u07d4\x1bf\x10\xfbh\xba\xd6\xed\x1c\xfa\xa0\xbb\xe3:$\xeb.\x96\xfa\xfb\x89\b=lz\xabc`\x00\x00\u07d4\x1by\x903\xefm\xc7\x12x\"\xf7EB\xbb\"\xdb\xfc\t\xa3\b\x89\x05k\xc7^-c\x10\x00\x00\u07d4\x1b~\xd9t\xb6\xe24\u0381$t\x98B\x9a[\u0520\xa2\xd19\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\x1b\x82o\xb3\xc0\x12\xb0\xd1Y\u253a[\x8aI\x9f\xf3\xc0\xe0<\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\x1b\x8a\xa0\x16\f\u05df\x00_\x88Q\nqI\x13\xd7\n\u04fe3\x89\n\xef\xfb\x83\a\x9a\xd0\x00\x00\xe0\x94\x1b\x8b\xd6\xd2\xec\xa2\x01\x85\xa7\x8e}\x98\xe8\xe1\x85g\x8d\xacH0\x8a\x03\x89O\x0eo\x9b\x9fp\x00\x00\u07d4\x1b\x9b-\u0096\x0eL\xb9@\x8ft\x05\x82|\x9bY\a\x16\x12\xfd\x8965\u026d\xc5\u07a0\x00\x00\xe0\x94\x1b\xa9\"\x8d8\x87'\xf3\x89\x15\x0e\xa0;s\xc8-\xe8\xeb.\t\x8a\x01\x89t\xfb\xe1w\xc9(\x00\x00\u07d4\x1b\xa9\xf7\x99~S\x87\xb6\xb2\xaa\x015\xac$R\xfe6\xb4\xc2\r\x89.\x14\x1e\xa0\x81\xca\b\x00\x00\u07d4\x1b\xba\x03\xffkJ\u057f\x18\x18J\xcb!\xb1\x88\xa3\x99\xe9\xebJ\x89a\t=|,m8\x00\x00\u07d4\x1b\xbc\x19\x9eXg\x90\xbe\x87\xaf\xed\xc8I\xc0G&t\\]{\x89\xd8\xd7&\xb7\x17z\x80\x00\x00\u07d4\x1b\xbc`\xbc\xc8\x0e\\\xdc5\xc5Aj\x1f\n@\xa8=\xae\x86{\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\x1b\xc4L\x87a#\x1b\xa1\xf1\x1f_\xaa@\xfaf\x9a\x01>\x12\u0389\v\tR\xc4Z\xea\xad\x00\x00\u07d4\x1b\xcf4A\xa8f\xbd\xbe\x960\t\xce3\xc8\x1c\xbb\x02a\xb0,\x89\t\xdd\xc1\xe3\xb9\x01\x18\x00\x00\u07d4\x1b\u048c\xd5\u01ca\xeeQ5|\x95\xc1\xef\x925\xe7\xc1\x8b\xc8T\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\x1b\xd8\xeb\xaavt\xbb\x18\u1458\xdb$OW\x03\x13\a_C\x89\b!\xab\rD\x14\x98\x00\x00\u07d4\x1b\xd9\t\xac\rJ\x11\x02\xec\x98\xdc\xf2\u0329j\n\xdc\u05e9Q\x89\x01\x16Q\xac>zu\x80\x00\u07d4\x1b\xe3T,6\x13hte\xf1Zp\xae\xeb\x81f+e\u0328\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\x1b\xeaM\xf5\x12/\xaf\u07b3`~\xdd\xda\x1e\xa4\xff\u06da\xbf*\x89\x12\xc1\xb6\xee\xd0=(\x00\x00\u07d4\x1b\xecM\x02\u0385\xfcH\xfe\xb6$\x89\x84\x1d\x85\xb1pXj\x9b\x89\x82\x1a\xb0\xd4AI\x80\x00\x00\u07d4\x1b\xf9t\u0650OE\u0381\xa8E\xe1\x1e\xf4\xcb\xcf'\xafq\x9e\x89\x05k\xc7^-c\x10\x00\x00\xe0\x94\x1c\x04VI\xcdS\xdc#T\x1f\x8e\xd4\xd3A\x81(\b\xd5\u075c\x8a\x01{x\x83\xc0i\x16`\x00\x00\u07d4\x1c\x12\x8b\xd6\u0365\xfc\xa2uu\xe4\xb4;2S\xc8\xc4\x17*\xfe\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\x1c\x13\u04c67\xb9\xa4|\xe7\x9d7\xa8oP\xfb@\x9c\x06\a(\x89Hz\x9a0E9D\x00\x00\u07d4\x1c \x10\xbdf-\xf4\x17\xf2\xa2q\x87\x9a\xfb\x13\xefL\x88\xa3\xae\x89\xd8\xd7&\xb7\x17z\x80\x00\x00\xe0\x94\x1c%z\u0525Q\x05\xea;X\xed7K\x19\x8d\xa2f\xc8_c\x8a\x02\x1e\x19\xe0\u027a\xb2@\x00\x00\xe0\x94\x1c.6\a\xe1'\xca\xca\x0f\xbd\\YH\xad\xad}\xd80\xb2\x85\x8a\x04+\xf0kx\xed;P\x00\x00\u07d4\x1c5l\xfd\xb9_\xeb\xb7\x14c;(\xd5\xc12\u0744\xa9\xb46\x89\x01Z\xf1\u05cbX\xc4\x00\x00\u07d4\x1c5\xaa\xb6\x88\xa0\u034e\xf8.vT\x1b\xa7\xac9R\u007ft;\x89\x1b\x1a\xe4\xd6\xe2\xefP\x00\x00\xe0\x94\x1c>\xf0]\xae\x9d\xcb\u0509\xf3\x02D\bf\x9d\xe2D\xc5*\x02\x8a\x04<3\xc1\x93ud\x80\x00\x00\u07d4\x1cJ\xf0\xe8c\xd2el\x865\xbco\xfe\xc8\u0759(\x90\x8c\xb5\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\x1c`\x19\x93x\x92\a\xf9e\xbb\x86\\\xbbL\xd6W\xcc\xe7o\xc0\x89\x05T\x1ap7P?\x00\x00\u07d4\x1cc\xfa\x9e,\xbb\xf2<I\xfc\xde\xf1\u02eb\xfen\r\x1e\x14\xc1\x8965\u026d\xc5\u07a0\x00\x00\xe0\x94\x1cg\x02\xb3\xb0ZQ\x14\xbd\xbc\xae\xca%S\x1a\xee\xb3H5\xf4\x8a\x05\x85V\xbe\xadE\u072e\x00\x00\u07d4\x1ch\xa6a8x:c\u024c\xc6u\xa9\xecw\xafE\x98\xd3^\x89\x02\xb7F\xf4\x8f\x0f\x12\x00\x00\u07d4\x1cs\xd0\vn%\xd8\xeb\x9c\x1f\xf4\xad\x82{k\x9e\x9c\xf6\xd2\f\x89\n\u05ce\xbcZ\xc6 \x00\x00\u07d4\x1cu\x1e\u007f$\u07dd\x94\xa67\xa5\xde\xde\xff\u0142w\xb5\xdb\x19\x89\xae\x8ez\v\xb5u\xd0\x00\x00\xe0\x94\x1c|\xb2\xfek\xf3\xe0\x9c\xbc\xdc\x18z\xf3\x8f\xa8\xf5\x05:p\xb6\x8a\x02\x1c\x84\xf7B\xd0\u03ad\x80\x00\xe0\x94\x1c\x89\x06\x0f\x98|Q\x8f\xa0y\xec,\n^\xbf\xa3\x0f] \xf7\x8a\b\v\xfb\xef\xcb_\v\xc0\x00\x00\u07d4\x1c\x94\xd66\xe6\x84\xeb\x15X\x95\xcem\xb4\xa2X\x8f\xba\x1d\x00\x1b\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\x1c\x99\xfe\x9b\xb6\xc6\xd1\x06m\x91 \x99T\u007f\xd1\U001007ac\u0649lk\x93[\x8b\xbd@\x00\x00\u07d4\x1c\xb4P\x92\x00x\xaa\xb21|}\xb3\xb3\x8a\xf7\xdd)\x8b-A\x89\x12nr\xa6\x9aP\xd0\x00\x00\u07d4\x1c\xb5\xf3;MH\x896\xd1>1a\xda3\xa1\xda}\xf7\r\x1b\x89\n\u05ce\xbcZ\xc6 \x00\x00\u07d4\x1c\xb6\xb2\xd7\xcf\xc5Y\xb7\xf4\x1eoV\xab\x95\xc7\xc9X\xcd\x0eL\x89Hz\x9a0E9D\x00\x00\u07d4\x1c\xc1\xd3\xc1O\x0f\xb8d\x0e6rM\xc42)\xd2\xeaz\x1eH\x89\\(=A\x03\x94\x10\x00\x00\u07d4\x1c\xc9\bv\x00A\t\xcdy\xa3\u07a8f\u02c4\n\xc3d\xba\x1b\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\x1c\xd1\xf0\xa3\x14\u02f2\x00\xde\n\f\xb1\xef\x97\xe9 p\x9d\x97\u0089lk\x93[\x8b\xbd@\x00\x00\u0794\x1c\xdaA\x1b\xd5\x16;\xae\xca\x1eU\x85c`\x1c\xe7 \xe2N\xe1\x88\xfc\x93c\x92\x80\x1c\x00\x00\u07d4\x1c\xe8\x1d1\xa7\x920\"\xe1%\xbfH\xa3\xe06\x93\xb9\x8d\xc9\u0749lk\x93[\x8b\xbd@\x00\x00\u07d4\x1c\xeb\xf0\x98]\u007fh\n\xaa\x91\\D\xccb\xed\xb4\x9e\xab&\x9e\x8965\u026d\xc5\u07a0\x00\x00\xe0\x94\x1c\xedg\x15\xf8b\xb1\xff\x86\x05\x82\x01\xfc\xceP\x82\xb3nb\xb2\x8a\x01j^`\xbe\xe2s\xb1\x00\x00\u07d4\x1c\xf0L\xb1C\x80\x05\x9e\xfd?#\x8be\u057e\xb8j\xfa\x14\u0609\x01\x15\x8eF\t\x13\xd0\x00\x00\u07d4\x1c\xf1\x05\xab#\x02;ULX>\x86\u05d2\x11y\xee\x83\x16\x9f\x89j\xcb=\xf2~\x1f\x88\x00\x00\u07d4\x1c\xf2\xebz\x8c\xca\u00ad\xea\xef\x0e\xe8sG\xd55\u04f9@X\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\x1c\xfc\xf7Q\u007f\f\bE\x97 \x94+dz\u0452\xaa\x9c\x88(\x89+^:\xf1k\x18\x80\x00\x00\xe0\x94\x1d\t\xad$\x12i\x1c\u0141\xc1\xab6\xb6\xf9CL\xd4\xf0\x8bT\x8a\x01{x\x83\xc0i\x16`\x00\x00\u07d4\x1d\x15|Xv\xc5\xca\xd5S\xc9\x12\xca\xf6\xce-Rw\xe0\\s\x89lk\x93[\x8b\xbd@\x00\x00\xe0\x94\x1d&\x15\xf8\xb6\xcaP\x12\xb6c\xbd\u0414\xb0\xc5\x13|w\x8d\u07ca\x02\x1e\x19\xe0\u027a\xb2@\x00\x00\u07d4\x1d)\u01ea\xb4+ H\u04b2R%\u0518\u06e6z\x03\xfb\xb2\x89\n\u05ce\xbcZ\xc6 \x00\x00\u0794\x1d4\x1f\xa5\xa3\xa1\xbd\x05\x1f}\xb8\a\xb6\xdb/\u01faO\x9bE\x88\xfc\x93c\x92\x80\x1c\x00\x00\u07d4\x1d4N\x96%g\xcb'\xe4M\xb9\xf2\xfa\u01f6\x8d\xf1\xc1\xe6\xf7\x89i*\xe8\x89p\x81\xd0\x00\x00\u07d4\x1d6h0c\xb7\xe9\xeb\x99F-\xab\xd5i\xbd\xdc\xe7\x16\x86\xf2\x8965\u026d\xc5\u07a0\x00\x00\u07d4\x1d7aky?\x94\x91\x188\xac\x8e\x19\xee\x94I\u07d2\x1e\u0109QP\xae\x84\xa8\xcd\xf0\x00\x00\xe0\x94\x1d9[0\xad\xda\x1c\xf2\x1f\t\x1aOJ{u3q\x18\x94A\x8a\x15-\x02\xc7\xe1J\xf6\x80\x00\x00\u07d4\x1dEXn\xb8\x03\xca!\x90e\v\xf7H\xa2\xb1t1+\xb5\a\x89K\xe4\xe7&{j\xe0\x00\x00\u07d4\x1dW.\xdd-\x87\xca'\x1ag\x14\xc1Z;7v\x1d\u0320\x05\x89\x06\xeb\xd5*\x8d\xdd9\x00\x00\u07d4\x1dc0\x97\xa8R%\xa1\xffC!\xb1)\x88\xfd\xd5\\+8D\x89\xd8\xd7&\xb7\x17z\x80\x00\x00\xe0\x94\x1di\xc8=(\xff\x04t\xce\xeb\xea\xcb:\xd2'\xa1D\xec\u78ca\x01(\xcc\x03\x92\nb\u0480\x00\u07d4\x1d\x96\xbc\u0544W\xbb\xf1\xd3\u00a4o\xfa\xf1m\xbf}\x83hY\x89\tIr\t\xd8F~\x80\x00\u07d4\x1d\x9ej\xaf\x80\x19\xa0_#\x0e]\xef\x05\xaf]\x88\x9b\xd4\xd0\xf2\x89\a?u\u0460\x85\xba\x00\x00\u07d4\x1d\xab\x17.\xff\xa6\xfb\xeeSL\x94\xb1~yN\xda\xc5OU\xf8\x89j\xcb=\xf2~\x1f\x88\x00\x00\u07d4\x1d\xb9\xac\x9a\x9e\xae\xec\nR7W\x05\fq\xf4rx\xc7-P\x89Hz\x9a0E9D\x00\x00\u07d4\x1d\xbe\x8e\x1c+\x8a\x00\x9f\x85\xf1\xad<\xe8\r.\x055\x0e\u3709\aW\rn\x9e\xbb\xe4\x00\x00\u07d4\x1d\xc7\xf7\xda\xd8]\xf5?\x12q\x15$\x03\xf4\xe1\xe4\xfd\xb3\xaf\xa0\x89\n\u05ce\xbcZ\xc6 \x00\x00\u07d4\x1d\u03bc\xb7em\xf5\u072a3h\xa0U\xd2/\x9e\xd6\xcd\xd9@\x89\x1b\x18\x1eK\xf24<\x00\x00\xe0\x94\x1d\xd7tA\x84J\xfe\x9c\xc1\x8f\x15\xd8\xc7{\xcc\xfbe^\xe04\x8a\x01\x06\xebEW\x99D\x88\x00\x00\u07d4\x1d\xde\xfe\xfd5\xab\x8fe\x8b$q\xe5G\x90\xbc\x17\xaf\x98\u07a4\x8965\u026d\xc5\u07a0\x00\x00\u07d4\x1d\xee\xc0\x1a\xbe\\\r\x95-\xe9\x10l=\xc3\x069\xd8P\x05\u0589lk\x93[\x8b\xbd@\x00\x00\u07d4\x1d\xf6\x91\x16rg\x9b\xb0\xef5\t\x03\x8c\f'\xe3\x94\xfd\xfe0\x89\x1dF\x01b\xf5\x16\xf0\x00\x00\u07d4\x1d\xfa\xee\ar\x12\xf1\xbe\xaf\x0eo/\x18@Sz\xe1T\xad\x86\x8965\u026d\xc5\u07a0\x00\x00\xe0\x94\x1e\x06\r\xc6\xc5\xf1\u02cc\xc7\xe1E.\x02\xee\x16u\b\xb5eB\x8a\x02\xb1O\x02\xc8d\xc7~\x00\x00\xe0\x94\x1e\x13\xecQ\x14,\ubde2`\x83A,<\xe3QD\xbaV\xa1\x8a\x01\x0f\f\xf0d\xddY \x00\x00\u07d4\x1e\x1aH(\x11\x9b\xe3\t\xbd\x88#nMH+PM\xc5W\x11\x89\xa00\xdc\xeb\xbd/L\x00\x00\u07d4\x1e\x1a\ud178leb\u02cf\xa1\xebo\x8f;\xc9\u072eny\x89\xf4\xd2\u0744%\x9b$\x00\x00\u07d4\x1e\x1ccQwj\xc3\x10\x919~\xcf\x16\x00-\x97\x9a\x1b-Q\x89K\xe4\xe7&{j\xe0\x00\x00\u07d4\x1e\x1dz_$h\xb9N\xa8&\x98-\xbf!%y<nJZ\x8964\xf4\x84\x17@\x1a\x00\x00\u07d4\x1e!\x0epG\x88m\xaaR\xaa\xf7\x0fK\x99\x1d\xach\xe3\x02^\x89\n\u05ce\xbcZ\xc6 \x00\x00\u07d4\x1e+\xf4\xba\x8e^\xf1\x8d7\xdemj\xd66\xc4\xca\xe4\x89\xd0\u0309lk\x93[\x8b\xbd@\x00\x00\u07d4\x1e/\xe4\xe4\xa7}\x14\x1f\xf4\x9a\f\u007f\xbc\x95\xb0\xa2\xb2\x83\xee\xeb\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\x1e3\xd1\xc2\xfb^\bO/\x1dT\xbcRgr\u007f\xec?\x98]\x89\x1b\x1a\xe4\xd6\xe2\xefP\x00\x00\u07d4\x1e8\x1a\xdc\xf8\x01\xa3\xbf\x9f\u05ff\xac\x9c\xcc+\x84\x82\xad^f\x89 \x89r\xc0\x01\rt\x00\x00\xe0\x94\x1e;\xad\xb1\xb6\xe18\x0e'\x03\x9cWj\xe6\".\x96:[S\x8a\x04<3\xc1\x93ud\x80\x00\x00\u07d4\x1eHM\x06!\xf0\xf53\x1b5\xd5@\x8d\x9a\xaeN\xb1\xac\xf2\x1e\x89\x01\x15\x8eF\t\x13\xd0\x00\x00\u07d4\x1eX\x00\"}M\xcfu\xe3\x0fU\x95\u017e\xd3\xf7.4\x1e;\x89\ru\xda\xcesA~\x00\x00\u07d4\x1eYj\x81\xb3W\xc6\xf2Ip\xcc1=\xf6\xdb\u06ab\xd0\u041e\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\x1ei\x15\xeb\u0661\x9c\x81\xb6\x92\xad\x99\xb1!\x8aY,\x1a\u01f1\x89\xd8\xd7&\xb7\x17z\x80\x00\x00\u07d4\x1en\x01S\xfc\x16\x1b\xc0^ek\xbb\x14Lq\x87\xbfO\xe8M\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\x1epfU\xe2\x84\xdc\xf0\xbb7\xfe\a]a:\x18\xdc\x12\xffJ\x89\xedC\xbf\x1e\ue0ac\x00\x00\xe0\x94\x1ex>R*\xb7\xdf\n\u02ac\x9e\xee\xd3Y09\xe5\xacuy\x8a+\x14F\xddj\xef\xe4\x1c\x00\x00\u07d4\x1e{^M\x1fW+\xec\xf2\xc0\x0f\xc9\f\xb4v{Jn3\u0509\x06\x1f\xc6\x10u\x93\xe1\x00\x00\u07d4\x1e\x8eh\x9b\x02\x91|\xdc)$]\f\x9ch\xb0\x94\xb4\x1a\x9e\u0589lk\x93[\x8b\xbd@\x00\x00\u07d4\x1e\xa34\xb5u\b\a\xeat\xaa\u016b\x86\x94\xec_(\xaaw\u03c9\x1a\xb2\xcf|\x9f\x87\xe2\x00\x00\u07d4\x1e\xa4qU\x04\u01af\x10{\x01\x94\xf4\xf7\xb1\xcbo\xcc\xcdoK\x89 \x041\x97\xe0\xb0'\x00\x00\u07d4\x1e\xa4\x92\xbc\xe1\xad\x10~3\u007fK\u0527\xac\x9a{\xab\xcc\u036b\x89\x05k\xc7^-c\x10\x00\x00\u07d4\x1e\xa6\xbf/\x15\xae\x9c\x1d\xbcd\u06a7\xf8\xeaM\r\x81\xaa\xd3\xeb\x89\u3bb5sr@\xa0\x00\x00\u07d4\x1e\xb4\xbfs\x15j\x82\xa0\xa6\x82 \x80\xc6\xed\xf4\x9cF\x9a\xf8\xb9\x89g\x8a\x93 b\xe4\x18\x00\x00\xe0\x94\x1e\xba\xcbxD\xfd\xc3\"\xf8\x05\x90O\xbf\x19b\x80-\xb1S|\x8a\x02\x1e\x19\xe0\u027a\xb2@\x00\x00\u07d4\x1e\xc4\xecKw\xbf\x19\u0411\xa8h\xe6\xf4\x91T\x18\x05A\xf9\x0e\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\x1e\xd0n\xe5\x16b\xa8lcE\x88\xfbb\xdcC\xc8\xf2~|\x17\x89\n\u05ce\xbcZ\xc6 \x00\x00\u07d4\x1e\u063b?\x06w\x8b\x03\x9e\x99a\xd8\x1c\xb7\x1as\xe6x|\x8e\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\x1e\xda\bNye\x00\xba\x14\xc5\x12\x1c\r\x90\x84of\xe4\xbeb\x89\x1c\xfd\xd7F\x82\x16\xe8\x00\x00\u07d4\x1e\xeel\xbe\xe4\xfe\x96\xadaZ\x9c\xf5\x85zdy@\u07ccx\x89\x01\r:\xa56\xe2\x94\x00\x00\u07d4\x1e\xf2\u073f\xe0\xa5\x00A\x1d\x95n\xb8\u0213\x9c=l\xfef\x9d\x89*\x11)\u0413g \x00\x00\xe0\x94\x1e\xf5\xc9\xc76P\u03fb\xde\\\x88U1\xd4'\xc7\xc3\xfeUD\x8a\x01EB\xba\x12\xa37\xc0\x00\x00\u07d4\x1f\x04\x12\xbf\xed\u0356N\x83}\t,q\xa5\xfc\xba\xf3\x01&\xe2\x89\x01\x15\x8eF\t\x13\xd0\x00\x00\u07d4\x1f\x17O@\xa0Dr4\xe6fS\x91Mu\xbc\x00>V\x90\u0709\b\xacr0H\x9e\x80\x00\x00\u07d4\x1f!\x86\xde\xd2>\f\xf9R\x16\x94\xe4\xe1dY>i\n\x96\x85\x89\x10CV\x1a\x88)0\x00\x00\u07d4\x1f*\xfc\n\xed\x11\xbf\xc7\x1ew\xa9\ae{6\xeav\xe3\xfb\x99\x89\xd8\xd7&\xb7\x17z\x80\x00\x00\u0794\x1f9Y\xfc)\x11\x10\xe8\x822\xc3kvg\xfcx\xa3ya?\x88\xfc\x93c\x92\x80\x1c\x00\x00\u07d4\x1f=\xa6\x8f\xe8~\xafC\xa8)\xabm~\u0166\xe0\t\xb2\x04\xfb\x89\x1e\x16\x01u\x8c,~\x00\x00\u07d4\x1fI\xb8m\r9EY\x06\x98\xa6\xaa\xf1g<7u\\\xa8\r\x89%\xf2s\x93=\xb5p\x00\x00\u07d4\x1f_;4\xbd\x13K'\x81\xaf\xe5\xa0BJ\u0144l\xde\xfd\x11\x89\x05]\xe6\xa7y\xbb\xac\x00\x00\u07d4\x1fo\x0004\x97R\x06\x1c\x96\a+\xc3\xd6\xeb5I \x8dk\x89\x01K\x8d\xe1\xeb\x88\u06c0\x00\u07d4\x1f}\x8e\x86\xd6\xee\xb0%E\xaa\xd9\x0e\x912{\xd3i\xd7\xd2\xf3\x89\x01\x15\x8eF\t\x13\xd0\x00\x00\u07d4\x1f\x81\x16\xbd\n\xf5W\x0e\xaf\fV\u011cz\xb5\xe3zX\x04X\x89lk\x93[\x8b\xbd@\x00\x00\u0794\x1f\x88\xf8\xa13\x8f\xc7\xc1\tv\xab\xcd?\xb8\u04c5T\xb5\uc708\xb9\xf6]\x00\xf6<\x00\x00\u07d4\x1f\x9c2hE\x8d\xa3\x01\xa2\xbeZ\xb0\x82W\xf7{\xb5\xa9\x8a\xa4\x89\n\u05ce\xbcZ\xc6 \x00\x00\u07d4\x1f\xa21\x9f\xed\x8c-F*\xdf.\x17\xfe\xecjo0Qn\x95\x89\x06\xca\xe3\x06!\xd4r\x00\x00\u07d4\x1f\xb4c\xa08\x99\x83\xdf}Y?{\xddmxI\u007f\xed\x88y\x89\x01\x15\x8eF\t\x13\xd0\x00\x00\u07d4\x1f\xb7\xbd1\r\x95\xf2\xa6\u067a\xaf\x8a\x8aC\n\x9a\x04E:\x8b\x89\xa2\xa1]\tQ\x9b\xe0\x00\x00\u07d4\x1f\xcc|\xe6\xa8HX\x95\xa3\x19\x9e\x16H\x1fr\xe1\xf7b\xde\xfe\x8965\u026d\xc5\u07a0\x00\x00\u07d4\x1f\xcf\xd1\xd5\u007f\x87\"\x90V\f\xb6-`\x0e\x1d\xef\xbe\xfc\xcc\x1c\x89P\xc5\xe7a\xa4D\b\x00\x00\u0794\x1f\u0496\xbe\x03\xads|\x92\xf9\u0186\x9e\x8d\x80\xa7\x1cW\x14\xaa\x88\xb9\x8b\xc8)\xa6\xf9\x00\x00\u07d4\x1f\xdd\xd8_\u024b\xe9\xc4\x04Ya\xf4\x0f\x93\x80^\xccEI\xe5\x89\b\xe3\xf5\v\x17<\x10\x00\x00\u07d4 \x01\xbe\xf7{f\xf5\x1e\x15\x99\xb0/\xb1\x10\x19J\x00\x99\xb7\x8d\x89lk\x93[\x8b\xbd@\x00\x00\u07d4 \x02d\xa0\x9f\x8ch\xe3\xe6b\x97\x95(\x0fV%O\x86@\u0409\x01\x15\x8eF\t\x13\xd0\x00\x00\u07d4 \x03qy\a\xa7%`\xf40\u007f\x1b\xee\xccT6\xf4=!\xe7\x89\x1b\x1a\xe4\xd6\xe2\xefP\x00\x00\u07d4 \r\xfc\vq\xe3Y\xb2\xb4eD\n6\xa6\xcd\xc3Rw0\a\x89QP\xae\x84\xa8\xcd\xf0\x00\x00\u07d4 \x13L\xbf\xf8\x8b\xfa\xdcFkR\xec\ua9d8W\x89\x1d\x83\x1e\x8965\u026d\xc5\u07a0\x00\x00\u07d4 \x14&\x1f\x01\b\x9fSyV0\xba\x9d\xd2O\x9a4\xc2\xd9B\x89Hz\x9a0E9D\x00\x00\u07d4 \x16\x89]\xf3,\x8e\xd5G\x82iF\x84#\xae\xa7\xb7\xfb\xceP\x89\x01\x15\x8eF\t\x13\xd0\x00\x00\u07d4 \x18\x1cKA\xf6\xf9r\xb6iX!_\x19\xf5p\xc1]\xdf\xf1\x89V\xbcu\xe2\xd61\x00\x00\x00\u07d4 \x18d\xa8\xf7\x84\xc2'{\v|\x9e\xe74\xf7\xb3w\xea\xb6H\x89\xf2(\x14\x00\xd1\xd5\xec\x00\x00\u07d4 \xb8\x1a\xe59&\xac\xe9\xf7\xd7AZ\x05\f\x03\x1dX_ \x89\x12\u007f\x19\xe8>\xb3H\x00\x00\xe0\x94 <b\x83\xf2\r\xf7\xbc\x86T/\u07f4\xe7c\xec\u06fb\xee\xf5\x8a\x05K@\xb1\xf8R\xbd\xa0\x00\x00\xe0\x94 J\u0248g\xa7\xc9\xc7\xedq\x1c\xb8/(\xa8x\xca\xf6\x9bH\x8a\x01EB\xba\x12\xa37\xc0\x00\x00\u07d4 R7\u013e\x14o\xba\x99G\x8f:}\xad\x17\xb0\x918\u0695\x89lk\x93[\x8b\xbd@\x00\x00\u07d4 S\xac\x97T\x8a\fN\x8b\x80\xbcrY\f\u05a0\x98\xfeu\x16\x89\n#%u;F\f\x00\x00\u07d4 _Qf\xf1$@\xd8Wb\xc9g\u04ee\x86\x18O\x8fM\x98\x89\x17r$\xaa\x84Lr\x00\x00\xe0\x94 _\xc8C\xe1\x9aI\x13\u0448\x1e\xb6\x9bi\xc0\xfa;\xe5\xc5\v\x8a\x02\r\u058a\xaf2\x89\x10\x00\x00\u07d4 d\x82\xeeo\x13\x8aw\x8f\xe1\xadb\xb1\x80\u0385o\xbb#\xe6\x89lk\x93[\x8b\xbd@\x00\x00\xe0\x94 fwM\x82'\x93\xff%\xf1v\t\tG\x9c\xf6$\x91\xbf\x88\x8a\v\xae:\u0185\xcbr\xe0\x00\x00\u07d4 mU\xd5y*QN\xc1\b\xe0\x90Y\x9f*\x06^P\x11\x85\x89\n\xdf0\xbap\u0217\x00\x00\u07d4 p~B]*\x11\xd2\u021f9\x1b+\x80\x9fUlY$!\x89lk\x93[\x8b\xbd@\x00\x00\xe0\x94 ~\xf8\v]`\xb6\xfb\xff\xc5\x1f:d\xb8\xc7 6\xa5\xab\xbd\x8a\x01je\x02\xf1Z\x1eT\x00\x00\xe0\x94 \x82K\xa1\xdb\xeb\xbe\xf9\x84n\xf3\xd0\xf6\xc1\xb0\x17\xe6\x91.\u010a\x01\x84\xb2nM\xaf\x1d5\x00\x00\u07d4 \x84\xfc\xe5\x05\xd9{\xeb\xf1\xad\x8c_\xf6\x82o\xc6E7\x1f\xb2\x89\x01\xa0Ui\r\x9d\xb8\x00\x00\u07d4 \x8cEs,\n7\x8f\x17\xac\x83$\x92mE\x9b\xa8\xb6X\xb4\x89\xa00\xdc\xeb\xbd/L\x00\x00\u07d4 \x93w\xb6\xad?\xe1\x01\xc9h[5vT\\k\x16\x84\xe7<\x89b\xa9\x92\xe5:\n\xf0\x00\x00\u07d4 \x9e\x8e)\xd3;\xea\xe8\xfbk\xaax=\x13>\x1d\x9e\xc1\xbc\v\x89-C\xf3\xeb\xfa\xfb,\x00\x00\u07d4 \xa1RV\xd5\f\xe0X\xbf\x0e\xacC\xaaS:\xa1n\u0273\x80\x89\x01\x15\x8eF\t\x13\xd0\x00\x00\u07d4 \xa2\x9cPy\xe2k?\x181\x8b\xb2\xe5\x0e\x8e\x8b4n[\xe8\x89\x1b\x1a\xb3\x19\xf5\xecu\x00\x00\u07d4 \xa8\x16\x80\xe4e\xf8\x87\x90\xf0\aO`\xb4\xf3_]\x1ej\xa5\x89Ea\x80'\x8f\fw\x80\x00\u07d4 \xb9\xa9\u6f48\x80\u0659J\xe0\r\u0439(*\v\xea\xb8\x16\x89\x1b\x1a\xe4\xd6\xe2\xefP\x00\x00\u07d4 \u0084\xba\x10\xa2\b0\xfc=i\x9e\xc9}-\xfa'\xe1\xb9^\x89lk\x93[\x8b\xbd@\x00\x00\u07d4 \xd1A\u007f\x99\xc5i\u3fb0\x95\x85e0\xfe\x12\xd0\xfc\uaa89@\x15\xf9K\x11\x83i\x80\x00\u07d4 \u074f\u02f4n\xa4o\u3066\x8b\x8c\xa0\xea[\xe2\x1f\u9949lk\x93[\x8b\xbd@\x00\x00\xe0\x94 \xff>\u078c\xad\xb5\xc3{H\xcb\x14X\x0f\xb6^#\t\n{\x8a\b\xe4\xd3\x16\x82v\x86@\x00\x00\xe0\x94!\x008\x1d`\xa5\xb5J\xdc\t\u0456\x83\xa8\xf6\u057bK\xfb\u02ca\x02\x1e\x19\xe0\u027a\xb2@\x00\x00\xe0\x94!\x18\xc1\x16\xab\f\xdfo\xd1\x1dT\xa40\x93\a\xb4w\xc3\xfc\x0f\x8a\x02\x1e\x19\xe0\u027a\xb2@\x00\x00\xe0\x94!\x1b)\xce\xfcy\xae\x97gD\xfd\xeb\u03bd<\xbb2\xc5\x13\x03\x8a\x02\xf6\xf1\a\x80\xd2,\xc0\x00\x00\u07d4! l\xe2.\xa4\x80\xe8Y@\xd3\x13\x14\xe0\xd6ONM:\x04\x8965\u026d\xc5\u07a0\x00\x00\u07d4!2\xc0Qj.\x17\x17J\xc5G\xc4;{\x00 \xd1\xebLY\x895e\x9e\xf9?\x0f\xc4\x00\x00\xe0\x94!@\x8bMz,\x0en\xcaAC\xf2\xca\u037b\u033a\x12\x1b\u060a\x04<3\xc1\x93ud\x80\x00\x00\u07d4!Kt9U\xa5\x12\xden\r\x88j\x8c\xbd\x02\x82\xbe\xe6\u04a2\x89lk\x93[\x8b\xbd@\x00\x00\u07d4!L\x89\u017d\x8e}\"\xbcWK\xb3^H\x95\x02\x11\xc6\xf7v\x89\x01\x06T\xf2X\xfd5\x80\x00\xe0\x94!Ti\x14\xdf\u04ef*\xddA\xb0\xff>\x83\xff\xdat\x14\xe1\xe0\x8a\x01C\x95\xe78ZP.\x00\x00\u07d4!X.\x99\xe5\x02\xcb\xf3\xd3\xc2;\xdf\xfbv\xe9\x01\xacmV\xb2\x89\x05k\xc7^-c\x10\x00\x00\u07d4!Y$\b\x13\xa70\x95\xa7\xeb\xf7\u00f3t>\x80(\xae_\t\x89lk\x93[\x8b\xbd@\x00\x00\u07d4!`\xb4\xc0,\xac\n\x81\u0791\b\xdeCE\x90\xa8\xbf\xe6\x875\x89j\xcb=\xf2~\x1f\x88\x00\x00\xe0\x94!nA\x86N\xf9\x8f\x06\r\xa0\x8e\xca\xe1\x9a\xd1\x16j\x17\xd06\x8a\x016\x9f\xb9a(\xacH\x00\x00\u07d4!\x84o/\xdfZA\xed\x8d\xf3n^\xd8TM\xf7Y\x88\xec\xe3\x89lj\xccg\u05f1\xd4\x00\x00\xe0\x94!\xa6\xdbe'F{\xc6\xda\xd5K\xc1n\x9f\xe2\x95;g\x94\xed\x8a\x02\xf6\xf1\a\x80\xd2,\xc0\x00\x00\u07d4!\xa6\xfe\xb6\xab\x11\xc7f\xfd\xd9w\xf8\xdfA!\x15_G\xa1\xc0\x89\x03\x19\xcf8\xf1\x00X\x00\x00\u07d4!\xb1\x82\xf2\xda+8D\x93\xcf_5\xf8=\x9d\x1e\xe1O*!\x89lk\x93[\x8b\xbd@\x00\x00\u07d4!\xbf\xe1\xb4\\\xac\xdebt\xfd\x86\b\u0661x\xbf>\xebn\u0709l\xee\x06\u077e\x15\xec\x00\x00\u07d4!\xc0s\x80HOl\xbc\x87$\xad2\xbc\x86L;Z\xd5\x00\xb7\x8965\u026d\xc5\u07a0\x00\x00\xe0\x94!\u00e8\xbb\xa2g\xc8\u0322{\x1a\x9a\xfa\xba\xd8o`z\xf7\b\x8a\x01\xe4\xa3lI\u06580\x00\x00\u07d4!\xcem[\x90\x18\xce\xc0J\u0596yD\xbe\xa3\x9e\x800\xb6\xb8\x89\x01\x15\x8eF\t\x13\xd0\x00\x00\u07d4!\xd0'\x05\xf3\xf6I\x05\xd8\x0e\xd9\x14y\x13\xea\x8cs\a\u0595\x89I\xed\xb1\xc0\x98\x876\x00\x00\u07d4!\xd1?\f@$\xe9g\xd9G\a\x91\xb5\x0f\"\xde:\xfe\xcf\x1b\x89\xf1Z\xd3^.1\xe5\x00\x00\xe0\x94!\xdb\u06c1z\r\x84\x04\u01bd\xd6\x15\x047N\x9cC\xc9!\x0e\x8a\x02\x1e\x18\xb9\xe9\xabE\xe4\x80\x00\xe0\x94!\xdf\x1e\xc2KNK\xfey\xb0\xc0\x95\u03ba\xe1\x98\xf2\x91\xfb\u044a\x04<3\xc1\x93ud\x80\x00\x00\xe0\x94!\xdf-\u036ft\xb2\xbf\x804\x04\xddM\xe6\xa3^\xab\xec\x1b\xbd\x8a\x01w\"J\xa8D\xc7 \x00\x00\u07d4!\xe2\x19\u021c\xa8\xac\x14\xaeL\xbaa0\xee\xb7}\x9em9b\x89*\u035f\xaa\xa08\xee\x00\x00\u07d4!\xe5\u04ba\xe9\x95\xcc\xfd\b\xa5\xc1k\xb5$\xe1\xf60D\x8f\x82\x89\x97\xc9\xceL\xf6\xd5\xc0\x00\x00\u07d4!\xe5\xd7s 0L \x1c\x1eS\xb2a\xa1#\u0421\x06>\x81\x89\x04\xb6\xfa\x9d3\xddF\x00\x00\xe0\x94!\xea\xe6\xfe\xff\xa9\xfb\xf4\u0347OG9\xac\xe50\u033eY7\x8a\x01\x0f\f\xf0d\xddY \x00\x00\u07d4!\xec\xb2\u07e6Wy\xc7Y-\x04\x1c\xd2\x10Z\x81\xf4\xfdNF\x8965\u026d\xc5\u07a0\x00\x00\u07d4!\uff20\x9b5\x80\xb9\x8es\xf5\xb2\xf7\xf4\xdc\v\xf0,R\x9c\x89lk\x93[\x8b\xbd@\x00\x00\u07d4!\xfd\v\xad\xe5\xf4\xeftt\xd0X\xb7\xf3\xd8T\xcb\x13\x00RN\x89\x01\x15\x8eF\t\x13\xd0\x00\x00\xe0\x94!\xfdG\xc5%`\x12\x19\x8f\xa5\xab\xf11\xc0mj\xa1\x96_u\x8a\x01\xab,\xf7\xc9\xf8~ \x00\x00\u07d4!\xfdl]\x97\xf9\xc6\x00\xb7h!\xdd\xd4\xe7v5\x0f\xce+\xe0\x89lj\u04c2\xd4\xfba\x00\x00\u07d4\"\r\u018d\xf0\x19\xb6\xb0\u033f\xfbxKZZ\xb4\xb1]@`\x89\u0556{\xe4\xfc?\x10\x00\x00\u07d4\"\x0e+\x92\xc0\xf6\xc9\x02\xb5\x13\xd9\xf1\xe6\xfa\xb6\xa8\xb0\xde\xf3\u05c9+^:\xf1k\x18\x80\x00\x00\u07d4\"V\x1cY1\x14560\x9c\x17\xe82X{b\\9\v\x9a\x89\xd8\xd7&\xb7\x17z\x80\x00\x00\u07d4\"W\xfc\xa1jn\\*d|<)\xf3l\xe2)\xab\x93\xb1~\x89\xd8\xd7&\xb7\x17z\x80\x00\x00\u07d4\"]5\xfa\xed\xb3\x91\u01fc-\xb7\xfa\x90q\x16\x04\x05\x99m\x00\x89\t\x18T\xfc\x18bc\x00\x00\u07d4\"_\x9e\xb3\xfbo\xf3\xe9\xe3\xc8D~\x14\xa6n\x8dO7y\xf6\x89lk\x93[\x8b\xbd@\x00\x00\xe0\x94\"r\x18n\xf2}\xcb\xe2\xf5\xfc70P\xfd\xae\u007f*\xce#\x16\x8a\x03h\xc8b:\x8bM\x10\x00\x00\u07d4\"s\xba\u05fcNHv\"\xd1u\xefzf\x98\x8bj\x93\xc4\xee\x89\x01\x15\x8eF\t\x13\xd0\x00\x00\u07d4\"v&K\xec\x85&\xc0\xc0\xf2pgz\xba\xf4\xf0\xe4A\xe1g\x8965\u026d\xc5\u07a0\x00\x00\xe0\x94\"\x82B\xf83n\xec\xd8$.\x1f\x00\x0fA\x93~q\xdf\xfb\xbf\x8a\x01\x0f\f\xf0d\xddY \x00\x00\u07d4\"\x84*\xb80\xdaP\x99\x13\xf8\x1d\xd1\xf0O\x10\xaf\x9e\xdd\x1cU\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\"\x94O\xbc\xa9\xb5yc\bN\xb8M\xf7\xc8_\xb9\xbc\u07f8V\x89\xfc\x11\x8f\uf43a8\x80\x00\u07d4\"\x9c\xc4q\x1bbu^\xa2\x96DZ\u00f7\u007f\xc63\x82\x1c\xf2\x89\x02#\xe8\xb0R\x192\x80\x00\u0794\"\x9eC\r\xe2\xb7OD&Q\xdd\u0377\x01v\xbc\x05L\xadT\x88\xbb\xf9\x81\xbcJ\xaa\x80\x00\u07d4\"\x9fO\x1a*OT\atP[G\a\xa8\x1d\xe4D\x10%[\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\"\x9f\xf8\v\xf5p\x80\t\xa9\xf79\xe0\xf8\xb5`\x91@\x16\u0566\x89\x12\x11\xec\xb5m\x13H\x80\x00\u07d4\"\xa2X\x12\xabV\xdc\xc4#\x17^\xd1\u062d\xac\xce3\xcd\x18\x10\x89dI\xe8NG\xa8\xa8\x00\x00\xe0\x94\"\xb9j\xb2\xca\xd5]\xb1\x00\xb50\x01\xf9\xe4\xdb7\x81\x04\xc8\a\x8a\x02\x1e\x19\xe0\u027a\xb2@\x00\x00\u07d4\"\xbd\xff\xc2@\xa8\x8f\xf7C\x1a\xf3\xbf\xf5\x0e\x14\xda7\xd5\x18>\x8965\u026d\xc5\u07a0\x00\x00\u07d4\"\xce4\x91Y\xee\xb1D\xef\x06\xff&6X\x8a\xefy\xf6(2\x89\n1\x06+\xee\xedp\x00\x00\u07d4\"\xdbU\x9f,<\x14u\xa2\xe6\xff\xe8:YyY\x91\x96\xa7\xfa\x8965\u026d\xc5\u07a0\x00\x00\u07d4\"\xe1QX\xb5\xee>\x86\xeb\x032\xe3\u6a6cl\u0675^\u0349\b\xacr0H\x9e\x80\x00\x00\u07d4\"\xe2H\x8e-\xa2jI\xae\x84\xc0\x1b\xd5K!\xf2\x94x\x91\u0189]\u0212\xaa\x111\xc8\x00\x00\u07d4\"\xe5\x12\x14\x9a\x18\xd3i\xb7<q\xef\xa4>\x86\xc9\xed\xab\xaf\x1d\x89N\xe0.g\x14a\\\x00\x00\u07d4\"\xeb}\xb0\xbaV\xb0\xf8\xb8\x16\u0332\x06\xe6\x15\xd9)\x18[\r\x89\x04])s~\"\xf2\x00\x00\u07d4\"\xee\xd3'\xf8\xeb\x1d\x138\xa3\xcb{\x0f\x8aK\xaaY\a\u0355\x89\x01E]_Hw\b\x80\x00\xe0\x94\"\xf0\x04\u07cd\xe9\xe6\xeb\xf5#\u032c\xe4W\xac\xcb&\xf9r\x81\x8a\x02\x1e\x19\xe0\u027a\xb2@\x00\x00\u0794\"\xf2\xdc\xffZ\u05cc>\xb6\x85\v\\\xb9Q\x12{e\x95\"\u623e -j\x0e\xda\x00\x00\u07d4\"\xf3\xc7y\xddy\x02>\xa9*x\xb6\\\x1a\x17\x80\xf6-\\J\x89j\xcb=\xf2~\x1f\x88\x00\x00\u07d4\"\xfe\x88M\x907)\x1bMR\xe6(Z\xe6\x8d\xea\v\xe9\xff\xb5\x89lk\x93[\x8b\xbd@\x00\x00\u07d4#\x06\u07d3\x1a\x94\rX\xc0\x16e\xfaM\b\x00\x80,\x02\xed\xfe\x8965\u026d\xc5\u07a0\x00\x00\xe0\x94#\t\xd3@\x91D[22Y\v\xd7\x0fO\x10\x02[,\x95\t\x8a\x02\x1e\x19\xe0\u027a\xb2@\x00\x00\u07d4#\x12\x00F\xf6\x83!\x02\xa7R\xa7fVi\x1c\x86>\x17\u5709\x11\xe0\xe4\xf8\xa5\v\xd4\x00\x00\u07d4#\x1a\x15\xac\xc1\x99\u021f\xa9\xcb\"D\x1c\xc7\x030\xbd\xcc\xe6\x17\x89\x1b\x1a\xe4\xd6\xe2\xefP\x00\x00\u07d4#\x1d\x94\x15]\xbc\xfe*\x93\xa3\x19\xb6\x17\x1fc\xb2\v\u04b6\xfa\x89\xcf\x14{\xb9\x06\xe2\xf8\x00\x00\u07d4#(2\xcdYw\xe0\nL0\xd0\x16?.$\xf0\x88\xa6\xcb\t\x89\xa2\xa1]\tQ\x9b\xe0\x00\x00\u07d4#,m\x03\xb5\xb6\xe6q\x1e\xff\xf1\x90\xe4\x9c(\xee\xf3l\x82\xb0\x89Hz\x9a0E9D\x00\x00\xe0\x94#,\xb1\xcdI\x99<\x14J?\x88\xb3a\x1e#5i\xa8k\u058a\x03L`lB\u042c`\x00\x00\u07d4#,\xe7\x82Pb%\xfd\x98`\xa2\xed\xc1Jz0Gsm\xa2\x89\x01\x15\x8eF\t\x13\xd0\x00\x00\u07d4#/R]U\x85\x9b}N`\x8d H\u007f\xaa\xdb\x00)15\x89\xd8\xd7&\xb7\x17z\x80\x00\x00\xe0\x94#4\u0150\u01e4\x87i\x100E\u0176SL\x8a4i\xf4J\x8a\x03\xb1\x99\a=\xf7-\xc0\x00\x00\u07d4#7n\u02bftl\xe53!\xcfB\xc8fI\xb9+g\xb2\xff\x89lk\x93[\x8b\xbd@\x00\x00\u07d4#7\x8fB\x92m\x01\x84\xb7\x93\xb0\xc8'\xa6\xdd>=3O\u0349\x03\t'\xf7L\x9d\xe0\x00\x00\u07d4#8B\xb1\xd0i/\xd1\x11@\xcfZ\u0364\xbf\x960\xba\xe5\xf8\x89lk\x93[\x8b\xbd@\x00\x00\u07d4#9\xe9I(p\xaf\xea%7\xf3\x89\xac/\x83\x83\x02\xa3<\x06\x89lk\x93[\x8b\xbd@\x00\x00\u07d4#;\xdd\xdd]\xa9HR\xf4\xad\xe8\xd2\x12\x88V\x82\xd9\ak\u0189\xd8\xd7&\xb7\x17z\x80\x00\x00\u07d4#OF\xba\xb7?\xe4]1\xbf\x87\xf0\xa1\xe0Fa\x99\xf2\ubb09\x1aJ\xba\"\\ t\x00\x00\u07d4#U\x1fV\x97_\xe9+1\xfaF\x9cI\xeaf\xeefb\xf4\x1e\x89g\x8a\x93 b\xe4\x18\x00\x00\u07d4#V\x95B\xc9}V`\x18\xc9\a\xac\xfc\xf3\x91\xd1@g\xe8~\x89lk\x93[\x8b\xbd@\x00\x00\xe0\x94#_\xa6l\x02^\xf5T\x00p\xeb\xcf\r7-\x81w\xc4g\xab\x8a\a\x12\x9e\x1c\xdf7>\xe0\x00\x00\xe0\x94#r\xc4\xc1\u0253\x9fz\xafl\xfa\xc0@\x90\xf0\x04t\x84\n\t\x8a\x02\x1e\x19\xe0\u027a\xb2@\x00\x00\u07d4#s\f5z\x91\x02nD\xb1\xd0\xe2\xfc*Q\xd0q\xd8\xd7{\x89\xd8\xd7&\xb7\x17z\x80\x00\x00\u07d4#v\xad\xa9\x033\xb1\u0441\bL\x97\xe6E\xe8\x10\xaa[v\xf1\x89(\xa8WBTf\xf8\x00\x00\u07d4#x\xfdC\x82Q\x1e\x96\x8e\u0452\x10g7\xd3$\xf4T\xb55\x8965\u026d\xc5\u07a0\x00\x00\u07d4#\x82\xa9\u050e\xc8>\xa3e(\x90\xfd\x0e\u7710{[-\xc1\x89\a?u\u0460\x85\xba\x00\x00\u07d4#\x83\xc2\"\xe6~\x96\x91\x90\xd3!\x9e\xf1M\xa3xP\xe2lU\x89lk\x93[\x8b\xbd@\x00\x00\u07d4#\x8akv5%/RDHl\n\xf0\xa7: s\x85\xe09\x89JD\x91\xbdm\xcd(\x00\x00\u07d4#\x9as>k\x85Z\u0152\xd6c\x15a\x86\xa8\xa1t\xd2D\x9e\x89X\xbe7X\xb2A\xf6\x00\x00\xe0\x94#\xab\t\xe7?\x87\xaa\x0f;\xe0\x13\x9d\xf0\xc8\xebk\xe5cO\x95\x8a\x01\xb1\xaeMn.\xf5\x00\x00\x00\xe0\x94#\xab\xd9\xe9>yW\xe5\xb66\xbeey\x05\x1c\x15\xe5\xce\v\x0e\x8a\x03\xa3\xc8\xf7\xcb\xf4,8\x00\x00\u07d4#\xb1\u0111\u007f\xbd\x93\xee=H8\x93\x06\x95s\x84\xa5Il\xbf\x89\xd8\xd8X?\xa2\xd5/\x00\x00\xe0\x94#\xba8d\xdaX=\xabV\xf4 \x87<7g\x96\x90\xe0/\x00\x8a\x02\x13BR\r_\xec \x00\x00\u07d4#\xc5Z\xebW9\x87o\n\xc8\xd7\xeb\xea\x13\xber\x96\x85\xf0\x00\x89Hz\x9a0E9D\x00\x00\u07d4#\u025b\xa0\x87D\x8e\x19\xc9p\x1d\xf6n\f\xabR6\x831\xfa\x89lk\x93[\x8b\xbd@\x00\x00\u07d4#\xcc\xc3\u01ac\xd8\\.F\fO\xfd\xd8+\xc7]\xc8I\xea\x14\x89\xd8\xd7&\xb7\x17z\x80\x00\x00\u07d4#\xcd%\x98\xa2\x0e\x14\x9e\xad*\u0593yWn\xce\xdb`\u3389lk\x93[\x8b\xbd@\x00\x00\u07d4#\u07cfH\xee\x00\x92V\xeay~\x1f\xa3i\xbe\xeb\xcfk\xc6c\x89|\xd3\xfa\xc2m\x19\x81\x80\x00\u07d4#\xe2\u01a8\xbe\x8e\n\u03e5\xc4\xdf^6\x05\x8b\xb7\u02ecZ\x81\x89lk\x93[\x8b\xbd@\x00\x00\u07d4#\xeaf\x9e5d\x81\x9a\x83\xb0\xc2l\x00\xa1m\x9e\x82olF\x89M\x8dl\xa9h\xca\x13\x00\x00\u07d4#\xebo\xd8Vq\xa9\x06:\xb7g\x8e\xbe&Z \xf6\x1a\x02\xb3\x89lk\x93[\x8b\xbd@\x00\x00\u07d4#\xf9\xec\xf3\xe5\xdd\u0723\x88\x15\xd3\xe5\x9e\xd3K[\x90\xb4\xa3S\x89\v\x17\x81\xa3\xf0\xbb \x00\x00\u07d4#\xfa~\xb5\x1aH\"\x95\x98\xf9~v+\xe0\x86\x96R\xdf\xfcf\x8965\u026d\xc5\u07a0\x00\x00\xe0\x94$\x03\x05rs\x13\xd0\x1esT,w_\xf5\x9d\x11\xcd5\xf8\x19\x8a\x01A\x88Vf\x80\u007f\\\x80\x00\u07d4$\x04k\x91\u069ba\xb6)\u02cb\x8e\xc0\xc3Q\xa0~\a\x03\xe4\x89lk\x93[\x8b\xbd@\x00\x00\u07d4$\x0eU\x9e'J\xae\xf0\xc2X\x99\x8c\x97\x9fg\x1d\x11s\xb8\x8b\x89\xd8\xd7&\xb7\x17z\x80\x00\x00\xe0\x94$\x13aU\x9f\xee\xf8\x0e\xf170!S\xbd\x9e\xd2\xf2]\xb3\xef\x8a\x04<3\xc1\x93ud\x80\x00\x00\xe0\x94$;;\xcaj)\x93Y\xe8\x86\xce3\xa3\x03A\xfa\xfeMW=\x8a\x04<3\xc1\x93ud\x80\x00\x00\u07d4$<\x84\xd1$ W\f\xc4\xef;\xab\xa1\xc9Y\u0083$\x95 \x89\u007f\x1fi\x93\xa8S\x04\x00\x00\xe0\x94$CJ>2\xe5N\xcf'/\xe3G\v_oQ/gU \x8a\x01@a\xb9\xd7z^\x98\x00\x00\u07d4$HYo\x91\xc0\x9b\xaa0\xbc\x96\x10j-7\xb5p^](\x89lk\x93[\x8b\xbd@\x00\x00\u0794$Xn\xc5E\x175\xee\xaa\xebG\r\xc8sj\xaeu/\x82\xe5\x88\xf4?\xc2\xc0N\xe0\x00\x00\u07d4$X\xd6U_\xf9\x8a\x12\x9c\xce@7\x95=\x00 n\xffB\x87\x89\n\xad\xec\x98?\xcf\xf4\x00\x00\u07d4$b\x91\x16[Y3-\xf5\xf1\x8c\xe5\u0248V\xfa\xe9X\x97\u0589\\(=A\x03\x94\x10\x00\x00\u07d4$g\u01a5\u0196\xed\xe9\xa1\xe5B\xbf\x1a\xd0k\xccK\x06\xac\xa0\x89\x01\x00\xbd3\xfb\x98\xba\x00\x00\u07d4$v\xb2\xbbu\x1c\xe7H\xe1\xa4\xc4\xff{#\v\xe0\xc1]\"E\x89\xd8\xd7&\xb7\x17z\x80\x00\x00\u07d4$z\n\x11\xc5\u007f\x03\x83\xb9I\xdeT\vf\xde\xe6\x86\x04\xb0\xa1\x899\xfb\xae\x8d\x04-\xd0\x00\x00\u07d4$\x87\xc3\u013e\x86\xa2r=\x91|\x06\xb4XU\x01p\xc3\xed\xba\x8965\u026d\xc5\u07a0\x00\x00\u07d4$\x89\xac\x12i4\xd4\u05a9M\xf0\x87C\xda{v\x91\xe9y\x8e\x8965\u026d\xc5\u07a0\x00\x00\u07d4$\x9d\xb2\x9d\xbc\x19\xd1#]\xa7)\x8a\x04\b\x1c1WB\u9b09a\xac\xff\x81\xa7\x8a\xd4\x00\x00\u07d4$\xa4\xeb6\xa7\xe4\x98\xc3o\x99\x97\\\x1a\x8dr\x9f\u05b3\x05\u05c9\r\xfcx!\x0e\xb2\xc8\x00\x00\u07d4$\xa7P\xea\xe5\x87G\x11\x11m\xd7\xd4{q\x86\u0399\r1\x03\x89\n\u05ce\xbcZ\xc6 \x00\x00\u07d4$\xaa\x11Q\xbbv_\xa3\xa8\x9c\xa5\x0e\xb6\xe1\xb1\xc7\x06A\u007f\u0509\xa8\r$g~\xfe\xf0\x00\x00\u0794$\xac\xa0\x8d[\xe8^\xbb\x9f12\xdf\xc1\xb6 \x82N\xdf\xed\xf9\x88\xfc\x93c\x92\x80\x1c\x00\x00\u07d4$\xb2\xbe\x11\x8b\x16\u0632\x17Gi\xd1{L\xf8O\a\u0294m\x89lk\x93[\x8b\xbd@\x00\x00\u07d4$\xb8\xb4F\u07bd\x19G\x95]\u0404\xf2\xc5D\x933F\u04ed\x89\xeaim\x90@9\xbd\x80\x00\u07d4$\xb9^\xbe\xf7\x95\x00\xba\xa0\xed\xa7.w\xf8wA]\xf7\\3\x891T\xc9r\x9d\x05x\x00\x00\u07d4$\xb9\xe6dOk\xa4\xcd\xe1&'\r\x81\xf6\xab`\xf2\x86\xdf\xf4\x89\a?u\u0460\x85\xba\x00\x00\u07d4$\xbdY\x04\x05\x90\x91\xd2\xf9\xe1-j&\xa0\x10\xca\"\xab\x14\xe8\x89e\xea=\xb7UF`\x00\x00\u07d4$\xc0\u020bT\xa3TG\t\x82\x8a\xb4\xab\x06\x84\x05Y\xf6\xc5\u2250\xf54`\x8ar\x88\x00\x00\u07d4$\xc1\x17\xd1\u04b3\xa9z\xb1\x1aFy\u025awJ\x9e\xad\xe8\u044965\u026d\xc5\u07a0\x00\x00\u07d4$\xcf\xf0\xe93j\x9f\x80\xf9\xb1\u02d6\x8c\xafk\x1d\x1cI2\xa4\x89\n\xdaUGK\x814\x00\x00\u07d4$\u06aa\xdd\xf7\xb0k\xbc\ua6c0Y\x00\x85\xa8\x85gh+N\x89\x11K \x15\u04bb\xd0\x00\x00\u07d4$\xdc\xc2K\xd9\xc7!\f\xea\u03f3\r\xa9\x8a\xe0JM{\x8a\xb9\x8965\u026d\xc5\u07a0\x00\x00\u07d4$\xf7E\r\xdb\xf1\x8b\x02\x0f\xeb\x1a 2\xd9\xd5Kc>\xdf7\x89\x02\xb5\xe3\xaf\x16\xb1\x88\x00\x00\u07d4$\xfcs\xd2\a\x93\t\x8e\t\u076bW\x98Pb$\xfa\x1e\x18P\x89\n\u05ce\xbcZ\xc6 \x00\x00\u07d4$\xfd\x9al\x87L/\xab?\xf3n\x9a\xfb\xf8\xce\r2\xc7\u0792\x89Hz\x9a0E9D\x00\x00\u07d4%\n@\xce\xf3 #\x97\xf2@F\x95H\xbe\xb5bj\xf4\xf2<\x89\x05\x03\xb2\x03\xe9\xfb\xa2\x00\x00\u07d4%\niC\av\xf64w\x03\xf9R\x97\x83\x95Za\x97\xb6\x82\x89i*\xe8\x89p\x81\xd0\x00\x00\u07d4%\x0e\xb7\xc6o\x86\x9d\xdfI\u0685\xf39>\x98\f\x02\x9a\xa44\x89\xd8\xd7&\xb7\x17z\x80\x00\x00\u07d4%\x10j\xb6u]\xf8mkc\xa1\x87p;\f\xfe\xa0\u5520\x89\x01|@Z\xd4\x1d\xb4\x00\x00\xe0\x94%\x18_2Z\xcf-dP\x06\x98\xf6\\v\x9d\xdfh0\x16\x02\x8a\x01\x0f\f\xf0d\xddY \x00\x00\u07d4%\x1c\x12r,hy\"y\x92\xa3\x04\xeb5v\xcd\x18CN\xa5\x89lk\x93[\x8b\xbd@\x00\x00\u07d4%\x1eh8\xf7\xce\u0173\x83\xc1\xd9\x01F4\x12t\xda\xf8\xe5\x02\x89\a\xff\x1c\xcbua\xdf\x00\x00\u07d4%%\x9d\x97Z!\xd8:\xe3\x0e3\xf8\x00\xf5?7\u07e0\x198\x89\x01\x15\x8eF\t\x13\xd0\x00\x00\u07d4%({\x81_\\\x828\ns\xb0\xb1?\xba\xf9\x82\xbe$\xc4\u04c9\x02+\x1c\x8c\x12'\xa0\x00\x00\xe0\x94%+eU\xaf\u0700\xf2\xd9m\x97-\x17\u06c4\xeaZ\xd5!\xac\x8a\x01\xab,\xf7\xc9\xf8~ \x00\x00\u07d4%8S)6\x81<\x91\xe6S(O\x01|\x80\u00f8\xf8\xa3o\x89l\x87T\xc8\xf3\f\b\x00\x00\xe0\x94%>2\xb7N\xa4I\n\xb9&\x06\xfd\xa0\xaa%{\xf2=\u02cb\x8a\x02\x1e\x19\xe0\u027a\xb2@\x00\x00\xe0\x94%?\x1et*,\uc1b0\u05f3\x06\xe5\xea\xcbl\xcb/\x85T\x8a\x04>^\xde\x1f\x87\x8c \x00\x00\u07d4%A1J\v@\x8e\x95\xa6\x94DIwq*Pq5\x91\xab\x89X\x9e\x1a]\xf4\u05f5\x00\x00\u07d4%L\x1e\xccc\f(w\u0780\x95\xf0\xa8\u06e1\xe8\xbf\x1fU\f\x89\\(=A\x03\x94\x10\x00\x00\u07d4%Z\xbc\x8d\b\xa0\x96\xa8\x8f=j\xb5_\xbcsR\xbd\u0739\u0389\x04t6\x821>\u0780\x00\u07d4%[\xdddt\u0302b\xf2j\"\u00cfE\x94\x0e\x1c\ue99b\x89\xd8\xd7&\xb7\x17z\x80\x00\x00\u07d4%`\xb0\x9b\x89\xa4\xaehI\xedZ<\x99XBf1qDf\x89\\(=A\x03\x94\x10\x00\x00\u07d4%a\xa18\xdc\xf8;\xd8\x13\xe0\xe7\xf1\bd+\xe3\xde=o\x05\x8964\xf4\x84\x17@\x1a\x00\x00\u0794%a\xec\x0f7\x92\x18\xfe^\xd4\xe0(\xa3\xf7D\xaaAuLr\x88\xb9\x8b\xc8)\xa6\xf9\x00\x00\u0794%b\x92\xa1\x91\xbd\xda4\xc4\xdakk\u0591G\xbfu\u2a6b\x88\xc2\xff.\r\xfb\x03\x80\x00\u07d4%i~\xf2\f\u032ap\xd3-7o\x82r\xd9\xc1\a\f=x\x89\n\u05ce\xbcZ\xc6 \x00\x00\u07d4%o\xa1P\u0307\xb5\x05j\a\xd0\x04\xef\xc8E$s\x9eb\xb5\x89\n\u05ce\xbcZ\xc6 \x00\x00\u07d4%r\x1c\x87\xb0\xdc!7|r\x00\xe5$\xb1J\"\xf0\xafi\xfb\x89\xd8\xd7&\xb7\x17z\x80\x00\x00\u07d4%\x899\xbb\xf0\f\x9d\xe9\xafS8\xf5\xd7\x14\xab\xf6\xd0\xc1\xc6q\x89T\x06\x923\xbf\u007fx\x00\x00\xe0\x94%\x90\x12hp\xe0\xbd\xe8\xa6c\xab\x04\nr\xa5W=\x8dA\u008a\x01\x0f\f\xf0d\xddY \x00\x00\u07d4%\x9e\xc4\xd2e\xf3\xabSk|p\xfa\x97\xac\xa1Bi,\x13\xfc\x89\x01\x1b\x1b[\xea\x89\xf8\x00\x00\xe0\x94%\xa5\x00\xee\xeczf*\x84\x15R\xb5\x16\x8bp{\r\xe2\x1e\x9e\x8a\x02\x1f/o\x0f\xc3\xc6\x10\x00\x00\xe0\x94%\xa5\xa4M8\xa2\xf4Lj\x9d\xb9\u037ck\x1e.\x97\xab\xb5\t\x8a\x03\x99\x92d\x8a#\u0220\x00\x00\u07d4%\xa7L*\xc7]\u023a\xa8\xb3\x1a\x9c|\xb4\xb7\x82\x9b$V\u0689lk\x93[\x8b\xbd@\x00\x00\xe0\x94%\xad\xb8\xf9o9I,\x9b\xb4|^\u0708bNF\aV\x97\x8a\x05\xa9\x94\v\xc5hyP\x00\x00\u07d4%\xae\xe6\x8d\t\xaf\xb7\x1d\x88\x17\xf3\xf1\x84\xecV/x\x97\xb74\x89lk\x93[\x8b\xbd@\x00\x00\u07d4%\xb0S;\x81\xd0*a{\x92)\xc7\xec]o/g.[Z\x8965\u026d\xc5\u07a0\x00\x00\u07d4%\xb7\x8c\x9f\xad\x85\xb43C\xf0\xbf\xcd\x0f\xac\x11\u0254\x9c\xa5\xeb\x89lk\x93[\x8b\xbd@\x00\x00\u07d4%\xbcI\xef(\x8c\xd1e\xe5%\xc6a\xa8\x12\u03c4\xfb\xec\x8f3\x89\x12Y!\xae\xbd\xa9\xd0\x00\x00\u07d4%\xbd\xfa>\xe2o8Ia{#\x00bX\x8a\x97\xe3\xca\xe7\x01\x8965\xe6\x19\xbb\x04\xd4\x00\x00\u07d4%\xc1\xa3~\xe5\xf0\x82e\xa1\xe1\r=\x90\xd5G)U\xf9x\x06\x89b\xa9\x92\xe5:\n\xf0\x00\x00\u07d4%\xc6\xe7O\xf1\xd9(\u07d8\x13z\xf4\u07c40\xdf$\xf0|\u05c9\x15$VU\xb1\x02X\x00\x00\xe0\x94%\xcf\xc4\xe2\\5\xc1;i\xf7\xe7}\xbf\xb0\x8b\xafXuk\x8d\x8a\bxg\x83&\xea\xc9\x00\x00\x00\xe0\x94%\xda\u0515\xa1\x1a\x86\xb9\xee\xec\xe1\xee\xec\x80^W\xf1W\xfa\xff\x8a\x03c\\\x9a\xdc]\xea\x00\x00\x00\xe0\x94%\xe07\xf0\n\x18'\v\xa5\xec4 \"\x9d\xdb\n,\u33e2\x8a\x02\x1e\x19\xe0\u027a\xb2@\x00\x00\u07d4%\xe6a\xc99\x86:\xcc\x04No\x17\xb5i\x8c\xce7\x9e\xc3\u0309JD\x91\xbdm\xcd(\x00\x00\u07d4&\x04\x8f\xe8M\x9b\x01\nb\xe71b~I\xbc.\xb7?@\x8f\x89\xd8\xd7&\xb7\x17z\x80\x00\x00\u07d4&\x06\u00f3\xb4\xca\x1b\t\x14\x98`,\xb1\x97\x8b\xf3\xb9R!\xc0\x89\x15\xaf\x1dx\xb5\x8c@\x00\x00\u07d4&\n#\x0eDe\a~\v\x14\xeeDB\xa4\x82\u0570\xc9\x14\xbf\x89Z\xf6\x06\xa0k[\x11\x80\x00\u07d4&\r\xf8\x94:\x8c\x9a]\xbayE2\u007f\xd7\xe0\x83|\x11\xad\a\x89\n\u05ce\xbcZ\xc6 \x00\x00\u07d4&\x14\xf4-]\xa8D7ux\xe6\xb4H\xdc$0[\xef+\x03\x89lk\x93[\x8b\xbd@\x00\x00\u07d4&\x15\x10\x0e\xa7\xe2[\xba\x9b\xcat`X\xaf\xbb\xb4\xff\xbeBD\x89\x1b\x1a\xe4\xd6\xe2\xefP\x00\x00\u07d4&\x15u\xe9\xcfY\xc8\"o\xa7\xaa\xf9\x1d\xe8o\xb7\x0fZ\u00ee\x89\x10C\xa4CjR?\x00\x00\xe0\x94&\x1e\x0f\xa6LQ\x13te\xee\xcf[\x90\xf1\x97\xf7\x93\u007f\xdb\x05\x8a\x03\xcf\xc8.7\xe9\xa7@\x00\x00\u07d4&*\x8b\xfd}\x9d\xc5\xdd:\u05c1a\xb6\xbbV\b$76U\x89?j\x83\x84\a+v\x00\x00\xe0\x94&*\xedK\xc0\xf4\xa4\xb2\xc6\xfb5y>\x83ZI\x18\x9c\xdf\xec\x8a\x02\x1e\x19\xe0\u027a\xb2@\x00\x00\xe0\x94&-\xc16L\xcfm\xf8\\C&\x8e\xe1\x82UM\xaei.)\x8a\x01\v /\xect\xce\xd8\x00\x00\u07d4&8\x140\x9d\xe4\xe65\xcfX^\r6Tw\xfc@\xe6l\xf7\x89\a\xea(2uw\b\x00\x00\u07d4&9\xee\xe9\x87<\xee\xc2o\u0314T\xb5H\xb9\xe7\xc5J\xa6\\\x8965\u026d\xc5\u07a0\x00\x00\xe0\x94&>W\xda\xcb\xe0\x14\x9f\x82\xfee\xa2fH\x98\x86o\xf5\xb4c\x8a\b\v\xfb\xef\xcb_\v\xc0\x00\x00\u07d4&GT\x19\xc0m_\x14z\xa5\x97$\x8e\xb4l\xf7\xbe\xfad\xa5\x89X\xe7\x92n\xe8X\xa0\x00\x00\u07d4&L\xc8\bj\x87\x10\xf9\x1b!r\t\x05\x91,\u05d6J\xe8h\x89\x01s\x17\x90SM\xf2\x00\x00\xe0\x94&S\x83\u058bR\xd04\x16\x1b\xfa\xb0\x1a\xe1\xb0G\x94/\xbc2\x8a\x04rq\xde\xe2\rt\\\x00\x00\u07d4&Y\xfa\xcb\x1e\x83CeS\xb5\xb4)\x89\xad\xb8\a_\x99S\xed\x89\x01\x97evw\x1a^\x00\x00\xe0\x94&o-\xa7\xf0\b^\xf3\xf3\xfa\t\xba\xee#+\x93\xc7D\xdb.\x8a\f\xb4\x9bD\xba`-\x80\x00\x00\u07d4&qH\xfdr\xc5Ob\nY/\xb9'\x991\x9c\xc4S+\\\x89\x169\u46fa\x16(\x00\x00\xe0\x94&xJ\u0791\u0228:\x8e9e\x8c\x8d\x82wA<\u0319T\x8a\x01EB\xba\x12\xa37\xc0\x00\x00\u07d4&z~n\x82\xe1\xb9\x1dQ\xde\u0776D\xf0\xe9m\xbb\x1f\u007f~\x89\x01\x15\x8eF\t\x13\xd0\x00\x00\u07d4&\x80q=@\x80\x8e*P\xed\x011P\xa2\xa6\x94\xb9j\u007f\x1d\x89a\t=|,m8\x00\x00\u07d4&\x97\xb39\x81;\f-\x96K$q\xeb\x1c`oN\u02d6\x16\x89>\x8e\xf7\x95\u0610\xc8\x00\x00\u07d4&\xa6\x8e\xab\x90Z\x8b=\xce\x00\xe3\x170\x82%\u06b1\xb9\xf6\xb8\x89kV\x05\x15\x82\xa9p\x00\x00\u07d4&\xb1\x1d\x06e\x88\xcet\xa5r\xa8Zc(s\x92\x12\xaa\x8b@\x89lk\x93[\x8b\xbd@\x00\x00\u07d4&\xba\xbfB\xb2g\xfd\xcf8a\xfd\xd4#j^GHH\xb3X\x8965\u026d\xc5\u07a0\x00\x00\u07d4&\xc0\x05Kp\r:|-\xcb\xe2uh\x9dOL\xad\x16\xa35\x89lk\x93[\x8b\xbd@\x00\x00\u07d4&\xc2\xff\xc3\x0e\xfd\xc5'>v\x18:\x16\xc2i\x8dnS\x12\x86\x89*\x11)\u0413g \x00\x00\u07d4&\u025f\x88I\u0240+\x83\xc8a!\u007f\xd0z\x9e\x84\u0377\x9d\x89\x10CV\x1a\x88)0\x00\x00\u07d4&\xcf\xff\xd0R\x15+\xb3\xf9W\xb4x\xd5\xf9\x8b#:|+\x92\x89\xd8\xd7&\xb7\x17z\x80\x00\x00\u07d4&\u0521h\x91\xf5)\"x\x92\x17\xfc\u0606\xf7\xfc\xe2\x96\xd4\x00\x89lk\x93[\x8b\xbd@\x00\x00\u07d4&\xd4\xec\x17\xd5\u03b2\u0214\xbd\u015d\nji]\xad+C\u0309\x9f\x1fxv\x1d4\x1a\x00\x00\u07d4&\xe8\x01\xb6,\x82q\x91\xddh\xd3\x1a\x01\x19\x90\x94\u007f\xd0\xeb\xe0\x89\x01\x15\x8eF\t\x13\xd0\x00\x00\u07d4&\xe9\xe2\xadr\x97\x02bd\x17\xef%\xde\r\xc8\x00\xf7\xa7y\xb3\x8965\u026d\xc5\u07a0\x00\x00\u07d4&\xf9\xf7\xce\xfd~9K\x9d9$A+\xf2\u0083\x1f\xaf\x1f\x85\x89\xd8\xd7&\xb7\x17z\x80\x00\x00\xe0\x94&\xfe\x17L\xbfRfP\xe0\xcd\x00\x9b\xd6\x12e\x02\u038ehM\x8a\x02w\x01s8\xa3\n\xe0\x00\x00\xe0\x94&\xff\nQ\xe7\xce\u0384\x00'ix\xdb\xd6#n\xf1b\xc0\xe6\x8a\x15.\x18V'T\nP\x00\x00\u07d4'\x10\x1a\x0fV\u04da\x88\u0168O\x9b2L\xdd\xe3>\\\xb6\x8c\x89lk\x93[\x8b\xbd@\x00\x00\u07d4'\x14L\xa9\xa7w\x1a\x83j\xd5\x0f\x80?d\xd8i\xb2\xae+ \x89\xd8\xd7&\xb7\x17z\x80\x00\x00\u07d4'\x14i\x13V:\xa7E\xe2X\x840\xd94\x8e\x86\xea|5\x10\x89\x15\xaf\x1dx\xb5\x8c@\x00\x00\u07d4'\x1d=H\x1c\xb8\x8evq\xad!iI\xb66^\x060=\xe0\x89\xd8\xd7&\xb7\x17z\x80\x00\x00\u07d4' \xf9\xcaBn\xf2\xf2\xcb\xd2\xfe\xcd9\x92\fO\x1a\x89\xe1m\x89lk\x93[\x8b\xbd@\x00\x00\u07d4'*\x13\x1aZejz:\xca5\u023d \"\"\xa7Y\"X\x89\x90\xf54`\x8ar\x88\x00\x00\u07d4'D\xffgFA!\xe3Z\xfc)\"\x17qd\xfa/\xcb\x02g\x89\x05k\xc7^-c\x10\x00\x00\u07d4'J=w\x1a=p\x97\x96\xfb\xc4\xd5\xf4\x8f\xce/\xe3\x8cy\u0589\x01\x15\x8eF\t\x13\xd0\x00\x00\u07d4'Mi\x17\x0f\xe7\x14\x14\x01\x88+\x88j\xc4a\x8cj\xe4\x0e\u06c93\xc5I\x901r\f\x00\x00\u07d4'R\x1d\xeb;n\xf1An\xa4\u01c1\xa2\xe5\u05f3n\xe8\x1ca\x89lk\x93[\x8b\xbd@\x00\x00\u07d4'Xu\xffO\xbb\f\xf3\xa40!1'H\u007fv\b\xd0L\xba\x89\x1b\x1c\x01\x0evmX\x00\x00\u07d4'j\x00n0(\xec\xd4L\xdbb\xba\nw\u0394\xeb\xd9\xf1\x0f\x89a\x94\x04\x9f0\xf7 \x00\x00\u07d4'k\x05!\xb0\xe6\x8b'}\xf0\xbb2\xf3\xfdH2cP\xbf\xb2\x89\x02\xb5\xe3\xaf\x16\xb1\x88\x00\x00\u07d4'o\xd7\xd2O\x8f\x88?Zz()[\xf1qQ\u01e8K\x03\x89lk\x93[\x8b\xbd@\x00\x00\u07d4'p\xf1N\xfb\x16]\u07bay\xc1\v\xb0\xaf1\xc3\x1eY3L\x89\xa2\xa1]\tQ\x9b\xe0\x00\x00\u07d4'vw\xab\xa1\xe5,;S\xbf\xa2\a\x1dN\x85\x9a\n\xf7\xe8\xe1\x8965\u026d\xc5\u07a0\x00\x00\u07d4'\x82Ff\xd2x\xd7\x04#\xf0=\xfe\x1d\u01e3\xf0/C\u2d4966\xc2^f\xec\xe7\x00\x00\u07d4'\x83\f_`#\xaf\xaa\xf7\x97Egl J\x0f\xac\u0360\xba\x89\r\x02\xabHl\xed\xc0\x00\x00\xe0\x94'\x84\x90?\x1d|\x1b\\\xd9\x01\xf8\x87]\x14\xa7\x9b<\xbe*V\x8a\x04\xbd\xa7\xe9\xd7J\xd5P\x00\x00\u07d4'\x8c\v\xdec\x0e\u00d3\xb1\xe7&\u007f\xc9\xd7\xd9p\x19\xe4\x14[\x89lk\x93[\x8b\xbd@\x00\x00\u07d4'\x98q\x10\"\x1a\x88\b&\xad\xb2\xe7\xab^\xcax\xc6\xe3\x1a\xec\x89\xd8\xd7&\xb7\x17z\x80\x00\x00\xe0\x94'\xac\a;\xe7\x9c\xe6W\xa9:\xa6\x93\xeeC\xbf\x0f\xa4\x1f\xef\x04\x8a\n\x96\x81c\xf0\xa5{@\x00\x00\u07d4'\xb1iN\xaf\xa1e\xeb\xd7\xcc{\u025et\x81J\x95\x14\x19\u0709+^:\xf1k\x18\x80\x00\x00\u07d4'\xb6(\x16\xe1\xe3\xb8\u045by\xd1Q=]\xfa\x85[\f:*\x89\x05j\xf5\xc1\xfdiP\x80\x00\u07d4'\xbf\x94<\x163\xfe2\xf8\xbc\xcc\xdbc\x02\xb4\a\xa5rND\x892\xf8Lm\xf4\b\xc0\x80\x00\u07d4'\xbf\x9fD\xba}\x05\xc35@\u00e5;\xb0,\xbb\xff\xe7\xc3\u0189lk\x93[\x8b\xbd@\x00\x00\u07d4'\xc2\xd7\xcaPM\xaa=\x90f\xdc\t\x13}\xc4/:\xaa\xb4R\x89 \x86\xac5\x10R`\x00\x00\u07d4'\xd1X\xac=>\x11\t\xabnW\x0e\x90\xe8]8\x92\xcdv\x80\x89\x05k\xc7^-c\x10\x00\x00\u07d4'\xe69\x89\xca\x1e\x90;\xc6 \xcf\x1b\x9c?g\xb9\xe2\xaee\x81\x89Hz\x9a0E9D\x00\x00\xe0\x94'\xf0<\xf1\xab\xc5\xe1\xb5\x1d\xbcDK(\x9eT,\x9d\u07f0\xe6\x8a\x01\x0f\f\xf0d\xddY \x00\x00\u07d4'\xfc\x85\xa4\x9c\xff\x90\xdb\xcf\xda\u071d\xdd@\u05b9\xa2!\nl\x89\x05k\xc7^-c\x10\x00\x00\u07d4(\x05A^\x1d\u007f\xde\xc6\xde\u07f8\x9eR\x1d\x10Y-t<\x10\x89\x05k\xc7^-c\x10\x00\x00\u07d4(\a>\xfc\x17\xd0\\\xab1\x95\xc2\xdb3+a\x98Gw\xa6\x12\x8965\u026d\xc5\u07a0\x00\x00\u07d4(\x12P\xa2\x91!'\nN\xe5\u05cd$\xfe\xaf\xe8,p\xba:\x8965\u026d\xc5\u07a0\x00\x00\u07d4(\x13\xd2c\xfc_\xf2G\x9e\x97\x05\x95\u05b6\xb5`\xf8\xd6\xd6\u0449lk\x93[\x8b\xbd@\x00\x00\u07d4(.\x80\xa5T\x87ZVy\x9f\xa0\xa9\u007fU\x10\u7557LN\x8965\u026d\xc5\u07a0\x00\x00\u07d4(3\x96\xce<\xac9\x8b\xcb\xe7\"\u007f2>x\xff\x96\u0407g\x89\x15\xaf\x1dx\xb5\x8c@\x00\x00\u07d4(4\x9f~\xf9t\xeaU\xfe6\xa1X;4\xce\xc3\xc4Pe\xf0\x89\f\xb63\u051eeY\x00\x00\u07d4(6\x120F\xb2\x84\xe5\xef\x10+\xfd\"\xb1v^P\x81\x16\xad\x89\x16S\xfb\xb5\xc4'\xe4\x00\x00\u07d4(<#\x14(<\x92\u0530d\xf0\xae\xf9\xbbRF\xa7\x00\u007f9\x89\n\u05ce\xbcZ\xc6 \x00\x00\u07d4(>\x11 7I\xb1\xfaO2\xfe\xbbq\xe4\x9d\x13Y\x198*\x8965\u026d\xc5\u07a0\x00\x00\xe0\x94(>bR\xb4\xef\xcfFT9\x1a\xcbu\xf9\x03\u015bx\xc5\xfb\x8a\x02\x8a\x85t%Fo\x80\x00\x00\xe0\x94(Q\x0en\xff\x1f\xc8)\xb6WoC(\xbc98\xecze\x80\x8a\x02\x1e\x19\xe0\u027a\xb2@\x00\x00\u07d4(X\xac\xac\xaf!\xea\x81\u02b7Y\x8f\xdb\xd8kE.\x9e\x8e\x15\x89$\x1a\x9bOaz(\x00\x00\u07d4(Z\xe5\x1b\x95\x00\u014dT\x13e\xd9ui\xf1K\xb2\xa3p\x9b\x89lk\x93[\x8b\xbd@\x00\x00\u07d4(f\xb8\x1d\xec\xb0.\xe7\n\xe2P\xce\xe5\xcd\xc7{Y\u05f6y\x89lk\x93[\x8b\xbd@\x00\x00\u07d4(i\x06\xb6\xbdIr\xe3\xc7\x16U\xe0K\xaf6&\f|\xb1S\x89\x12nr\xa6\x9aP\xd0\x00\x00\u07d4(k\x18ma\xea\x1f\u05cd\x990\xfe\x12\xb0e7\xb0\\=Q\x8965\u026d\xc5\u07a0\x00\x00\xe0\x94(t\xf3\xe2\x98]_{@f'\xe1{\xaaw+\x01\xab\u031e\x8a\x01F\x05\x04\x10v_8\x00\x00\xe0\x94(|\xf9\u0410.\xf8\x19\xa7\xa5\xf1ID[\xf1w^\xe8\xc4|\x8a\x03c\\\x9a\xdc]\xea\x00\x00\x00\u07d4(\x81\x8e\x18\xb6\x10\x00\x13!\xb3\x1d\xf6\xfe}(\x15\u036d\xc9\xf5\x8965\u026d\xc5\u07a0\x00\x00\u07d4(\x86\x83$3~\x11\xba\x10l\xb4\x81\u0696/:\x84S\x80\x8d\x89lk\x93[\x8b\xbd@\x00\x00\xe0\x94(\x90K\xb7\xc40)C\xb7\t\xb1Myp\xe4+\x83$\u184a\x02\x1f\x97\x84j\a-~\x00\x00\u07d4(\x95\xe8\t\x99\xd4\x06\xadY.+&'7\xd3_}\xb4\xb6\x99\x89i*\xe8\x89p\x81\xd0\x00\x00\u07d4(\x96r\x80!N!\x8a\x12\f]\xda7\x04\x1b\x11\x1e\xa3mt\x89\n\u05ce\xbcZ\xc6 \x00\x00\u07d4(\xa3\xda\t\xa8\x19H\x19\xae\x19\x9f.m\x9d\x13\x04\x81~(\xa5\x89lk\x93[\x8b\xbd@\x00\x00\u07d4(\xab\x16_\xfbi\xed\xa0\xc5I\xae8\xe9\x82o_\u007f\x92\xf8S\x89FM\xf6\xd7\xc8DY\x00\x00\u07d4(\xb7u\x85\xcb=U\xa1\x99\xab)\x1d:\x18\u018f\u8684\x8a\x89j@v\xcfy\x95\xa0\x00\x00\xe0\x94(\xd4\xeb\xf4\x1e=<E\x1e\x94;\xdd~\x1f\x17_\xae\x93*=\x8a\x01EB\xba\x12\xa37\xc0\x00\x00\xe0\x94(\xd7\xe5\x86o\x1d\x85\xfd\x1c\xeb2\xbf\xbe\x1d\xfc6\xdbCEf\x8a\x01\x86B1\xc6\x105\x1c\x00\x00\u0794(\xd8\xc3_\xb7\xee\xa6\"X!5\xe3\xadG\xa2'\u0266c\xbd\x88\xfc\x93c\x92\x80\x1c\x00\x00\u07d4(\xe4\xaf0\u0353\xf6\x86\xa1\"\xad{\xb1\x9f\x8a\x87\x85\xee\xe3B\x89q\xe5;pl\u01f4\x00\x00\u07d4(\xea\xeax\xcdM\x95\xfa\xec\xfbh\x83n\xaf\xe85 \U000fbdc9\n\u05ce\xbcZ\xc6 \x00\x00\xe0\x94(\xef\xaecVP\x9e\u07ec\xe8\x9f\xc6\x1a\u007f\xdc\xdb9\xee\xa8\xe5\x8a\x01!\xeah\xc1\x14\xe5\x10\x00\x00\xe0\x94(\xfa%\x80\xf9\xeb\xe4 \xf3\xe5\xee\xfd\xd3qc\x8e;z\xf4\x99\x8a\x01EB\xba\x12\xa37\xc0\x00\x00\u07d4)\x01\xf8\a\u007f4\x19\v\xb4z\x8e\"\u007f\xa2\x9b0\xce\x11;1\x89\x05k\xc7^-c\x10\x00\x00\u07d4)\x05\xb1\x92\xe8<\xe6Y\xaa5[\x9d\f N>\x95\xf9\xbb\x9a\x89u#\\\x1d\x009>\x80\x00\u07d4)\nV\xd4\x1fn\x9e\xfb\xdc\xea\x03B\u0dd2\x9a\x8c\xdf\xcb\x05\x89\x12\xa5\xf5\x81h\xee`\x00\x00\u07d4)\x15bK\xcbg\x917\xb8\xda\xe9\xabW\xd1\x1bI\x05\xea\xeeK\x89\x01\x15\x8eF\t\x13\xd0\x00\x00\u07d4)\x1e\xfe\x00\x81\xdc\xe8\xc1G\x99\xf7\xb2\xa46\x19\xc0\u00f3\xfc\x1f\x89A\rXj \xa4\xc0\x00\x00\u07d4)\x1f\x92\x9c\xa5\x9bT\xf8D>=Mu\xd9]\xee$<\xefx\x89\x1b\x1a\b\x927\a=\x00\x00\xe0\x94))\x8c\xcb\xdf\xf6\x89\xf8\u007f\xe4\x1a\xa6\xe9\x8f\u07f5=\xea\xf3z\x8a\x041\\2\xd7\x1a\x9e`\x00\x00\u07d4)/\"\x8b\n\x94t\x8c\x8e\xeca-$o\x98\x93c\xe0\x8f\b\x89\n\ad\a\xd3\xf7D\x00\x00\u07d4)3\x84\xc4+o\x8f)\x05\xceR\xb7 \\\"t7la+\x89K\xe4\xe7&{j\xe0\x00\x00\u07d4)4\xc0\xdf{\xbc\x17+l\x18k\vrTz\u038b\xf7TT\x89\x03@\xaa\xd2\x1b;p\x00\x00\u07d4)<#\x06\xdf6\x04\xaeO\xda\r z\xbasog\xde\a\x92\x89\n\u05ce\xbcZ\xc6 \x00\x00\xe0\x94)I\xfd\x1d\xef\\v\xa2\x86\xb3\x87$$\x80\x9a\a\xdb9f\xf3\x8a\x01\x1b\xd9\x06\u06a0\xc9C\x80\x00\u07d4)OIK?.\x14</\xfc\x978\xcb\xfd\x95\x01\x85\v\x87N\x89yn>\xa3\xf8\xab\x00\x00\x00\u07d4)U\xc3W\xfd\x8fu\xd5\x15\x9a=\xfai\u0178z5\x9d\ua309lk\x93[\x8b\xbd@\x00\x00\u07d4)a\xfb9\x1ca\x95|\xb5\xc9\xe4\a\u0762\x938\u04f9,\x80\x8964\xfb\x9f\x14\x89\xa7\x00\x00\u07d4)h\x1d\x99\x12\xdd\xd0~\xaa\xbb\x88\xd0]\x90\xf7f\xe8bA}\x8965\u026d\xc5\u07a0\x00\x00\u07d4)kq\xc0\x01X\x19\xc2B\xa7\x86\x1eo\xf7\xed\xed\x8a_q\xe3\x89lh\xcc\u041b\x02,\x00\x00\u07d4)mf\xb5!W\x1aNA\x03\xa7\xf5b\xc5\x11\xe6\xaas-\x81\x89$=M\x18\"\x9c\xa2\x00\x00\u07d4)o\x00\xde\x1d\u00fb\x01\xd4z\x8c\xcd\x1e]\x1d\u0661\xebw\x91\x8965\u026d\xc5\u07a0\x00\x00\u07d4)s\x85\xe8\x864FV\x85\xc21\xa3\x14\xa0\xd5\xdc\xd1F\xaf\x01\x89T\x06\x923\xbf\u007fx\x00\x00\u07d4)v=\xd6\u069a|\x16\x11s\x88\x83!\ub9b6<\x8f\xb8E\x89\x11\xc7\xea\x16.x \x00\x00\u07d4)yt\x11t\xa8\xc1\xea\v\u007f\x9e\xdfe\x81w\x85\x94\x17\xf5\x12\x89\x19\x01\x96l\x84\x96\x83\x80\x00\u07d4)z\x88\x92\x1b_\xca\x10\u5edd\xed`\x02T7\xae\"\x16\x94\x89\n\u05ce\xbcZ\xc6 \x00\x00\xe0\x94)}]\xbe\"//\xb5%1\xac\xbd\v\x01=\xc4F\xacsh\x8a\x04<3\xc1\x93ud\x80\x00\x00\u07d4)\x82N\x94\xccCH\xbc\x962y\xdc\xdfG9\x17\x152L\u04c9i*\xe8\x89p\x81\xd0\x00\x00\u07d4)\x82\xd7j\x15\xf8G\xddA\xf1\x92*\xf3h\xfeg\x8d\x0eh\x1e\x89\x05k\xc7^-c\x10\x00\x00\u07d4)\x88\x87\xba\xb5|[\xa4\xf0aR)\xd7R_\xa1\x13\xb7\ua249\x02+\x1c\x8c\x12'\xa0\x00\x00\xe0\x94)\x8e\xc7kD\r\x88\a\xb3\xf7\x8b_\x90\x97\x9b\xeeB\xedC\u06ca\x06ZM\xa2]0\x16\xc0\x00\x00\u07d4)\x93h`\x90B\xa8X\xd1\xec\xdf\x1f\xc0\xad\xa5\xea\xce\xca)\u03c9lk\x93[\x8b\xbd@\x00\x00\u07d4)\x9e\v\xcaU\xe0i\u0785\x04\xe8\x9a\xcan\xca!\u04ca\x9a]\x89\x03\x027\x9b\xf2\xca.\x00\x00\u07d4)\xac+E\x84T\xa3l~\x96\xc7:\x86g\"*\x12$,q\x89\xd8\xd7&\xb7\x17z\x80\x00\x00\xe0\x94)\xad\u03c3\xb6\xb2\n\u01a44\xab\xb1\x99<\xbd\x05\xc6\x0e\xa2\xe4\x8a\x02\x1e\x19\xe0\u027a\xb2@\x00\x00\xe0\x94)\xae\xf4\x8d\xe8\xc9\xfb\xadK\x9eL\xa9pyzU3\xebr-\x8a\x02\x1e\x19\xe0\u027a\xb2@\x00\x00\u07d4)\xb3\xf5a\xeezn%\x94\x1e\x98\xa52[x\xad\u01d7\x85\xf3\x89\x05k\xc7^-c\x10\x00\x00\u07d4)\xbd\xc4\xf2\x8d\xe0\x18\x0fC<&\x94\xebt\xf5PL\xe9C7\x89lk\x93[\x8b\xbd@\x00\x00\u07d4)\u0300M\x92+\xe9\x1fY\t\xf3H\xb0\xaa\xa5\xd2\x1b`x0\x89\xd8\xd7&\xb7\x17z\x80\x00\x00\xe0\x94)\xda>5\xb2;\xb1\xf7/\x8e\"X\xcf\u007fU3Y\xd2K\xac\x8a\x04<3\xc1\x93ud\x80\x00\x00\xe0\x94)\xe6y\x90\xe1\xb6\xd5.\x10U\xff\xe0I\xc51\x95\xa8\x15B\u03ca\x04<3\xc1\x93ud\x80\x00\x00\u07d4)\uab82v\x17b\xf4\xd2\xdbS\xa9\u018b\x0fk\vmNf\x89lk\x93[\x8b\xbd@\x00\x00\u07d4)\xeb~\xef\xda\xe9\xfe\xb4I\xc6?\xf5\xf2y\xd6u\x10\xeb\x14\"\x89\x01\r:\xa56\xe2\x94\x00\x00\u07d4)\xf0\xed\xc6\x038\xe7\x11 \x85\xa1\xd1\x14\u068cB\u038fU\u0589\xa0Z\u007f\x0f\xd8%x\x00\x00\u07d4)\xf8\xfb\xa4\xc3\ar\xb0W\xed\xbb\xe6*\xe7B\f9\x05r\xe1\x8965\u026d\xc5\u07a0\x00\x00\xe0\x94)\xf9(l\x0es\x8d\x17!\xa6\x91\u01b9Z\xb3\u0667\x97\xed\xe8\x8a*Z\x05\x8f\u0095\xed\x00\x00\x00\u07d4*\b^%\xb6Hb\xf5\xe6\x8dv\x8e+\x0fz\x85)\x85\x8e\xee\x89k\x88:\xcdWf\xcd\x00\x00\u07d4**\xb6\xb7Lz\xf1\xd9Gk\xb5\xbc\xb4RG\x97\xbe\xdc5R\x8965\u026d\xc5\u07a0\x00\x00\u07d4*9\x19\nO\u0783\u07f3\xdd\xcbL_\xbb\x83\xaclIu\\\x8965\u026d\xc5\u07a0\x00\x00\u07d4*@\r\xff\x85\x94\xder(\xb4\xfd\x15\xc3#\"\xb7[\xb8}\xa8\x89\x051\xa1\u007f`z-\x00\x00\xe0\x94*D\xa7!\x8f\xe4Me\xa1\xb4\xb7\xa7\u0671\xc2\xc5,\x8c>4\x8a\r-\x06\xc3\x05\xa1\xebW\x80\x00\u07d4*F\xd3Swqv\xff\x8e\x83\xff\xa8\x00\x1fOp\xf9s:\xa5\x89\x05\xbf\v\xa6cOh\x00\x00\u07d4*Y_\x16\xee\xe4\xcb\f\x17\u0662\xd99\xb3\xc1\x0flgrC\x89;\xa1\x91\v\xf3A\xb0\x00\x00\u07d4*Y\xe4~\xa5\xd8\xf0\xe7\xc0(\xa3\xe8\xe0\x93\xa4\x9c\x1bP\xb9\xa3\x89lk\x93[\x8b\xbd@\x00\x00\u07d4*[\xa9\xe3L\u054d\xa5L\x9a'\x12f:;\xe2t\xc8\xe4{\x89\n\xad\xec\x98?\xcf\xf4\x00\x00\xe0\x94*^:@\xd2\xcd\x03%vm\xe7:=g\x18\x96\xb3b\xc7;\x8a\x15-\x02\xc7\xe1J\xf6\x80\x00\x00\xe0\x94*cY\x0e\xfe\x99\x86\xc3\xfe\xe0\x9b\n\n3\x8b\x15\xbe\xd9\x1f!\x8a\x01^\x1cN\x05\xee&\xd0\x00\x00\u07d4*gf\n\x13h\xef\xcdbn\xf3k+\x1b`\x19\x80\x94\x1c\x05\x89\a?u\u0460\x85\xba\x00\x00\u07d4*t+\x89\x10\x94\x1e\t2\x83\n\x1d\x96\x92\xcf\u0484\x94\xcf@\x89\x1b\x1a\xb3\x19\xf5\xecu\x00\x00\u07d4*tl\xd4@'\xaf>\xbd7\xc3x\xc8^\xf7\xf7T\xab_(\x89\x15[\xd90\u007f\x9f\xe8\x00\x00\u07d4*\x81\xd2|\xb6\xd4w\x0f\xf4\xf3\u0123\xba\x18\xe5\xe5\u007f\aQ|\x89lk\x93[\x8b\xbd@\x00\x00\u07d4*\x91\xa9\xfe\xd4\x1b}\x0e\\\xd2\xd81X\xd3\xe8\xa4\x1a\x9a-q\x89i*\xe8\x89p\x81\xd0\x00\x00\xe0\x94*\x9cW\xfe{k\x13\x8a\x92\rgo<v\xb6\u00a0\xee\xf6\x99\x8a\x01\xfd\x934\x94\xaa_\xe0\x00\x00\u07d4*\x9c\x96\xc1\x91Q\xff\xcb\xe2\x9aF\x16\xd0\xc5+93\xb4e\x9f\x89\x03\xc17\x9b\x87e\xe1\x80\x00\u07d4*\xa1\x92w|\xa5\xb9x\xb6\xb2\xc2\xff\x80\n\xc1\x86\x0fu?G\x89\x12)\x0f\x15\x18\v\xdc\x00\x00\xe0\x94*\xaa5'Mt%Fg\vt&&E!\x03*\xf4\xf4\u00ca\x02\x1e\x19\xe0\u027a\xb2@\x00\x00\u07d4*\xae\xa1\xf1\x04o0\xf1\t\xfa\xec\x1cc\xef\\u\x94\xeb\b\u0689\xd8\xd7&\xb7\x17z\x80\x00\x00\u07d4*\xb9~\x8dY\xee\xe6H\xabl\xaf\x86\x96\xf8\x997\x148d\u0589\xcf\x15&@\xc5\xc80\x00\x00\xe0\x94*\xbc\u1009@\xcdN\xf5\xb5\xe0R\x85\xf8-\xf7\xa9\xab^\x03\x8a\x02\x13BR\r_\xec \x00\x00\xe0\x94*\xbd\xf1\xa67\xeflB\xa7\xe2\xfe!ws\xd6w\xe8\x04\xeb\u074a\x01\x0f\f\xf0d\xddY \x00\x00\u07d4*\xc1\xf8\u05ffr\x1f<\xfet\xd2\x0f\ua6c7\xa2\x8a\xaa\x98,\x89\b\xbaR\xe6\xfcE\xe4\x00\x00\xe0\x94*\u031c\x1a2$\vM[/wz.\xa0R\xb4/\xc1'\x1c\x8a\b\xd8\a\xee\x14\xd86\x10\x00\x00\u07d4*\xd6\xc9\xd1\f&\x18\x19\xa1\xa0\xca,H\xd8\u01f2\xa7\x17(\u07c965\u026d\xc5\u07a0\x00\x00\xe0\x94*\xe58f\xfc-\x14\xd5r\xabs\xb4\xa0e\xa1\x18\x82g\xf5'\x8a\x01\xb1\xaeMn.\xf5\x00\x00\x00\u07d4*\xe7:y\xae\xa0'\x853\xac\xcf!\a\t\"\xb1a?\x8f2\x89\xa7\xe9K\xbe\xaep\x1a\x80\x00\u07d4*\xe8-\xab\x92\xa6c\x89\ue86b\xb9\x01\xd1\xd5\u007fZ|\xca\v\x89lk\x93[\x8b\xbd@\x00\x00\u07d4*\uc01d\xf92[\x9fH9\x96\xe9\x9fs1\t\u007f\b\xaa\x0e\x89\xd8\xd7&\xb7\x17z\x80\x00\x00\xe0\x94*\xed,\xe51\xc0V\xb0\t~\xfc<m\xe1\fGb\x00N\u064a\x025iS\xab}\xdc8\x00\x00\u07d4*\xfb\x05\x8c=1\x03+5;\xf2O\t\xae \xd5M\xe5}\xbe\x89;\xa1\x91\v\xf3A\xb0\x00\x00\xe0\x94+\x03bc6\x14\xbf\xcbX5iC\x8e\xccN\xa5{\x1d3~\x8a\x04<3\xc1\x93ud\x80\x00\x00\u07d4+\x10\x1e\x82,\xd9b\x96*\x06\x80\n,\b\u04f1]\x82\xb75\x89\b=lz\xabc`\x00\x00\u07d4+\x12\x9c&\xb7]\xde\x12\u007f\x83 \xbd\x0fcA\f\x92\xa9\xf8v\x89wC\"\x17\xe6\x83`\x00\x00\xe0\x94+$\x1f\x03s7\xebJ\xcca\x84\x9b\xd2r\xac\x13?|\xdfK\x8aP\vk\u0296*\xb8@\x00\x00\u07d4+:h\xdbk\f\xae\x8a|zGk\xdf\u03fdb\x05\xe1\x06\x87\x89\x82\x1a\xb0\xd4AI\x80\x00\x00\u07d4+<\xf9s\x11\xff0\xf4`\x94Z\x9d\x80\x99\xf4\xa8\x8e&\xd4V\x89lk\x93[\x8b\xbd@\x00\x00\u07d4+I\xfb\xa2\x9806\x0f\u0376\xda#\xbb\xfe\xa5\xc0\xbb\xacR\x81\x89\x01\x15\x8eF\t\x13\xd0\x00\x00\u0794+OE\a\xbbk\x98\x17\x94,\xe43x\x1bp\x8f\xbc\xd1f\xfd\x88\xfc\x93c\x92\x80\x1c\x00\x00\xe0\x94+P\x16\xe2Es\x87\x95ebXq\x15\xaa\x87Y\xd8i_\u07ca*Z\x05\x8f\u0095\xed\x00\x00\x00\xe0\x94+\\`\xe8E5\xee\xb4\u0540\xde\x12z\x12\xeb&w\u0333\x92\x8a\x04<3\xc1\x93ud\x80\x00\x00\u07d4+\\\ud647\xc0v_\x90\x0eI\u03dd\xa2\xd9\xf9\xc1\x13\x88U\x89\x15\xaf\x1dx\xb5\x8c@\x00\x00\xe0\x94+_K?\x1e\x11pz\"z\xa5\u67e4\x9d\xde\xd3?\xb3!\x8a\x01EB\xba\x12\xa37\xc0\x00\x00\u07d4+h0k\xa7\xf8\u06afs\xf4\xc6D\xef}'C\xc0\xf2hV\x89.\xe1\x82\xca\x17\xdd\xd0\x00\x00\xe0\x94+n\u049a\x95u<:\xd9H4\x8e>{\x1a%\x10\x80\xff\xb9\x8a4\xf0\x86\xf3\xb3;h@\x00\x00\u07d4+p\x1d\x16\xc0\xd3\xcc\x1eL\xd8TE\xe6\xad\x02\ue92c\x01-\x89 \x86\xac5\x10R`\x00\x00\xe0\x94+q|\xd42\xa3#\xa4e\x909\x84\x8d;\x87\xde&\xfc\x95F\x8ai\xe1\r\xe7fv\u0400\x00\x00\u07d4+t\xc3s\xd0K\xfb\x0f\xd6\n\x18\xa0\x1a\x88\xfb\xe8Gp\u5309\x02+\x1c\x8c\x12'\xa0\x00\x00\u07d4+w\xa4\u060c\rV\xa3\xdb\xe3\xba\xe0J\x05\xf4\xfc\u0477W\xe1\x89\x10CV\x1a\x88)0\x00\x00\xe0\x94+\x84\x88\xbd-<\x19z=&\x15\x18\x15\xb5\xa7\x98\xd2qh\u070a\x01j\x1f\x9f_\xd7\xd9`\x00\x00\u07d4+\x8a\r\xee\\\xb0\xe1\xe9~\x15\xcf\xcan\x19\xad!\xf9\x95\ufb49\x1bUC\x8d\x9a$\x9b\x00\x00\xe0\x94+\x8f\xe4\x16n#\xd1\x19c\xc0\x93+\x8a\u078e\x01E\xea\ap\x8a\t(\x96R\x9b\xad\u0708\x00\x00\xe0\x94+\x99\xb4.OBa\x9e\xe3k\xaa~J\xf2\xd6^\xac\xfc\xba5\x8a\bxg\x83&\xea\xc9\x00\x00\x00\u07d4+\xab\x0f\xbe(\u0544 \xb5 6w\n\x12\xf9\x95*\xeai\x11\x89\xcf\x15&@\xc5\xc80\x00\x00\u07d4+\xad\xe9\x1d\x15E\x17b\x0f\u05349\xac\x97\x15zA\x02\xa9\xf7\x89\xd8\xd7&\xb7\x17z\x80\x00\x00\u07d4+\xaf\x8dn\"\x11t\x12H \xeeI+\x94Y\xecO\xad\xaf\xbb\x89lk\x93[\x8b\xbd@\x00\x00\u07d4+\xaf\xbf\x9e\x9e\xd2\xc2\x19\xf7\xf2y\x13t\xe7\xd0\\\xb0gw\xe7\x89\v\xed\x1d\x02c\xd9\xf0\x00\x00\xe0\x94+\xb3f\xb9\xed\xcb\r\xa6\x80\xf0\xe1\v;n(t\x81\x90\xd6\u00ca\x01:b\u05f5v@d\x00\x00\xe0\x94+\xb6\xf5x\xad\xfb\u7ca1\x16\xb3UO\xac\xf9\x96\x98\x13\xc3\x19\x8a\x01\x91'\xa19\x1e\xa2\xa0\x00\x00\u07d4+\xbeb\xea\xc8\f\xa7\xf4\xd6\xfd\xee~}\x8e(\xb6:\xcfw\x0e\x89\x81\xe3-\xf9r\xab\xf0\x00\x00\u07d4+\xbeg*\x18WP\x8fc\x0f*^\xdbV=\x9e\x9d\xe9(\x15\x89lk\x93[\x8b\xbd@\x00\x00\u07d4+\xc4)\xd6\x18\xa6jL\xf8-\xbb-\x82N\x93V\xef\xfa\x12j\x89lj\xccg\u05f1\xd4\x00\x00\u07d4+\xd2R\xe0\xd72\xff\x1d|x\xf0\xa0.l\xb2T#\xcf\x1b\x1a\x89\x90\xf54`\x8ar\x88\x00\x00\u07d4+\xdd\x03\xbe\xbb\xee';l\xa1\x05\x9b4\x99\x9a[\xbda\xbby\x89\x01\x15\x8eF\t\x13\xd0\x00\x00\u07d4,\x04\x11\\>R\x96\x1b\r\xc0\xb0\xbf1\xfb\xa4ToYf\xfd\x89\n\u05ce\xbcZ\xc6 \x00\x00\xe0\x94,\x06\u0752+aQJ\xaf\xed\xd8D\x88\xc0\u008em\xcf\x0e\x99\x8a\x15-\x02\xc7\xe1J\xf6\x80\x00\x00\xe0\x94,\f\xc3\xf9QH,\u0222\x92X\x15hN\xb9\xf9N\x06\x02\x00\x8a\x01EB\xba\x12\xa37\xc0\x00\x00\u07d4,\x0e\xe14\u0633aE\xb4{\xee\u7bcd'8\xdb\xda\b\xe8\x89\n\xe5os\x0em\x84\x00\x00\u07d4,\x0f[\x9d\xf46%y\x8e~\x03\xc1\xa5\xfdjm\t\x1a\xf8+\x89\x01\xb0\xfc\xaa\xb2\x000\x00\x00\u07d4,\x12\x8c\x95\xd9W!Q\x01\xf0C\u074f\u0142EmA\x01m\x89-C\xf3\xeb\xfa\xfb,\x00\x00\u07d4,\x18\x00\xf3_\xa0->\xb6\xff[%(_^J\xdd\x13\xb3\x8d\x891\"\u04ed\xaf\xde\x10\x00\x00\u07d4,\x1c\x19\x11N=m\xe2xQHK\x8d'\x15\xe5\x0f\x8a\x10e\x89\x05k\xc7^-c\x10\x00\x00\u07d4,\x1c\xc6\xe1\x8c\x15$\x88\xba\x11\xc2\xcc\x1b\xce\xfa-\xf3\x06\xab\u0449Z\x87\xe7\xd7\xf5\xf6X\x00\x00\xe0\x94,\x1d\xf8\xa7oH\xf6\xb5K\u03dc\xafV\xf0\xee\x1c\xf5z\xb3=\x8a\x02$\u007fu\x00\x89\xdaX\x00\x00\u07d4,!G\x94z\xe3?\xb0\x98\xb4\x89\xa5\xc1k\xff\xf9\xab\xcdN*\x89\n\u05ce\xbcZ\xc6 \x00\x00\u07d4,#OP\\\xa8\xdc\xc7}\x9b~\x01\xd2W\xc3\x18\xcc\x199m\x89\x05k\xc7^-c\x10\x00\x00\u07d4,$(\xe4\xa6it\xed\xc8\"\xd5\xdb\xfb$\x1b'(\aQX\x89lk\x93[\x8b\xbd@\x00\x00\u07d4,-\x15\xff9V\x1c\x1br\xed\xa1\xcc\x02\u007f\xfe\xf27C\xa1D\x89\u0500\xed\x9e\xf3+@\x00\x00\u07d4,-\xb2\x8c3\t7^\xea<mr\xcdm\x0e\xec\x14Z\xfc\xc0\x89lk\x93[\x8b\xbd@\x00\x00\u07d4,BN\xe4\u007fX<\xdc\xe0z\xe3\x18\xb6\xfa\xd4b8\x1dM+\x89\xd8\xd7&\xb7\x17z\x80\x00\x00\xe0\x94,KG\x03\a\xa0Y\x85@U\xd9\x1e\xc3yM\x80\xb5=\x0fJ\x8a\x04<3\xc1\x93ud\x80\x00\x00\u07d4,R\u0244\x10.\xe0\xcd>1\x82\x1b\x84\xd4\b\x93\x0e\xfa\x1a\u01c9lk\x93[\x8b\xbd@\x00\x00\u07d4,Z-\n\xbd\xa0;\xbe!W\x81\xb4\xff)l\x8ca\xbd\xba\xf6\x89\x01\xa8\xe5oH\xc0\"\x80\x00\u07d4,[}{\x19Z7\x1b\xf9\xab\u0774/\xe0O/\x1d\x9a\x99\x10\x89\n\u05ce\xbcZ\xc6 \x00\x00\u07d4,]\xf8ffj\x19K&\u03bb@~J\x1f\xd7> \x8d^\x8965\u026d\xc5\u07a0\x00\x00\xe0\x94,`?\xf0\xfe\x93alCW>\xf2y\xbf\xea@\x88\x8dj\xe7\x8a\x01\x00\xf4\xb6\xd6gW\x90\x00\x00\xe0\x94,hF\xa1\xaa\x99\x9a\"F\xa2\x87\x05`\x00\xbaM\u02e8\xe6=\x8a\x02\x1f/o\x0f\xc3\xc6\x10\x00\x00\u0794,j\xfc\xd4\x03|\x1e\xd1O\xa7O\xf6u\x8e\tE\xa1\x85\xa8\xe8\x88\xf4?\xc2\xc0N\xe0\x00\x00\u07d4,ki\x9d\x9e\xad4\x9f\x06\u007fEq\x1a\aJd\x1d\xb6\xa8\x97\x89\x01\x15\x8eF\t\x13\xd0\x00\x00\u07d4,o\\\x12L\u01c9\xf8\xbb9\x8e?\x88\x97Q\xbcK`-\x9e\x89\x01Y\xf2\v\xed\x00\xf0\x00\x00\u07d4,\x83\xae\xb0/\xcf\x06}e\xa4p\x82\xfd\x97x3\xab\x1c\uc449\b'8#%\x8a\xc0\x00\x00\xe0\x94,\x89\xf5\xfd\xca=\x15T\t\xb68\xb9\x8at.U\xebFR\xb7\x8a\x14\u06f2\x19\\\xa2(\x90\x00\x00\u07d4,\x96HI\xb1\xf6\x9c\xc7\u03a4D%8\xed\x87\xfd\xf1l\xfc\x8f\x89lk\x93[\x8b\xbd@\x00\x00\u0794,\x9f\xa7,\x95\xf3}\b\xe9\xa3`\t\u7930\u007f)\xba\xd4\x1a\x88\xdfn\xb0\xb2\xd3\xca\x00\x00\u07d4,\xafk\xf4\xec}Z\x19\xc5\xe0\x89z^\xeb\x01\x1d\xce\xceB\x10\x89\a\x93H5\xa01\x16\x00\x00\u07d4,\xb4\xc3\xc1k\xb1\xc5^|kz\x19\xb1'\xa1\xac\x93\x90\xcc\t\x89\xb8'\x94\xa9$O\f\x80\x00\xe0\x94,\xb5IZPS6\xc2FT\x10\xd1\xca\xe0\x95\xb8\xe1\xba\\\u074a\x04<3\xc1\x93ud\x80\x00\x00\u07d4,\xb6\x15\a:@\xdc\u06d9\xfa\xa8HW.\x98{;\x05n\xfb\x89+X\xad\u06c9\xa2X\x00\x00\u07d4,\xbam]\r\xc2\x04\xea\x8a%\xad\xa2\xe2oVu\xbd_/\u0709H#\xef}\u06da\xf3\x80\x00\u07d4,\xbb\fs\u07d1\xb9\x17@\xb6i;wJ}\x05\x17~\x8eX\x89dI\xe8NG\xa8\xa8\x00\x00\u07d4,\xcbfIM\n\xf6\x89\xab\xf9H=6]x$D\xe7\u07ad\x8965\u026d\xc5\u07a0\x00\x00\u07d4,\xcc\x1f\x1c\xb5\xf4\xa8\x00.\x18k \x88]\x9d\xbc\x03\f\b\x94\x89lk\x93[\x8b\xbd@\x00\x00\u07d4,\u03c0\xe2\x18\x98\x12^\xb4\xe8\a\u0342\xe0\x9b\x9d(Y/n\x89lk\x93[\x8b\xbd@\x00\x00\u07d4,\u0456\x94\u0452j\x0f\xa9\x18\x9e\u07ba\xfcg\x1c\xf1\xb2\u02a5\x8965\u026d\xc5\u07a0\x00\x00\u07d4,\u04d34\xac~\xacyrW\xab\xe3sa\x95\xf5\xb4\xb5\xce\x0f\x89\x05kGx^7&\x00\x00\u07d4,\u05de\xb5 '\xb1,\x18\x82\x8e>\xaa\xb2\x96\x9b\xfc\u0487\xe9\x89\x01\x15\x8eF\t\x13\xd0\x00\x00\u07d4,\xd8xfV\x8d\xd8\x1a\xd4}\x9d:\u0404nZePss\x89\x15\xaf\x1dx\xb5\x8c@\x00\x00\u07d4,\xdb9De\x06\x16\xe4|\xb1\x82\xe0`2/\xa1Hyx\u0389b\xa9\x92\xe5:\n\xf0\x00\x00\u07d4,\xe1\x1a\x92\xfa\xd0$\xff+>\x87\xe3\xb5B\xe6\xc6\r\xcb\u0656\x89\xd8\xd7&\xb7\x17z\x80\x00\x00\u07d4-\x03&\xb2?\x04\t\xc0\xc0\xe9#hc\xa13\aZ\x94\xba\x18\x89\vg\x9b\xe7[\xe6\xae\x00\x00\u07d4-\r\xecQ\xa6\xe8s0\xa6\xa8\xfa*\x0fe\u060dJ\xbc\xdfs\x89\n\ad\a\xd3\xf7D\x00\x00\u07d4-#vkok\x05s}\xad\x80\xa4\x19\xc4\x0e\xdaMw\x10>\x89\xcf\x15&@\xc5\xc80\x00\x00\u07d4-+\x03#Y\xb3c\x96O\xc1\x1aQ\x82c\xbf\xd0T1\xe8g\x89\b\x1c\x1d\xf7b\x9ep\x00\x00\u07d4-4\x80\xbf\be\aJr\xc7u\x9e\xe5\x13{Mp\xc5\x1c\xe9\x89\n\u05ce\xbcZ\xc6 \x00\x00\u07d4-5\xa9\xdfbu\u007f\u007f\xfa\xd1\x04\x9a\xfb\x06\xcaJ\xfcFLQ\x89\x01\x15\x8eF\t\x13\xd0\x00\x00\u07d4-@U\x8b\x06\xf9\n9#\x14U\x92\x12;gt\xe4n1\xf4\x8965\u026d\xc5\u07a0\x00\x00\u07d4-Bi\x12\xd0Y\xfa\xd9t\v.9\n.\xea\xc0To\xf0\x1b\x89K\xe4\xe7&{j\xe0\x00\x00\u07d4-S-\xf4\xc69\x11\xd1\u0391\xf6\xd1\xfc\xbf\xf7\x96\x0fx\xa8\x85\x89Z\x85\x96\x8aXx\u0680\x00\u07d4-S\x91\xe98\xb3HX\u03d6[\x84\x051\xd5\xef\xdaA\v\t\x89K\xe4\xe7&{j\xe0\x00\x00\xe0\x94-[B\xfcY\xeb\xda\r\xfdf\xae\x91K\u008c\x1b\nn\xf8:\x8a+\u0235\x9f\xdc\xd86c\x80\x00\u07d4-]s5\xac\xb06+G\u07e3\xa8\xa4\xd3\xf5\x94\x95D\u04c0\x89\n\u05ce\xbcZ\xc6 \x00\x00\xe0\x94-a\xbf\xc5hs\x92<+\x00\t]\xc3\xea\xa0\xf5\x90\u062e\x0f\x8a\x04ef\xdf\xf8\xceU`\x00\x00\u07d4-e\x11\xfdz8\x00\xb2hT\xc7\xec9\xc0\u0735\xf4\xc4\xe8\xe8\x89\x15\xad\u077a/\x9ew\x00\x00\u07d4-}\\@\u076f\xc4P\xb0Jt\xa4\u06bc+\xb5\xd6e\x00.\x89lk\x93[\x8b\xbd@\x00\x00\u07d4-\x89\xa8\x00jO\x13z \xdc+\xecF\xfe.\xb3\x12\xea\x96T\x89\n\u05ce\xbcZ\xc6 \x00\x00\u07d4-\x8cR2\x9f8\u04a2\xfa\x9c\xba\xf5\u0143\xda\xf1I\v\xb1\x1c\x89\x01\x15\x8eF\t\x13\xd0\x00\x00\u07d4-\x8e\x06\x18\x92\xa5\xdc\xce!\x96j\xe1\xbb\a\x88\xfd>\x8b\xa0Y\x89\r\x8e\\\xe6\x17\xf2\xd5\x00\x00\u07d4-\x8e[\xb8\xd3R\x16\x95\xc7~|\x83N\x02\x91\xbf\xac\xeet\b\x89j\xcb=\xf2~\x1f\x88\x00\x00\u07d4-\x90\xb4\x15\xa3\x8e.\x19\xcd\xd0/\U000ed069z\xf7\xcb\xf6r\x89\x05\xf3\xc7\xf6A1\xe4\x00\x00\u07d4-\x9b\xado\x1e\xe0*p\xf1\xf1=\xef\\\u0332z\x9a'@1\x89a\t=|,m8\x00\x00\u07d4-\x9c_\xec\u04b4O\xbbj\x1e\xc72\xea\x05\x9fO\x1f\x9d+\\\x896\xca2f\x1d\x1a\xa7\x00\x00\xe0\x94-\xa6\x17iP\t\xccW\xd2j\u0510\xb3*]\xfb\xeb\x93N^\x8a\x04<3\xc1\x93ud\x80\x00\x00\u07d4-\xa7k|9\xb4 \u323a,\x10 \xb0\x85k\x02pd\x8a\x89lk\x93[\x8b\xbd@\x00\x00\u07d4-\u01ddn\u007fU\xbc\xe2\xe2\xd0\xc0*\xd0|\uca3bR\x93T\x89U\xa6\xe7\x9c\xcd\x1d0\x00\x00\xe0\x94-\xca\x0eD\x9a\xb6F\xdb\xdf\u04d3\xa9fb\x96\v\u02b5\xae\x1e\x8a\bxg\x83&\xea\xc9\x00\x00\x00\u07d4-\xd3%\xfd\xff\xb9{\x19\x99R\x84\xaf\xa5\xab\xdbWJ\x1d\xf1j\x89\x1b\x1a\xe4\xd6\xe2\xefP\x00\x00\u07d4-\xd5x\xf7@}\xfb\xd5H\xd0^\x95\xcc\u00dcHT)bj\x89\u3bb5sr@\xa0\x00\x00\u07d4-\xd8\xee\xef\x87\x19J\xbc,\xe7X]\xa1\xe3[|\xeax\f\xb7\x8965\xc6 G9\u0640\x00\u07d4-\xdf@\x90Wi\xbc\xc4&\xcb,)8\xff\xe0w\xe1\u8758\x89\xa2\xa1]\tQ\x9b\xe0\x00\x00\u07d4-\xe0\x96D\x00\u0082\xbd\u05ca\x91\x9ck\xf7|k_yay\x89\n\u05ce\xbcZ\xc6 \x00\x00\xe0\x94-\xe3\x1a\xfd\x18\x9a\x13\xa7o\xf6\xfes\xea\xd9\xf7K\xb5\u0126)\x8a\x01EB\xba\x12\xa37\xc0\x00\x00\u07d4-\xec\x982\x9d\x1f\x96\u00e5\x9c\xaay\x81uTR\xd4\xdaI\u0549\n\u05ce\xbcZ\xc6 \x00\x00\xe0\x94-\ue422\x8f\x19-gj\x87s#+V\xf1\x8f#\x9e/\xad\x8a\x03\xef\xa7\xe7G\xb6\u046d\x00\x00\xe0\x94.\b\x80\xa3E\x96#\a \xf0Z\xc8\xf0e\xaf\x86\x81\u0736\u008a\x15-\x02\xc7\xe1J\xf6\x80\x00\x00\u07d4.\fW\xb4qP\xf9Z\xa6\xa7\xe1j\xb9\xb1\xcb\xf5C(\x97\x9a\x89\x05k\xc7^-c\x10\x00\x00\u07d4.\x10\x91\v\xa6\xe0\xbc\x17\xe0UUf\x14\u02c7\t\x0fM~[\x89\n\u05ce\xbcZ\xc6 \x00\x00\xe0\x94.$\xb5\x97\x87;\xb1A\xbd\xb27\xea\x8aZ\xb7Gy\x9a\xf0-\x8a\x04<3\xc1\x93ud\x80\x00\x00\u07d4.(\x10\xde\xe4J\xe4\xdf\xf3\xd8cB\xab\x12fW\xd6S\xc36\x89\n\u05ce\xbcZ\xc6 \x00\x00\u07d4.,\xbdz\xd8%G\xb4\xf5\xff\x8b:\xb5o\x94*dE\xa3\xb0\x89\n\u05ce\xbcZ\xc6 \x00\x00\u07d4.-~\xa6k\x9fG\xd8\xccR\xc0\x1cR\xb6\u147c}G\x86\x89\xd8\xd4`,&\xbfl\x00\x00\u07d4.C\x93H\u07caBw\xb2*v\x84W\xd1\x15\x8e\x97\xc4\t\x04\x89*\x1e\x9f\xf2o\xbfA\x00\x00\xe0\x94.F\xfc\xeej;\xb1E\xb5\x94\xa2C\xa3\x91?\xce]\xado\xba\x8a\x02\x1e\x19\xe0\u027a\xb2@\x00\x00\u0794.G\xf2\x87\xf4\x98#7\x13\x85\r1&\x82<\xc6}\xce\xe2U\x88\u029d\x9e\xa5X\xb4\x00\x00\u07d4.N\u1b99j\xa0\xa1\xd9$(\xd0fR\xa6\xbe\xa6\xd2\xd1]\x89lk\x93[\x8b\xbd@\x00\x00\u07d4.R\x91+\xc1\x0e\xa3\x9dT\xe2\x93\xf7\xae\u05b9\x9a\x0fLs\xbe\x89\x15\xaf\x1dx\xb5\x8c@\x00\x00\u07d4.a\x9fW\xab\xc1\u91ea\x93j\xe3\xa2&Ib\xe7\xeb-\x9a\x89(\xfb\x9b\x8a\x8aSP\x00\x00\u07d4.d\xa8\xd7\x11\x11\xa2/L]\xe1\xe09\xb36\xf6\x8d9\x8a|\x89lk\x93[\x8b\xbd@\x00\x00\u07d4.i3T=O,\xc0\vSP\xbd\x80h\xba\x92C\u05be\xb0\x89lk\x93[\x8b\xbd@\x00\x00\xe0\x94.~\x05\xe2\x9e\u0767\xe4\xae%\xc5\x175C\xef\xd7\x1fm=\x80\x8a\x01EB\xba\x12\xa37\xc0\x00\x00\u07d4.\u007fFU \xec5\xcc#\u058eue\x1b\xb6h\x95D\xa1\x96\x898\xec[r\x1a\x1a&\x80\x00\u07d4.\x8e\xb3\nqn_\xe1\\t#>\x03\x9b\xfb\x11\x06\xe8\x1d\x12\x89\x05k\xc7^-c\x10\x00\x00\xe0\x94.\x98$\xb5\xc12\x11\x1b\xca$\xdd\xfb\xa7\xe5u\xa5\xcdr\x96\xc1\x8a\x03\xa4\x84Qnm\u007f\xfe\x00\x00\u07d4.\xa5\xfe\xe6?3z7nK\x91\x8e\xa8!H\xf9MH\xa6&\x89e\x0f\x8e\r\u0493\xc5\x00\x00\u07d4.\xafN*F\xb7\x89\xcc\u0088\xc8\xd1\xd9)N?\xb0\x858\x96\x89lk\x93[\x8b\xbd@\x00\x00\u07d4.\xaf\xf9\xf8\xf8\x110d\u04d5z\xc6\xd6\xe1\x1e\xeeB\xc8\x19]\x89j\xcb=\xf2~\x1f\x88\x00\x00\u07d4.\xba\fn\xe5\xa1\x14\\\x1cW9\x84\x96:`]\x88\nz \x89\x1b\x1a\xe4\xd6\xe2\xefP\x00\x00\u07d4.\xc9X\"\xeb\x88{\xc1\x13\xb4q*M\xfd\u007f\x13\xb0\x97\xb5\xe7\x8965\u026d\xc5\u07a0\x00\x00\u07d4.\xcaj<]\x9fD\x9d\tV\xbdC\xfa{M{\xe8CYX\x89lk\xdaip\x9c\xc2\x00\x00\xe0\x94.\xca\xc5\x04\xb23\x86n\xb5\xa4\xa9\x9e{\u0490\x13Y\xe4;=\x8a\x04<3\xc1\x93ud\x80\x00\x00\u07d4.\xeb\xf5\x942\xb5(\x92\xf98\v\xd1@\xaa\x99\xdc\xf8\xad\f\x0f\x89\b=lz\xabc`\x00\x00\u07d4.\xee\xd5\x04q\xa1\xa2\xbfS\xee0\xb1#.n\x9d\x80\xef\x86m\x89\x01\x15\x8eF\t\x13\xd0\x00\x00\u07d4.\xefk\x14\x17\u05f1\x0e\xcf\xc1\x9b\x12:\x8a\x89\xe7>RlX\x89 \x86\xac5\x10R`\x00\x00\u07d4.\xf8i\xf05\vW\xd54x\xd7\x01\xe3\xfe\xe5)\xbc\x91\x1cu\x89\x02\xb5\xe3\xaf\x16\xb1\x88\x00\x00\u07d4.\xf9\xe4eqj\xca\u03f8\xc8%/\xa8\xe7\xbcyi\xeb\xf6\u4255\x9e\xb1\xc0\xe4\xae \x00\x00\xe0\x94.\xfcLd}\xacj\xca\xc3Uw\xad\"\x17X\xfe\xf6ao\xaa\x8a\x01\xb1\xaeMn.\xf5\x00\x00\x00\u07d4/\x13eu&\xb1w\xca\xd5G\u00d0\x8c\x84\x0e\xffd{E\u0649?v\x84\x9c\xf1\xee,\x80\x00\u07d4/\x18}ZpMZ3\x8c[(v\xa0\x90\xdc\xe9d(N)\x89\xd8\xd7&\xb7\x17z\x80\x00\x00\xe0\x94/%#\u0303O\x00\x86\x05$\x02bb\x96gQ\x86\xa8\u508a\x03c\\\x9a\xdc]\xea\x00\x00\x00\u07d4/(*\xbb\xb6\u0523\xc3\xcd;\\\xa8\x12\xf7d>\x800_\x06\x89dI\xe8NG\xa8\xa8\x00\x00\u07d4/+\xba\x1b\x17\x96\x82\x1avo\xced\xb8O(\xech\xf1Z\xea\x89\x01\x15\x8eF\t\x13\xd0\x00\x00\u07d4/1]\x90\x16\xe8\xee_Sf\x81 /\x90\x84\xb02TMM\x898<\xd1+\x9e\x86<\x00\x00\u07d4/M\xa7SC\x0f\xc0\x9es\xac\xbc\xcd\xcd\xe9\xdad\u007f+]7\x89\n\u05ce\xbcZ\xc6 \x00\x00\u07d4/P\x80\xb8?~-\xc0\xa1\xdd\x11\xb0\x92\xad\x04+\xffx\x8fL\x89\xb4\xf8\xfby#\x1d+\x80\x00\u07d4/a\uf941\x9dp_+\x1eN\xe7T\xae\xb8\xa8\x19Pju\x89O%\x91\xf8\x96\xa6P\x00\x00\xe0\x94/f\xbf\xbf\"b\xef\u030d+\xd0DO\u0170ib\x98\xff\x1e\x8a\x02\x1a\xd95\xf7\x9fv\xd0\x00\x00\u07d4/m\xce\x130\u015e\xf9!`!TW-MK\xac\xbd\x04\x8a\x8965\u026d\xc5\u07a0\x00\x00\u07d4/}2\x90\x85\x1b\xe5\u01b4\xb4?}Et2\x9fa\xa7\x92\u00c9\x05k\xc7^-c\x10\x00\x00\u07d4/\x858\x17\xaf\u04f8\xf3\xb8n\x9f`\xeew\xb5\xd9ws\xc0\xe3\x89N\xae\xeaD\xe3h\xb9\x00\x00\u07d4/\xa4\x91\xfbY \xa6WN\xbd(\x9f9\xc1\xb2C\r-\x9aj\x89lk\x93[\x8b\xbd@\x00\x00\u07d4/\xb5f\xc9K\xbb\xa4\xe3\xcbg\xcd\xda}_\xadq1S\x91\x02\x89lk\x93[\x8b\xbd@\x00\x00\u07d4/\xbbPJ]\xc5'\xd3\xe3\xeb\x00\x85\xe2\xfc<}\xd58\xcbz\x89C\u00b1\x8a\xec<\n\x80\x00\u07d4/\xbc\x85y\x8aX5\x98\xb5\"\x16mn\x9d\xda\x12\x1db}\xbc\x89\n\u05ce\xbcZ\xc6 \x00\x00\u07d4/\xbc\xef3\x84\xd4 \xe4\xbfa\xa0f\x99\x90\xbcpT\U00065bc9lk\x93[\x8b\xbd@\x00\x00\xe0\x94/\xc8.\xf0v\x93#A&Oaz\f\x80\xddW\x1ej\xe99\x8a\x01\x84$\xf5\xf0\xb1\xb4\xe0\x00\x00\u07d4/\u075by\u07cd\xf50\xadc\xc2\x0eb\xafC\x1a\xe9\x92\x16\xb8\x89\x01#n\xfc\xbc\xbb4\x00\x00\u07d4/\xe0\x02?W\"e\x0f:\x8a\xc0\x10\t\x12^t\xe3\xf8.\x9b\x89\xa2\xa1]\tQ\x9b\xe0\x00\x00\u07d4/\xe0\xccBKS\xa3\x1f\t\x16\xbe\b\xec\x81\xc5\v\xf8\xea\xb0\xc1\x89 \x86\xac5\x10R`\x00\x00\u07d4/\xe1:\x8d\a\x85\u0787X\xa5\xe4\x18v\xc3n\x91l\xf7Pt\x89\xd8\xd7&\xb7\x17z\x80\x00\x00\u07d4/\xea\x1b/\x83O\x02\xfcT3?\x8a\x80\x9f\x048\xe5\x87\n\xa9\x89\x01\x18T\xd0\xf9\xce\xe4\x00\x00\u07d4/\xee6\xa4\x9e\xe5\x0e\xcfqo\x10G\x91VFw\x9f\x8b\xa0?\x899B\"\xc4\u0686\xd7\x00\x00\u07d4/\xef\x81G\x8aK.\x80\x98\xdb_\xf3\x87\xba!S\xf4\xe2+y\x896'\xe8\xf7\x127<\x00\x00\u07d4/\xf1`\xc4Or\xa2\x99\xb5\xec-q\xe2\x8c\xe5Dm/\u02ef\x89\x13\x84\x00\xec\xa3d\xa0\x00\x00\u07d4/\xf1\xcaU\xfd\x9c\xec\x1b\x1f\xe9\U00029af7LQ<\x1e*\xaa\x89\xa2\xa1]\tQ\x9b\xe0\x00\x00\xe0\x94/\xf5\u02b1,\r\x95\u007f\xd33\xf3\x82\xee\xb7Q\a\xa6L\xb8\xe8\x8a\x02\x1e\x19\xe0\u027a\xb2@\x00\x00\xe0\x94/\xf80\xcfU\xfb\x00\u0560\xe05\x14\xfe\xcdD1K\xd6\xd9\xf1\x8a\x02\x1e\x19\xe0\u027a\xb2@\x00\x00\u07d4/\xfe\x93\xec\x1aV6\xe9\xee4\xafp\xdf\xf5&\x82\xe6\xffpy\x89lk\x93[\x8b\xbd@\x00\x00\u07d40\x03y\x88p&q\xac\xbe\x89,\x03\xfeW\x88\xaa\x98\xaf(z\x89\x97\xc9\xceL\xf6\xd5\xc0\x00\x00\u07d40$\x8dX\xe4\x14\xb2\x0f\xed:lH+Y\xd9\xd8\xf5\xa4\xb7\xe2\x89\x03@\xaa\xd2\x1b;p\x00\x00\u07d4019\xbcYd\x03\xd5\u04d3\x1fwLf\u013aFtT\u06c9\\%\xe1J\xea(?\x00\x00\u079408\x00\x87xie\x14\x9e\x81B;\x15\xe3\x13\xba2\xc5\u01c3\x88\xfc\x93c\x92\x80\x1c\x00\x00\u07d40:0\xacB\x86\xae\x17\xcfH=\xad{\x87\fk\xd6M{J\x89\x1b\x1a\xe4\xd6\xe2\xefP\x00\x00\u07d40?\xba\xeb\xbeF\xb3[n[t\x94j_\x99\xbc\x15\x85\xca\xe7\x89/\x9a\xc0i_[\xba\x00\x00\u07d40ADZ3\xba\x15\x87A\x16\r\x9c4N\xb8\x8e\\0o\x94\x89\x03@\xaa\xd2\x1b;p\x00\x00\u07d40H\x01d\xbc\xd8It\xeb\xc0\xd9\f\x9b\x9a\xfa\xb6&\xcd\x1cs\x89+^:\xf1k\x18\x80\x00\x00\u07d40N\u019atTW!\xd71j\xefM\u03f4\x1a\u015e\xe2\xf0\x89\n\u05ce\xbcZ\xc6 \x00\x00\xe0\x940Q\x182\x91\x8d\x804\xa7\xbe\xe7.\xf2\xbf\xeeD\x0e\u02fc\xf6\x8a\x03h\xc8b:\x8bM\x10\x00\x00\u07d40Q?\u029f6\xfdx\x8c\xfe\xa7\xa3@\xe8m\xf9\x82\x94\xa2D\x89\x18;_\x03\xb1G\x9c\x00\x00\u07d40U\xef\xd2`)\xe0\xd1\x1b\x93\r\xf4\xf5;\x16,\x8c?\xd2\u0389\x1b\x1a\b\x927\a=\x00\x00\u07d40]&\xc1\v\xdc\x10?k\x9c!'.\xb7\xcb-\x91\b\xc4~\x89\x1b\x1a\xe4\xd6\xe2\xefP\x00\x00\u07d40_x\xd6\x18\xb9\x90\xb4)[\xac\x8a-\xfa&(\x84\xf8\x04\xea\x89\xd8\xd7&\xb7\x17z\x80\x00\x00\xe0\x940d\x89\x9a\x96<Gy\xcb\xf6\x13\xcdi\x80\x84j\xf1\xe6\xece\x8a\x01{w<\xe6\xe5\xdf\n\x00\x00\u07d40s\x04f\xb8\xebm\xc9\rT\x96\xaav\xa3G-}\xbe\v\xbe\x89lh\xcc\u041b\x02,\x00\x00\u07d40t,\xcd\xf4\xab\xbc\xd0\x05h\x1f\x81Y4\\\x9ey\x05K\x1a\x89$=M\x18\"\x9c\xa2\x00\x00\xe0\x940\x83\xef\x0e\xd4\xc4@\x11\x96wJ\x95\xcfN\u0703\xed\xc1HO\x8a#\xff\xb7\xedee\xd6@\x00\x00\u07d40\x8d\xd2\x1c\xeb\xe7U\x12g\x04\xb4\x8c\x0f\r\xc24\xc6\v\xa9\xb1\x89\n\u05ce\xbcZ\xc6 \x00\x00\u07d40\x90\xf8\x13\x0e\xc4Df\xaf\xad\xb3n\xd3\xc9&\x139cg{\x89\xd8\xd7&\xb7\x17z\x80\x00\x00\u07d40\x95D\xb6#,=\xd77\xf9E\xa01\x93\u045b_?e\xb9\x89:\xf3B\xf6~\xf6\xc8\x00\x00\u07d40\x96\u0723A\b\b[\xcf\x04\xaer\xb9Et\xa1>\x1a>\x1d\x89\n\u05ce\xbcZ\xc6 \x00\x00\u07d40\x98\xb6]\xb9>\xca\xca\xf75<H\x80\x83\x90\xa2#\xd5v\x84\x89\x18d\x84\xcf{\xb6\xa4\x80\x00\u07d40\xa9\xdarWLQ\xe7\xee\t\x04\xba\x1fs\xa6\xb7\xb8;\x9b\x9d\x89\x01\x18T\xd0\xf9\xce\xe4\x00\x00\u07d40\xac\xd8X\x87_\xa2N\xef\rW/\xc7\xd6*\xad\x0e\xbd\xdc5\x89\x15\xaf\x1dx\xb5\x8c@\x00\x00\u07d40\xb6aP\xf1\xa64W\x02?\xddE\xd0\xccl\xb5N\f\x0f\x06\x8965\u026d\xc5\u07a0\x00\x00\u07d40\xbbCW\xcdi\x10\xc8m\"8\xbfr|\xbe\x81Vh\x0eb\x89\x05k\xf9\x1b\x1ae\xeb\x00\x00\u07d40\xbfa\xb2\xd8w\xfe\x10cQ&2o\xa1\x89\u4c31\u00f0\x897\xb4\x89\x85\xa5\xd7\xe6\x00\x00\u07d40\xc0\x11B\x90z\xcb\x15e\xf7\x048\xb9\x98\n\xe71\x81\x878\x89lk\x93[\x8b\xbd@\x00\x00\xe0\x940\xc2j\x8e\x97\x1b\xaa\x18U\xd63\xbap?\x02\x8c\u01c71@\x8a\x02\x1e\x19\xe0\u027a\xb2@\x00\x00\u07d40\xdbk\x9b\x10~b\x10/CJ\x9d\u0416\f !\xf5\xceL\x89 \x83\x17\x9bnBS\x00\x00\u07d40\xe33X\xfc!\xc8P\x06\xe4\x0f25}\u0209Y@\xaa\xf0\x89g\x8a\x93 b\xe4\x18\x00\x00\u07d40\xe6\t\x00\xca\xccr\x03\xf3\x14\xdc`CG%Qg\xfc*\x0f\x89lk\x93[\x8b\xbd@\x00\x00\u07d40\u7273\xd2F^\x94nb\x10\xfa[5\xdeN\x8c\x93\b_\x89lk\x93[\x8b\xbd@\x00\x00\xe0\x940\xe9i\x8c\xf1\xe0\x8a\x9d\x04\x8b\xd8\xd8\x04\x8f(\xbe~\xd9@\x9f\x8a\x01je\x02\xf1Z\x1eT\x00\x00\u07d40\xe9\u0560\b\x8f\x1d\xdb/\u04c0\xe2\xa0I\x19\"f\xc5\x1c\xbf\x89\n\xac\xac\u0679\xe2+\x00\x00\u07d40\xea\xc7@\xe4\xf0,\xb5n\xef\x05&\xe5\xd3\x002&\x00\xd0>\x89j\xcb=\xf2~\x1f\x88\x00\x00\u07d40\uc4d2$J!\b\u0247\xbc\\\xdd\xe0\ud7c3z\x81{\x89T\x99%\xf6\xc9\xc5%\x00\x00\xe0\x940\xed\x11\xb7{\xc1~^f\x94\u023c[nG\x98\xf6\x8d\x9c\xa7\x8a\x1eo\xb3B\x1f\xe0)\x9e\x00\x00\u07d40\xf7\xd0%\xd1o{\xee\x10U\x80Ho\x9fV\x1c{\xae?\xef\x89\x1b\x1a\xe4\xd6\xe2\xefP\x00\x00\xe0\x940\xfb\xe5\x88_\x9f\xcc\xe9\xea^\u06c2\xedJ\x11\x96\xdd%\x9a\xed\x8a\x01\x19\xe4\u007f!8\x1f@\x00\x00\u07d41\x04}p?c\xb94$\xfb\xbdn/\x1f\x9et\xde\x13\xe7\t\x89\x9a\x81f\xf7\u6ca7\x80\x00\u07d411?\xfdc[\xf2\xf32HA\xa8\x8c\a\xed\x14aD\xce\xeb\x89j\xcb=\xf2~\x1f\x88\x00\x00\u07d41Y\xe9\fH\xa9\x15\x90J\xdf\u24b2/\xa5\xfd^ryk\x896\xaf\xe9\x8f&\x06\x10\x00\x00\u07d41]\xb7C\x9f\xa1\u0574#\xaf\xa7\xddq\x98\xc1\xcft\xc9\x18\xbc\x89 \x86\xac5\x10R`\x00\x00\u07d41^\xf2\xdab\x0f\xd30\xd1.\xe5]\xe5\xf3)\xa6\x96\xe0\xa9h\x89\b!\xab\rD\x14\x98\x00\x00\u07d41n\x92\xa9\x1b\xbd\xa6\x8b\x9e/\x98\xb3\xc0H\x93N<\xc0\xb4\x16\x89lk\x93[\x8b\xbd@\x00\x00\u07d41n\xb4\xe4}\xf7\x1bB\xe1mo\xe4h%\xb72{\xaf1$\x89\xd8\xd7&\xb7\x17z\x80\x00\x00\u07d41q\x87~\x9d\x82\f\xc6\x18\xfc\t\x19\xb2\x9e\xfd3?\xdaI4\x8965\u026d\xc5\u07a0\x00\x00\u07d41|\xf4\xa2<\xb1\x91\xcd\xc5c\x12\u009d\x15\xe2\x10\xb3\xb9\xb7\x84\x89\a\xcef\xc5\x0e(@\x00\x00\u07d41\x8b.\xa5\xf0\xaa\xa8y\xc4\xd5\xe5H\xac\x9d\x92\xa0\xc6t\x87\xb7\x89\n\u05ce\xbcZ\xc6 \x00\x00\u07d41\x8cv\xec\xfd\x8a\xf6\x8dpUSR\xe1\xf6\x01\xe3Y\x88\x04-\x89\x1b1\x19.h\xc7\xf0\x00\x00\u07d41\x8f\x1f\x8b\xd2 \xb0U\x8b\x95\xfb3\x10\x0f\xfd\xbbd\r|\xa6\x89\xd8\xd7&\xb7\x17z\x80\x00\x00\u07d41\xaa;\x1e\xbe\x8cM\xbc\xb6\xa7\b\xb1\xd7H1\xe6\x0eIv`\x89\x15\xaf\x1dx\xb5\x8c@\x00\x00\u07d41\xab\b\x89f\xec\xc7\"\x92X\xf6\t\x8f\xceh\xcf9\xb3\x84\x85\x8965\u026d\xc5\u07a0\x00\x00\xe0\x941\xadM\x99F\xef\t\xd8\xe9\x88\xd9F\xb1\"\u007f\x91A\x90\x176\x8a\x04\xd8S\xc8\xf8\x90\x89\x80\x00\x00\xe0\x941\xb4;\x01]\x00\x81d<l\xdaF\xa7\a:m\xfd\xbc\xa8%\x8a\n\x97\x91e \xcd\x18\xe8\x00\x00\u07d41\xcc\xc6\x16\xb3\x11\x82h\xe7]\x9a\xb8\x99l\x88X\xeb\xd7\xf3\u00c9\x15\xae\x0fw\x1c\xa1R\x00\x00\u07d41\xd8\x1dRl\x19^?\x10\xb5\xc6\xdbR\xb5\xe5\x9a\xfb\u0a55\x89\x0eO\xbciD\x9f \x00\x00\u07d41\xe9\xc0\x0f\f jNN~\x05\"\x17\r\xc8\x1e\x88\xf3\xebp\x89\x91\x8d\xdc:B\xa3\xd4\x00\x00\u07d41\xea\x12\u051a5\xa7@x\r\xde\xea\xec\xe8L\b5\xb2bp\x89\n\u05ce\xbcZ\xc6 \x00\x00\u07d41\xean\xab\x19\xd0\ad\xe9\xa9^\x18?+\x1b\"\xfc}\xc4\x0f\x89\x01\x15\x8eF\t\x13\xd0\x00\x00\u07d41\xeb\x12<\x95\xc8+\xf6\x85\xac\xe7\xa7Z\x18\x81\xa2\x89\xef\xca\x10\x891\xe0\t`sq\xbd\x00\x00\u07d41\ud147\x88\xbd\xa4\xd5'\t\x92\"\x1c\xc0B\x06\xecba\r\x89?\xc0GIH\xf3`\x00\x00\u07d41\xf0\x06\xf3IN\xd6\xc1n\xb9*\xaf\x90D\xfa\x8a\xbb_\u0563\x89\x1b\x1a\xe4\xd6\xe2\xefP\x00\x00\xe0\x942\x01%\x9c\xafsJ\xd7X\x1cV\x10Q\xba\v\xca\u007f\u0594k\x8a&\x1d\xd1\xce/ \x88\x80\x00\x00\u07d42\x03N\x85\x81\xd9HN\x8a\xf4*(\xdf\x19\x012\xec)\xc4f\x89\xbb\x91%T\"c\x90\x00\x00\u07d42 !\x02&x\xa0\x16m K:\xaaz\xd4\xecK\x88\xb7\u0409\x15\xaf\x1dx\xb5\x8c@\x00\x00\u07d42%\xc1\xca_*\x9c\x88\x15k\xb7\xd9\xcd\xc4J2fS\xc2\x14\x89\x15\xaf\x1dx\xb5\x8c@\x00\x00\u07d42'\x88\xb5\xe2\x9b\xf4\xf5\xf5Z\xe1\u0773 \x85\xfd\xa9\x1b\x8e\xbe\x89\n\u05ce\xbcZ\xc6 \x00\x00\u07d42-o\x9a\x14\r!?L\x80\xcd\x05\x1a\xfe%\xc6 \xbfL}\x89\x01\x15\x8eF\t\x13\xd0\x00\x00\u07d42.\\C\xb0\xf5$8\x96U\xa9\xb3\xff$\xf2\xd4\xdb=\xa1\x0f\x89\xfc\x13\xb6\x9b>~h\x00\x00\u07d424\x86\xcad\xb3uGO\xb2\xb7Y\xa9\xe7\xa15\x85\x9b\xd9\xf6\x89\x15\xaf\x1dx\xb5\x8c@\x00\x00\u07d427I\xa3\xb9q\x95\x9eF\u0234\x82-\xca\xfa\xf7\xaa\xf9\xbdn\x89\x01\x16q\xa5\xb2Ep\x00\x00\u07d42:\xadA\xdfKo\xc8\xfe\u038c\x93\x95\x8a\xa9\x01\xfah\bC\x894\x95tD\xb8@\xe8\x00\x00\xe0\x942;<\xfe>\xe6+\xbd\xe2\xa2a\xe5<\xb3\xec\xc0X\x10\xf2\u018a\x02\ub3b1\xa1r\u0738\x00\x00\u07d42?\xca^\xd7\u007fi\x9f\x9d\x990\xf5\xce\xef\xf8\xe5oY\xf0<\x89Hz\x9a0E9D\x00\x00\u07d42H\\\x81\x87(\xc1\x97\xfe\xa4\x87\xfb\xb6\xe8)\x15\x9e\xba\x83p\x899!\xb4\x13\xbcN\xc0\x80\x00\xe0\x942P\xe3\xe8X\xc2j\xde\u032d\xf3jVc\xc2*\xa8LAp\x8a\x01\x0f\f\xf0d\xddY \x00\x00\xe0\x942Y\xbd/\xdd\xfb\xbco\xba\u04f6\xe8t\xf0\xbb\xc0,\xda\x18\xb5\x8a\x02\x84`VI[\r\x18\x80\x00\u07d42uIo\xd4\u07491\xfdi\xfb\n\v\x04\xc4\xd1\xff\x87\x9e\xf5\x89\x18-~L\xfd\xa08\x00\x00\u07d42{\xb4\x9euOo\xb4\xf73\xc6\xe0o9\x89\xb4\xf6]K\xee\x89\x01\x15\x8eF\t\x13\xd0\x00\x00\u07d42\x82y\x1do\xd7\x13\xf1\xe9OK\xfdV^\xaax\xb3\xa0Y\x9d\x89Hz\x9a0E9D\x00\x00\u07d42\x83\xeb\u007f\x917\xdd9\xbe\xd5_\xfek\x8d\xc8E\xf3\xe1\xa0y\x89\x03\x97\n\xe9!Ux\x00\x00\u07d42\x86\t\x97\xd70\xb2\xd8;s$\x1a%\xd3f}Q\xc9\b\xef\x89\x1b\x1a\b\x927\a=\x00\x00\xe0\x942\x86\u047cez1,\x88G\xd9<\xb3\xcbyP\xf2\xb0\xc6\xe3\x8a\x04<3\xc1\x93ud\x80\x00\x00\xe0\x942\xa2\r\x02\x8e,b\x18\xb9\xd9[D\\w\x15$cj\"\xef\x8a\x02\x02\xfe\xfb\xf2\xd7\xc2\xf0\x00\x00\u07d42\xa7\x06\x91%\\\x9f\xc9y\x1aOu\u0238\x1f8\x8e\n%\x03\x895e\x9e\xf9?\x0f\xc4\x00\x00\u07d42\xb7\xfe\xeb\xc5\u015b\xf6^\x86\x1cL\v\xe4*v\x11\xa5T\x1a\x89w\u9aa8R\\\x10\x00\x00\xe0\x942\xba\x9a}\x04#\xe0:R_\xe2\xeb\xebf\x1d \x85w\x8b\u060a\x04<3\xc1\x93ud\x80\x00\x00\u07d42\xbb.\x96\x93\xe4\xe0\x854M/\r\xbdF\xa2\x83\u3807\xfd\x89\x15\xaf\x1dx\xb5\x8c@\x00\x00\xe0\x942\xc2\xfd\u2daa\xbb\x80\u5ba2\xb9I\xa2\x17\xf3\xcb\t\"\x83\x8a\x010a`\xaf\xdf 7\x80\x00\u07d42\xd9P\xd5\xe9>\xa1\u0574\x8d\xb4qO\x86{\x03 \xb3\x1c\x0f\x897\b\xba\xed=h\x90\x00\x00\u07d42\u06f6qlT\xe81e\x82\x9aJ\xbb6uxI\xb6\xe4}\x8965\u026d\xc5\u07a0\x00\x00\u07d42\xebd\xbe\x1b]\xed\xe4\b\u01bd\xef\xben@\\\x16\xb7\xed\x02\x89j\xcb=\xf2~\x1f\x88\x00\x00\u07d42\xef\\\xdcg\x1d\xf5V*\x90\x1a\xee]\xb7\x16\xb9\xbev\xdc\xf6\x89lk\x93[\x8b\xbd@\x00\x00\u07d42\xf2\x9e\x87'\xa7LkC\x01\xe3\xff\xff\x06\x87\xc1\xb8p\xda\xe9\x8965\u026d\xc5\u07a0\x00\x00\u07d42\xfa\x0e\x86\xcd\b}\u058di1\x90\xf3-\x931\t\t\xedS\x89\xd8\xd7&\xb7\x17z\x80\x00\x00\u07d42\xfb\xee\xd6\xf6&\xfc\xdf\xd5\x1a\xca\xfbs\v\x9e\xef\xf6\x12\xf5d\x89lk\x93[\x8b\xbd@\x00\x00\u07943\x00\xfb\x14\x9a\xde\xd6[\u02e6\xc0N\x9c\u05b7\xa0;\x89;\xb1\x88\xfc\x93c\x92\x80\x1c\x00\x00\xe0\x943\x01\xd9\xca/;\xfe\x02by\xcdh\x19\xf7\x9a)=\x98\x15n\x8a\n\x96\x81c\xf0\xa5{@\x00\x00\xe0\x943\b\xb04f\xc2z\x17\xdf\xe1\xaa\xfc\xeb\x81\xe1m)4Vo\x8a\x03\x99\x92d\x8a#\u0220\x00\x00\u07943\x1a\x1c&\xcci\x94\xcd\xd3\xc1K\xec\xe2v\xff\xffK\x9d\xf7|\x88\xfaz\xed\xdfO\x06\x80\x00\xe0\x943&\xb8\x8d\xe8\x06\x18DT\xc4\v'\xf3\t\xd9\xddm\u03f9x\x8a\x03\xca\\f\u067cD0\x00\x00\xe0\x943)\xeb;\xafCE\xd6\x00\xce\xd4\x0en\x99ueo\x117B\x8a\x01\x0f\b\xed\xa8\xe5U\t\x80\x00\u07d432\r\xd9\x0f+\xaa\x11\r\xd34\x87*\x99\x8f\x14\x84&E<\x8965f3\xeb\xd8\xea\x00\x00\u07d436\xc3\xefn\x8bP\xee\x90\xe07\xb1d\xb7\xa8\xea_\xaa\xc6]\x89\x0e\u0223\xa7\x1c\"T\x00\x00\xe0\x9438\fo\xffZ\xcd&Q0\x96)\u06daq\xbf? \u017a\x8a\x03h\xc8b:\x8bM\x10\x00\x00\u07d43:\xd1Yd\x01\xe0Z\xea-6\xcaG1\x8e\xf4\xcd,\xb3\u07c9\x9d\xc0\\\xce(\u00b8\x00\x00\u07d43C@\xeeK\x9c\u0701\xf8P\xa7Q\x16\xd5\x0e\u9d98%\xbf\x89lk\x93[\x8b\xbd@\x00\x00\u07d43H\x1e\x85n\xbe\u050e\xa7\b\xa2t&\xef(\xe8g\xf5|\u0449\n\u05ce\xbcZ\xc6 \x00\x00\xe0\x943V[\xa9\xda,\x03\xe7x\xce\x12)O\b\x1d\xfe\x81\x06M$\x8a\x03c\\\x9a\xdc]\xea\x00\x00\x00\u07943X\x1c\xee#0\x88\xc0\x86\r\x94N\f\xf1\u03ab\xb8&\x1c.\x88\xb9\x8b\xc8)\xa6\xf9\x00\x00\u07d43XX\xf7I\xf1i\u02bc\xfeR\xb7\x96\xe3\xc1\x1e\xc4~\xa3\u0089\n\u05ce\xbcZ\xc6 \x00\x00\xe0\x943^\"\x02[zw\u00e0t\u01cb\x8e=\xfe\a\x13A\x94n\x8a\x02'\xcas\n\xb3\xf6\xac\x00\x00\u07d43b\x9b\xd5/\x0e\x10{\xc0q\x17ld\xdf\x10\x8fdw}I\x89\x01\xcf\xddth!n\x80\x00\u07d43{;\u07c6\xd7\x13\xdb\xd0{]\xbf\xcc\x02+z{\x19F\xae\x89\xd7\xc1\x98q\x0ef\xb0\x00\x00\u07d43|\xfe\x11W\xa5\u0191 \x10\xddV\x153y\x17i\u00b6\xa6\x8965\u026d\xc5\u07a0\x00\x00\u07d43\xb36\xf5\xba^\xdb{\x1c\xcc~\xb1\xa0\u0644\xc1#\x1d\x0e\u0709lk\x93[\x8b\xbd@\x00\x00\u07d43\xc4\a\x13;\x84\xb3\xcaL=\xed\x1fFX\x90\f8\x10\x16$\x89\x97\xc9\xceL\xf6\xd5\xc0\x00\x00\xe0\x943\xd1r\xab\a\\Q\xdb\x1c\xd4\n\x8c\xa8\xdb\xff\r\x93\xb8C\xbb\x8a\x016x\x05\x10\xd1-\xe3\x80\x00\u07d43\xe9\xb7\x18#\x95.\x1ff\x95\x8c'\x8f\u008b\x11\x96\xa6\u0164\x89\x05k\xc7^-c\x10\x00\x00\u07d43\xeakxU\xe0[\a\xab\x80\u06b1\xe1M\xe9\xb6I\xe9\x9bl\x89\x1c\xd6\xfb\xadW\xdb\xd0\x00\x00\u07d43\xf1R#1\rD\u078bf6h_:L=\x9cVU\xa5\x89\r\x94b\xc6\xcbKZ\x00\x00\u07d43\xf4\xa6G\x1e\xb1\xbc\xa6\xa9\xf8[;Hr\xe1\aU\xc8+\xe1\x89lk\x93[\x8b\xbd@\x00\x00\u07d43\xfbWzM!O\xe0\x10\xd3,\xca|>\xed\xa6?\x87\xce\xef\x8965\u026d\xc5\u07a0\x00\x00\u07d43\xfdq\x8f\v\x91\xb5\xce\u020a]\xc1^\xec\xf0\xec\xef\xa4\xef=\x89\x17r$\xaa\x84Lr\x00\x00\u07d44\x14\x80\u030c\xb4v\xf8\xd0\x1f\xf3\b\x12\xe7\xc7\x0e\x05\xaf\xaf]\x89lk\x93[\x8b\xbd@\x00\x00\u07d44'-^ut1]\xca\u9afd1{\xac\x90(\x9dGe\x89b\xa9\x92\xe5:\n\xf0\x00\x00\xe0\x9440\xa1c\x81\xf8i\xf6\xeaT#\x91XU\xe8\x00\x885%\xa9\x8a\x03\xca\\f\u067cD0\x00\x00\u07d441\x86%\x81\x8e\xc1?\x11\x83Z\xe9sS\xce7}oY\n\x89Rf<\u02b1\xe1\xc0\x00\x00\u07d449<]\x91\xb9\xdeYr\x03\xe7[\xacC\t\xb5\xfa=(\u00c9\n\x84Jt$\xd9\xc8\x00\x00\u07d449\x99\x8b$|\xb4\xbf\x8b\xc8\nm+5'\xf1\xdf\xe9\xa6\u0489\a\x96\xe3\xea?\x8a\xb0\x00\x00\u07d44C}\x14ed\v\x13l\xb5\x84\x1c?\x93O\x9b\xa0\xb7\t}\x89\t`\xdbwh\x1e\x94\x00\x00\u07d44J\x8d\xb0\x86\xfa\xedN\xfc7\x13\x1b:\"\xb0x-\xadp\x95\x89\x1b\x1a\xe4\xd6\xe2\xefP\x00\x00\xe0\x944fM\"\x0f\xa7\xf3yX\x02J32\u0584\xbc\xc6\xd4\u023d\x8a\x02\x1e\x19\xe0\u027a\xb2@\x00\x00\u07d44f\xf6~9cl\x01\xf4;:!\xa0\xe8R\x93%\xc0\x86$\x89-\xb1\x16vP\xac\xd8\x00\x00\u07d44\x856\x1e\xe6\xbf\x06\xefe\b\xcc\xd2=\x94d\x1f\x81M>/\x89lk\x93[\x8b\xbd@\x00\x00\u07d44\x85\xf6!%d3\xb9\x8aB\x00\xda\xd8W\xef\xe5Y7\uc609lk\x93[\x8b\xbd@\x00\x00\u07d44\x95\x8aF\xd3\x0e0\xb2s\xec\xc6\xe5\xd3X\xa2\x12\xe50~\x8c\x89lk\x93[\x8b\xbd@\x00\x00\u07d44\x97\xddf\xfd\x11\x80q\xa7\x8c,\xb3n@\xb6e\x1c\xc8%\x98\x89\x05\xf1\x01kPv\xd0\x00\x00\xe0\x944\x9a\x81k\x17\xab='\xbb\xc0\xae\x00Q\xf6\xa0p\xbe\x1f\xf2\x9d\x8a\x02\x1e\x19\xe0\u027a\xb2@\x00\x00\u07d44\x9d,\x91\x8f\u041e(\a1\x8ef\xceC)\t\x17k\xd5\v\x89<\xb7\x1fQ\xfcU\x80\x00\x00\u07d44\xa0C\x1f\xff^\xad\x92\u007f<id\x96\x16\xdcn\x97\x94_o\x89\x15\xaf\x1dx\xb5\x8c@\x00\x00\xe0\x944\xa8]m$?\xb1\u07f7\xd1\xd2\xd4OSn\x94zL\ue78a\x04<3\xc1\x93ud\x80\x00\x00\u07d44\xa9\x01\xa6\x9f\x03k\u03dfxC\xc0\xba\x01\xb4&\xe8\xc3\xdc+\x89\xd8\xd7&\xb7\x17z\x80\x00\x00\u07d44\xb4TAn\x9f\xb4'Nj\xdd\xf8SB\x8a\x01\x98\xd6.\xe1\x89\x16\x10Bw\x9f\x1f\xfc\x00\x00\u07d44\xc8\xe5\xf13\x0f\xcbK\x14\xcau\xcb%\x80\xa4\xb9= N6\x89lk\x93[\x8b\xbd@\x00\x00\xe0\x944\u211b\xeaX:\xb0\xcc7\x97Q\x90\xf3\"\xb3\x95\x05U\x82\x8a\x01\xa5\xc5\xe8W\xfd\xf2\xb2\x00\x00\u07d44\xfaw\x92\xba\u063b\xd7\xffd\x05b\x14\xa3>\xb6`\f\x1e\xa8\x89\x02\xb5\xe3\xaf\x16\xb1\x88\x00\x00\u07d44\xff&\xeb`\xa8\u0469ZH\x9f\xae\x13n\xe9\x1dNX\bL\x89 \x86\xac5\x10R`\x00\x00\u07d44\xffX)R\xff$E\x8f{\x13\xd5\x1f\vO\x98p\"\xc1\xfe\x89\x98\x06\xde=\xa6\xe9x\x00\x00\u07d45\x10k\xa9N\x85c\u0533\xcb<\\i,\x10\xe6\x04\xb7\xce\u0609lk\x93[\x8b\xbd@\x00\x00\xe0\x945\x14_b\x03\x97\u019c\xb8\xe0\tb\x96\x1f\x0fH\x86d9\x89\x8a\x01EB\xba\x12\xa37\xc0\x00\x00\u07d45\x14t0\xc3\x10e\x00\u77e2\xf5\x02F.\x94p<#\xb1\x89lj\xccg\u05f1\xd4\x00\x00\xe0\x945\x17\x87\x845\x05\xf8\xe4\xef\xf4ef\xcc\u695fM\x1c_\xe7\x8a\x01\xf5q\x89\x87fKH\x00\x00\xe0\x945\x1f\x16\xe5\xe0sZ\xf5gQ\xb0\xe2%\xb2B\x11q9@\x90\x8a\x02\xd4\xca\x05\xe2\xb4<\xa8\x00\x00\xe0\x945$\xa0\x00#N\xba\xaf\a\x89\xa14\xa2\xa4\x178<\xe5(*\x8a\x011yU\x94}\x8e,\x00\x00\u07d45&\xee\xce\x1ak\xdc>\xe7\xb4\x00\xfe\x93[HF?1\xbe\u05c9\x04w\x87\x9bm\x140\x00\x00\u07d45*x_J\x92\x162PL\xe5\xd0\x15\xf8<I\xaa\x83\x8dm\x89\xe9\xe7\xe0\xfb5\xb7x\x00\x00\xe0\x945-)\xa2n\x8aA\x81\x81\x81tdg\xf5\x82\xe6\xe8@\x12\xe0\x8a\x01EB\xba\x12\xa37\xc0\x00\x00\u07d45.w\xc8ain\xf9j\xd5I4\xf8\x94\xaa\x8e\xa3QQ\u074965\u026d\xc5\u07a0\x00\x00\xe0\x945/%\xba\xbfJi\x06s\xe3Q\x95\xef\xa8\xf7\x9d\x05\x84\x8a\xad\x8a\x0e%<9\xben}\xc0\x00\x00\u07d456E3\"\xc1Fl\xb9\x05\xaf\\3\\\xa8\xdbt\xbf\xf1\xe6\x89\x18;_\x03\xb1G\x9c\x00\x00\u07d45=\xbe\xc4/\x92\xb5\x0f\x97Q)\xb9<L\x99su\xf0\x90s\x89l]\xb2\xa4\xd8\x15\xdc\x00\x00\u07d45@\u01fdz\x84B\u057e\xe2\x1a!\x80\xa1\xc4\xed\xff\x16I\xe0\x89C.\xacLo\x05\xb9\x80\x00\u07d45I\xbd@\xbb\xbc+0\t\\\xac\x8b\xe2\xc0z\x05\x88\xe0\xae\u0589\x01\x15\x8eF\t\x13\xd0\x00\x00\u07d45R\xa4\x96\xeb\xa6\u007f\x12\xben\xed\xab6\f\xd16a\xdct\x80\x89\x10CV\x1a\x88)0\x00\x00\u07d45T\x94{{\x94{\x00@\xdaR\xca\x18\t%\xc6\u04f8\x8f\xfe\x89\x03\x9f\xba\xe8\xd0B\xdd\x00\x00\u07d45\\\f9\xf5\xd5p\vA\xd3u\xb3\xf1xQ\xdc\xd5$\x01\xf9\x89\u05f3\xb7\xbaZ\xbfL\x00\x00\u07d45\\\xcf\xe0\xe7}U{\x97\x1b\xe1\xa5X\xbc\x02\u07de\xee\x05\x94\x89_\\\xb1\xaf\xc8e(\x00\x00\xe0\x945q\xcfz\xd3\x04\xec\xae\xe5\x95y/K\xbf\xa4\x84A\x85I\u058a\x01;\xcd\r\x89-\x9e\x16\x00\x00\u07d45u\xc7pf\x8a\x9d\x17\x9f\x1e\xf7h\u0093\xf8\x01f\xe2\xaa=\x89\x19\xb2\x12H\xa3\xef(\x00\x00\u07d45z\x02\xc0\xa9\xdf\xe2\x87\xdeD\u007f\xb6zp\xec[b6fG\x89\x01s\x17\x90SM\xf2\x00\x00\u07d45\x85^\xc6A\xab\x9e\b\x1e\xd0\u00a6\xdc\xd8\x13T\xd0$J\x87\x89A'\xab\u94e7\xaa\x80\x00\u07d45\x88\x89Z\xc9\xfb\xaf\xec\x01 \x92\xdc\x05\xc0\xc3\x02\xd9\a@\xfa\x89\xa2\xa1]\tQ\x9b\xe0\x00\x00\u07d45\x99I<\xe6Wr\u03d3\xe9\x8a\xf1\x19^\xc0\x95]\u0240\x02\x89QQY\fg\xb3(\x00\x00\xe0\x945\xa0\x80\x81y\x91s\xe0\x01\xcc[\xd4j\x02@m\xc9]\x17\x87\x8a\x02\x1e\x19\xe0\u027a\xb2@\x00\x00\u07d45\xa5I\xe8\xfdl6\x8dm\u0326\xd2\xe7\u044eM\xb9_R\x84\x89\x1b\x1a\b\x927\a=\x00\x00\u07d45\xa6\x88P\x83\u0219\u06bb\xf50\xedl\x12\xf4\xdd: L\xf5\x89\n\u05ce\xbcZ\xc6 \x00\x00\u07d45\xaa\xa0F]\x1c&\fB\x0f\xa3\x0e&)\x86\x9f\xb6U\x92\a\x89&7\x81\xe0\xe0\x87\xc8\x00\x00\u07d45\xac\x1d>\xd7FO\xa3\xdb\x14\xe7r\x92\x13\u03aa7\x8c\t^\x89Rf<\u02b1\xe1\xc0\x00\x00\u07d45\xaf\x04\n\f\xc23zv\xaf(\x81T\xc7V\x1e\x1a#3I\x8965\u026d\xc5\u07a0\x00\x00\u07d45\xb0>\xa4$W6\xf5{\x85\xd2\xebyb\x8f\x03m\xdc\xd7\x05\x89\xd8\xd7&\xb7\x17z\x80\x00\x00\u07d45\xbd$he\xfa\xb4\x90\xac\bz\xc1\xf1\xd4\xf2\xc1\r\f\xda\x03\x89\x15\xaf\x1dx\xb5\x8c@\x00\x00\xe0\x945\xbff\x88R/5Fz\u007fu0#\x14\xc0+\xa1v\x80\x0e\x8a\x03\xafA\x82\x02\xd9T\xe0\x00\x00\u07d45\u022d\xc1\x11%C+;w\xac\xd6F%\xfeX\xeb\xee\x9df\x89lk\x93[\x8b\xbd@\x00\x00\u07d45\u0497\x0fI\xdc\xc8\x1e\xa9\xeep~\x9c\x8a\n\xb2\xa8\xbbtc\x89N\x10\x03\xb2\x8d\x92\x80\x00\x00\u07d45\xe0\x96\x12\r\xea\xa5\xc1\xec\xb1d^,\u02cbN\xdb\xd9)\x9a\x89\x1b\x1a\xe4\xd6\xe2\xefP\x00\x00\u07d45\xea!c\xa3\x8c\u07da\x12?\x82\xa5\xec\x00%\x8d\xae\v\xc7g\x89\xd8\xd7&\xb7\x17z\x80\x00\x00\u07d45\xf1\xda\x12{\x837o\x1b\x88\xc8*3Y\xf6z^g\xddP\x89g\x8a\x93 b\xe4\x18\x00\x00\u07d45\xf2\x94\x9c\xf7\x8b\xc2\x19\xbbO\x01\x90|\xf3\xb4\xb3\u04c6T\x82\x89\x0f\xb5\xc8l\x92\xe44\x00\x00\u07d45\xf5\x86\x01I\xe4\xbb\xc0K\x8a\u0172r\xbeU\xad\x1a\xcaX\xe0\x89\n\u05ce\xbcZ\xc6 \x00\x00\u07d46\x02E\x8d\xa8omj\x9d\x9e\xb0=\xaf\x97\xfeV\x19\xd4B\xfa\x89lk\x93[\x8b\xbd@\x00\x00\u07d46\x057-\x93\xa9\x01\t\x88\x01\x8f\x9f1]\x03.\u0448\x0f\xa1\x89\x1b\x1b\xcfQ\x89j}\x00\x00\u07d46\x16\xd4H\x98_]2\xae\xfa\x8b\x93\xa9\x93\xe0\x94\xbd\x85I\x86\x89\v\"\u007fc\xbe\x81<\x00\x00\u07d46\x16\xfbF\xc8\x15x\xc9\xc8\xebM;\xf8\x80E\x1a\x887\x9d}\x89\n\u05ce\xbcZ\xc6 \x00\x00\u07d46\x1cu\x93\x16\x96\xbc=B}\x93\xe7lw\xfd\x13\xb2A\xf6\xf4\x89\x1d\xc5\xd8\xfc&m\xd6\x00\x00\u07d46\x1d\x9e\xd8\v[\xd2|\xf9\xf1\"o&u2X\xee_\x9b?\x89\xbfi\x14\xba}r\xc2\x00\x00\u07d46\x1f;\xa9\xed\x95kw\x0f%}6r\xfe\x1f\xf9\xf7\xb0$\f\x89 \x86\xac5\x10R`\x00\x00\u07d46\"|\u07e0\xfd;\x9d~jtF\x85\xf5\xbe\x9a\xa3f\xa7\xf0\x89\n\xc2s\x0e\xe9\xc6\xc1\x80\x00\u07d46/\xbc\xb1\x06b7\n\x06\x8f\xc2e&\x02\xa2Wy7\xcc\xe6\x89\n\u05ce\xbcZ\xc6 \x00\x00\u07d460\xc5\xe5e\u03aa\x8a\x0f\x0f\xfe2\x87^\xae*l\xe6<\x19\x89\t7r+7t\xd0\x00\x00\u07d463\x9f\x84\xa5\u00b4L\xe5=\xfd\xb6\xd4\xf9}\xf7\x82\x12\xa7\u07c9\x11o\x18\xb8\x17\x15\xa0\x00\x00\u07d464:\xec\xa0{n\u054a\x0eb\xfaN\xcbI\x8a\x12O\xc9q\x89\x10CV\x1a\x88)0\x00\x00\u07d46au@4\x81\xe0\xab\x15\xbbQF\x15\u02f9\x89\xeb\u018f\x82\x89lk\x93[\x8b\xbd@\x00\x00\u07d46ro;\x88Z$\xf9)\x96\u0681b^\u022d\x16\xd8\xcb\xe6\x89S\xafu\u0441HW\x80\x00\xe0\x946s\x95C\x99\xf6\u07feg\x18\x18%\x9b\xb2x\xe2\xe9.\xe3\x15\x8a*Z\x05\x8f\u0095\xed\x00\x00\x00\u07d46u\x8e\x04\x9c\u064b\u03a1\"w\xa6v\xf9)sb\x89\x00#\x89\xd8\xd7&\xb7\x17z\x80\x00\x00\u07d46\u007fY\u0302yS)8NA\xe1(1\x15\xe7\x91\xf2j\x01\x89lk\x93[\x8b\xbd@\x00\x00\u07d46\x81\x0f\xf9\xd2\x13\xa2q\xed\xa2\xb8\xaay\x8b\xe6T\xfaK\xbe\x06\x89lk\x93[\x8b\xbd@\x00\x00\u07d46\x8cT\x14\xb5k\x84U\x17\x1f\xbf\ab \xc1\u02e4\xb5\xca1\x89\x1e>\xf9\x11\xe8=r\x00\x00\xe0\x946\x90$k\xa3\xc8\x06y\xe2.\xacD\x12\xa1\xae\xfc\xe6\xd7\u0342\x8a\x04<3\xc1\x93ud\x80\x00\x00\u07d46\x92\x8bU\xbc\x86\x15\t\xd5\x1c\x8c\xf1\xd5F\xbf\xecn>\x90\xaf\x89j\xcb=\xf2~\x1f\x88\x00\x00\u07d46\x98\"\xf5W\x8b@\xdd\x1fDqpk\"\u0357\x13R\xdak\x89\x12\xc1\xb6\xee\xd0=(\x00\x00\u07d46\x9e\xf7a\x19_:7>$\xec\xe6\xcd\"R\x0f\xe0\xb9\xe8n\x89\x1c\xff\xaf\xc9M\xb2\b\x80\x00\u07d46\xa0\x8f\xd6\xfd\x1a\xc1|\xe1^\xd5~\xef\xb1*+\u2048\xbf\x89Hz\x9a0E9D\x00\x00\u07d46\xa0\xe6\x1e\x1b\xe4\u007f\xa8~0\xd3(\x88\xee\x030\x90\x1c\xa9\x91\x89\x01\x15\x8eF\t\x13\xd0\x00\x00\xe0\x946\xb2\xc8^:\xee\xeb\xb7\rc\u0124s\f\xe2\xe8\xe8\x8a6$\x8a\x02\x1e\x19\xe0\u027a\xb2@\x00\x00\xe0\x946\xbfC\xff5\u07d0\x90\x88$3l\x9b1\xce3\x06~/P\x8aIr\x15\x10\xc1\xc1\xe9H\x00\x00\u07d46\xbf\xe1\xfa;{p\xc1r\xeb\x04/h\x19\xa8\x97%\x95A>\x8965\u026d\xc5\u07a0\x00\x00\xe0\x946\xc5\x10\xbf\x8dnV\x9b\xf2\xf3}G&]\xbc\xb5\x02\xff+\u038a\x06ZM\xa2]0\x16\xc0\x00\x00\xe0\x946\xd8]\xc3h1V\xe6;\xf8\x80\xa9\xfa\xb7x\x8c\xf8\x14:'\x8a\x04<3\xc1\x93ud\x80\x00\x00\u07d46\u07cf\x88<\x12s\xec\x8a\x17\x1fz3\xcf\xd6I\xb1\xfe`u\x89\fRHJ\xc4\x16\x89\x00\x00\xe0\x946\xe1Va\f\xd8\xffd\xe7\x80\u061d\x00T8\\\xa7gU\xaa\x8a\x02\xf6\xf1\a\x80\xd2,\xc0\x00\x00\u07d46\xfe\xc6,,B^!\x9b\x18D\x8a\xd7W\x00\x9d\x8cT\x02o\x89\x15\xaf\x1dx\xb5\x8c@\x00\x00\u07d47\x00\xe3\x02t$\xd99\xdb\xde]B\xfbx\xf6\xc4\xdb\xec\x1a\x8f\x89\x02+\x1c\x8c\x12'\xa0\x00\x00\u07d47\x02\xe7\x04\xcc!at9\xadN\xa2zW\x14\xf2\xfd\xa1\xe92\x8965\u026d\xc5\u07a0\x00\x00\u07d47\x035\fMo\xe374,\xdd\xc6[\xf1\xe28k\xf3\xf9\xb2\x89m\x81!\xa1\x94\xd1\x10\x00\x00\xe0\x947\b\xe5\x9d\xe6\xb4\x05P\x88x)\x02\xe0W\x9cr\x01\xa8\xbfP\x8a*Z\x05\x8f\u0095\xed\x00\x00\x00\u07d47\x126~^U\xa9mZ\x19\x16\x8fn\xb2\xbc~\x99q\xf8i\x8965\u026d\xc5\u07a0\x00\x00\u07d47\x19Zc]\xccb\xf5jq\x80I\xd4~\x8f\x9f\x96\x83(\x91\x89j\xcb=\xf2~\x1f\x88\x00\x00\u07d47'4\x1f&\xc1 \x01\xe3x@^\xe3\x8b-\x84d\xecq@\x89lk\x93[\x8b\xbd@\x00\x00\u07d47.E:kb\x9f'g\x8c\u022e\xb5\xe5|\xe8^\xc0\xae\xf9\x89\n\u05ce\xbcZ\xc6 \x00\x00\u07d474\xcb\x18t\x91\xed\xe7\x13\xae[;-\x12(J\xf4k\x81\x01\x89\xa2\xa1]\tQ\x9b\xe0\x00\x00\u07d477!n\xe9\x1f\x17w2\xfbX\xfa@\x97&r\a\xe2\xcfU\x89Rf<\u02b1\xe1\xc0\x00\x00\u07d47<T~\f\xb5\xcec.\x1cZ\xd6aUr\f\x01\xc4\t\x95\x89\xfeT\xdc\xdc\xe6\xc5Z\x00\x00\u07d47l\xd7Ws\x83\xe9\x02\x95\x1b`\xa2\x01{\xa7\xea)\xe35v\x89lk\x93[\x8b\xbd@\x00\x00\u07d47\x8e\xa1\u070e\xdc\x19\xba\xe8&8\x02\x9e\xa8u,\xe9\x8b\xcf\u0349lk\x93[\x8b\xbd@\x00\x00\u07d47\x8f7$??\xf0\xbe\xf5\xe1\u0705\xebC\b\xd94\f)\xf9\x89lnY\xe6|xT\x00\x00\u07d47\x95\x9c \xb7\xe9\x93\x1dr\xf5\xa8\xae\x86\x9d\xaf\u076d;m\\\x89\n\u05ce\xbcZ\xc6 \x00\x00\u07d47\x9a\u007fuZ\x81\xa1~\xdb}\xaa\xa2\x8a\xfcf]\xfak\xe6:\x89\x01Z\xf1\u05cbX\xc4\x00\x00\u07d47\x9cqf\x84\x9b\xc2J\x02\xd6S^-\xef\x13\xda\xee\xf8\xaa\x8d\x89\x05k\xc7^-c\x10\x00\x00\xe0\x947\xa0Z\u03b99\\\x865\xa3\x9a|]&j\xe6\x10\xd1\v\xf2\x8a\x06ZM\xa2]0\x16\xc0\x00\x00\u07d47\xa1\x04Q\xf3af\xcfd=\xd2\xdel\x1c\xbb\xa8\xa0\x11\u03e3\x89\x14\x99\x8f2\xacxp\x00\x00\u07d47\xa7\xa6\xffN\xa3\xd6\x0e\xc3\a\xcaQjH\xd3\x05;\xb7\x9c\xbb\x89lk\x93[\x8b\xbd@\x00\x00\xe0\x947\xabf\b:O\xa28H\xb8\x86\xf9\xe6my\xcd\xc1P\xccp\x8a\x12\xbe\"\xff\xb5\xec\x008\x00\x00\u07d47\xac)\xbd\xa9?I{\u012e\xaa\xb95E,C\x15\x104\x1e\x895e\x9e\xf9?\x0f\xc4\x00\x00\u07d47\xb8\xbe\xac{\x1c\xa3\x88)\xd6\x1a\xb5R\xc7f\xf4\x8a\x10\xc3/\x89\x15\xaf\x1dx\xb5\x8c@\x00\x00\u07d47\xbb\xc4r\x12\xd8/\xcb^\xe0\x8fR%\xec\xc2\x04\x1a\xd2\xda}\x89\xb1\xcf$\xdd\u0431@\x00\x00\u07d47\u02c6\x8d,?\x95\xb2Wa\x1e\xb3JA\x88\u054bt\x98\x02\x89lk\x93[\x8b\xbd@\x00\x00\u07d47\u0640\xa1.\xe3\xbf#\xcc\\\xdbc\xb4\xaeEi\x1ft\xc87\x89lk\x93[\x8b\xbd@\x00\x00\u07d47\xe1i\xa98\b\xd8\x03V\x98\xf8\x15\xc7#V\x13\xc1\xe6Y\xf2\x8965\u026d\xc5\u07a0\x00\x00\u07d47\xea\u0693\xc4u\xde\xd2\xf7\xe1^w\x87\xd4\x00G\x0f\xa5 b\x89\n\u05ce\xbcZ\xc6 \x00\x00\u07d47\xfa\xc1\xe6\xbc\x12.\x93m\xfb\x84\xde\fK\xefn\r`\xc2\u05c9lk\x93[\x8b\xbd@\x00\x00\u07d48\a\xef\xf4:\xa9|v\x91\n\x19u-\xd7\x15\xee\x01\x82\xd9N\x89\r\x90\x15oo\xc2\xfb\x00\x00\u07d48\x15\xb0t?\x94\xfc\x8c\xc8eO\xd9\u0557\xed}\x8bw\xc5~\x89(\t\xd4)\u0616u\x00\x00\xe0\x948\x1d\xb4\xc8F]\xf4F\xa4\xce\x15\xbf\x81\xd4~/\x17\u0240\xbf\x8a\x06\u01b95\xb8\xbb\xd4\x00\x00\x00\u07d48 ,\\\xd7\a\x8dO\x88vs\xab\a\x10\x9a\u062d\xa8\x97 \x8965\u026d\xc5\u07a0\x00\x00\u07d48!\x86$\x93$,\n\ub139\r\xe0]%\f\x1eP\xc0t\x89\x11wlX\xe9F\xdc\x00\x00\xe0\x948%\x91\xe7!{C^\x8e\x88L\xdb\xf4\x15\xfe7zo\u278a\x01\xb2\u07dd!\x9fW\x98\x00\x00\u07d48+\xa7m\xb4\x1bu`m\u050aH\xf0\x13~\x91t\xe01\xb6\x89\x01\x15\x8eF\t\x13\xd0\x00\x00\u07d481u~\xaeuW\u02ca7\xa4\xb1\x06D\xb6>M;<u\x89\n\u05ce\xbcZ\xc6 \x00\x00\xe0\x9483\x04\xddzW \xb2\x9c\x1a\x10\xf6\x03B!\x9fH\x03/\x80\x8a\x01/\x93\x9c\x99\xed\xab\x80\x00\x00\xe0\x948:|\x89\x9e\xe1\x8b\xc2\x14\x96\x98p\xbct\x82\xf6\xd8\xf3W\x0e\x8a\x02\x1e\x19\xe0\u027a\xb2@\x00\x00\xe0\x948C\x0e\x93\x1d\x93\xbe\x01\xb4\xc3\xef\r\xc55\xf1\xe0\xa9a\x00c\x8a\x02\x1e\x19\xe0\u027a\xb2@\x00\x00\u07d48C\x9a\xaa$\xe3co:\x18\xe0 \xea\x1d\xa7\xe1E\x16\r\x86\x89\x8c\xf2?\x90\x9c\x0f\xa0\x00\x00\u07d48E\x8e\x06\x85W<\xb4\u048fS\t\x88)\x90Ep\x17\x92f\x89\x02+\x1c\x8c\x12'\xa0\x00\x00\u07d48Gfp8\xf3;\x01\xc1\xccy]\x8d\xafTu\xef\xf5\xa0\u0509'{\x9b\xf4$lA\x00\x00\u07d48d;\xab\xea`\x111l\u01d7\u0670\x93\u0217\xa1{\xda\xe7\x89\x12 \xbbtE\u06a0\x00\x00\u07d48i_\xc7\xe16|\xeb\x16>\xbb\x057Q\xf9\xf6\x8d\xdb\a\xa0\x89lk\x93[\x8b\xbd@\x00\x00\u07d48r\xf4\x8d\xc5\xe3\xf8\x17\xbck*\xd2\xd00\xfc^\x04q\x19=\x89\xd8\xd7&\xb7\x17z\x80\x00\x00\u07d48~\xea\xfdk@\t\u07af\x8b\u0578Zr\x98:\x8d\xcc4\x87\x89\xd8\xd7&\xb7\x17z\x80\x00\x00\u07d48\x81\xde\xfa\xe1\xc0{<\xe0Lx\xab\xe2k\f\u070ds\xf0\x10\x89\n\u05ce\xbcZ\xc6 \x00\x00\u07d48\x83\xbe\xcc\b\xb9\xbeh\xad;\b6\xaa\u00f6 \xdc\x00\x17\xef\x89lk\x93[\x8b\xbd@\x00\x00\u07d48\x85\xfe\xe6q\a\xdc:<t\x1e\xe2\x90\u0249\x18\u0279\x93\x97\x89\x01\x15\x8eF\t\x13\xd0\x00\x00\u07d48\x87\x19,\u007fpP\x06\xb60\t\x12v\xb3\x9a\u0180D\x8dk\x89\x03@\xaa\xd2\x1b;p\x00\x00\u07d48\x89\x8b\xbbES\xe0\v\xbf\xd0\xcf&\x8b/\xc4d\xd1T\xad\u0549\x11X\xe4`\x91=\x00\x00\x00\u07d48\x8b\xdc\xda\xe7\x94\xfcD\b.fu\x014A\x18\xea\x96\u0356\x89Z\x87\xe7\xd7\xf5\xf6X\x00\x00\u07d48\x8c\x85\xa9\xb9 }\x81F\x03?\xe3\x81C\xf6\xd3KY\\G\x89\n\u05ce\xbcZ\xc6 \x00\x00\u07d48\x96\xadt5y\u04ce#\x02EM\x1f\xb6\xe2\xabi\xe0\x1b\xfd\x89e\xea=\xb7UF`\x00\x00\u07d48\xa3\xdc\xcf/\xcf\xe0\xc9\x1a&$\xbd\f\xbf\x88\xeeJ\al3\x89lk\x93[\x8b\xbd@\x00\x00\u07d48\xa7D\xef\xa6\xd5\xc2\x13}\xef\xef\x8e\xf9\x18{d\x9e\xee\x1cx\x89\xd8\xd7&\xb7\x17z\x80\x00\x00\u07d48\xacfN\xe8\xe0y^Bu\u02c5+\u02e6\xa4y\xad\x9c\x8d\x89\x01\x15\x8eF\t\x13\xd0\x00\x00\u07d48\xb2\x19q\x06\x123\x87\xa0\xd4\xde6\x841\xa8\xba\xcd\xda0\xe2\x89\x01\x15\x8eF\t\x13\xd0\x00\x00\u07d48\xb3\x96\\!\xfa\x8991\a\x9b\xea\xcf\xff\xaf\x156x\xb6\xeb\x89\t<j\nQ\xe2g\x00\x00\u07d48\xb4\x03\xfb\x1f\xb7\xc1EY\xa2\xd6\xf6VJUR\xbc\xa3\x9a\xff\x89lk\x93[\x8b\xbd@\x00\x00\xe0\x948\xb5\x01F\xe7\x19\x16\xa5D\x8d\xe1*Mt!5\xdc\xf3\x983\x8a\x06\u0450\xc4u\x16\x9a \x00\x00\u07d48\xbf*\x1fzi\xde\x0e%F\xad\xb8\b\xb3c5d]\xa9\xff\x89lp\x049\u0675`\x00\x00\xe0\x948\xc1\v\x90\xc8Y\u02f7\x81V\x92\xf9\x9d\xaeR\n\xb5\xfe\xbf^\x8a\x02\xc9\xe4\x96o\xa5\xcf$\x00\x00\u07d48\u01c5\x1f_\xfdL\xee\x98\xdf0\xf3\xb2U\x97\xaf\x8al\xa2c\x89\x8e\xad:/}~\x18\x00\x00\u07d48\xd2\xe9\x15Id\xb4\x1c\x8dP\xa7H}9\x1e~\xe2\xc3\xd3\u0089\xbd\xbcA\xe04\x8b0\x00\x00\xe0\x948\xda\x1b\xa2\u079e,\x95K\t-\xd9\xd8\x12\x04\xfd\x01k\xa0\x16\x8a\x02&\x8e\xd0\x1f4\xb30\x00\x00\u07d48\xdf\fJ\xbe}\xed_\xe0h\xea\xdf\x15J\u0191wC$\xa4\x89a\t=|,m8\x00\x00\u07d48\xe2\xafs9>\xa9\x8a\x1d\x99:t\xdf\\\xd7T\xb9\x8dR\x9a\x89a\t=|,m8\x00\x00\u07d48\xe4m\xe4E<8\xe9A\xe7\x93\x0fC0O\x94\xbb{+\xe8\x89l\xb7\xe7Hg\xd5\xe6\x00\x00\u07d48\xe7\u06e8\xfdO\x1f\x85\r\xbc&I\xd8\xe8O\tR\xe3\xeb<\x89\x02\xb5\xe3\xaf\x16\xb1\x88\x00\x00\u07d48\xe8\xa3\x1a\xf2\xd2e\xe3\x1a\x9f\xff-\x8fF(m\x12E\xa4g\x89\x01\x15\x8eF\t\x13\xd0\x00\x00\u07d48\xeao[Z{\x88AuQ\xb4\x12=\xc1'\xdf\xe94-\xa6\x89\x15\xaf\x1dx\xb5\x8c@\x00\x00\u07d48\xee\xc6\xe2\x17\xf4\xd4\x1a\xa9 \xe4$\xb9RQ\x97\x04\x1c\xd4\u0189\xf0\r%\xeb\x92.g\x00\x00\xe0\x948\xf3\x87\xe1\xa4\xedJs\x10n\xf2\xb4b\xe4t\xe2\xe3\x14:\u040a\x01EB\xba\x12\xa37\xc0\x00\x00\u07d49\x11a\xb0\xe4<0 f\u898d,\xe7\xe1\x99\xec\xdb\x1dW\x89\xd8\xd7&\xb7\x17z\x80\x00\x00\xe0\x949\x15\uad6b.Yw\xd0u\xde\xc4}\x96\xb6\x8bK\\\xf5\x15\x8a\r\a\x01\x81\x85\x12\x0f@\x00\x00\u07d49\x1aw@\\\t\xa7+^\x846#z\xaa\xf9]h\xda\x17\t\x89\x02\xa9&J\xf3\u0479\x00\x00\u07d49\x1f \x17m\x126\rrMQG\n\x90p6uYJM\x89V\xbcu\xe2\xd61\x00\x00\x00\u07d49$3\xd2\u0383\xd3\xfbJv\x02\u0323\xfa\xcaN\xc1@\xa4\xb0\x89\x02\xc3\xc4e\xcaX\xec\x00\x00\xe0\x949?x;\\\u06c6\"\x1b\xf0)O\xb7\x14\x95\x9c{E\x89\x9c\x8a\x01@a\xb9\xd7z^\x98\x00\x00\u07d49?\xf4%^\\e\x8f.\u007f\x10\xec\xbd)%rg\x1b\xc2\u0489lk\x93[\x8b\xbd@\x00\x00\u07d49A2`\x0fAU\xe0\u007fME\xbc>\xb8\xd9\xfbr\xdc\u05c4\x89\x9fn\x92\xed\xea\a\xd4\x00\x00\u07d49Q\xe4\x8e<\x86\x9ekr\xa1C\xb6\xa4Ph\u0379\xd4f\u0409\x01\x15\x8eF\t\x13\xd0\x00\x00\xe0\x949T\xbd\xfe\v\xf5\x87\u0195\xa3\x05\xd9$L=[\xdd\xda\u027b\x8a\x04\x10'\x83'\xf9\x85`\x80\x00\u07d49]m%U \xa8\xdb)\xab\xc4}\x83\xa5\u06ca\x1a}\xf0\x87\x89\x05k\xc7^-c\x10\x00\x00\u07d49ck%\x81\x1b\x17j\xbf\xcf\xee\xcad\xbc\x87E/\x1f\xdf\xf4\x89\x15\xaf\x1dx\xb5\x8c@\x00\x00\u07d49i\xb4\xf7\x1b\xb8u\x1e\xdeC\xc0\x166:zaOv\x11\x8e\x89lk\x93[\x8b\xbd@\x00\x00\xe0\x949x/\xfe\x06\xacx\x82*<:\x8a\xfe0^P\xa5a\x88\u038a\x02\x1e\x19\xe0\u027a\xb2@\x00\x00\u07d49zn\xf8v:\x18\xf0\x0f\xac!~\x05\\\r0\x94\x10\x10\x11\x89lk\x93[\x8b\xbd@\x00\x00\u07d49|\u06cc\x80\xc6yP\xb1\x8deB)a\x0e\x93\xbf\xa6\xee\x1a\x89?\x95\xc8\xe0\x82\x15!\x00\x00\u07d49\x82O\x8b\xce\xd1v\xfd>\xa2.\u01a4\x93\xd0\xcc\xc3?\xc1G\x89\xd8\xd7&\xb7\x17z\x80\x00\x00\u07d49\x93l'\x19E\v\x94 \xcc%\"\u03d1\xdb\x01\xf2'\xc1\xc1\x89\x1b\x1a\xe4\xd6\xe2\xefP\x00\x00\u07d49\x95\xe0\x96\xb0\x8aZrh\x00\xfc\xd1}\x9cd\xc6N\b\x8d+\x89\n\u05ce\xbcZ\xc6 \x00\x00\u07d49\x9a\xa6\xf5\xd0x\xcb\tp\x88+\u0259 \x06\xf8\xfb\xdf4q\x8965\u026d\xc5\u07a0\x00\x00\u07d49\xaa\x05\xe5m}28T!\u03d36\xe9\r=\x15\xa9\xf8Y\x89\x01h\u048e?\x00(\x00\x00\u07d49\xaa\xf0\x85M\xb6\xeb9\xbc{.C\x84jv\x17\x1c\x04E\u0789dI\xe8NG\xa8\xa8\x00\x00\u07d49\xb1\xc4q\xae\x94\xe1!dE.\x81\x1f\xbb\xe2\xb3\xcdru\xac\x89lk\x93[\x8b\xbd@\x00\x00\u07d49\xb2\x992t\x90\xd7/\x9a\x9e\xdf\xf1\x1b\x83\xaf\xd0\xe9\xd3\xc4P\x89\n\u05ce\xbcZ\xc6 \x00\x00\u07d49\xba\u018d\x94xY\xf5\x9e\x92&\b\x9c\x96\xd6.\x9f\xbe<\u0789\x02+\x1c\x8c\x12'\xa0\x00\x00\xe0\x949\xbf\xd9xh\x9b\xec\x04\x8f\xc7v\xaa\x15$\u007f^\x1d|9\xa2\x8a\x04<3\xc1\x93ud\x80\x00\x00\u07d49\xc7s6|\x88%\xd3YlhoB\xbf\r\x141\x9e?\x84\x89\a?u\u0460\x85\xba\x00\x00\u07d49\u05291@,\fy\xc4W\x18o$\u07c7)\u03d5p1\x89\xd8\xd7&\xb7\x17z\x80\x00\x00\u07d49\xd6\xca\xca\"\xbc\xcdjr\xf8~\xe7\u05b5\x9e\v\xde!\xd7\x19\x89l\x87T\xc8\xf3\f\b\x00\x00\u07d49\xe0\xdbM`V\x8c\x80\v\x8cU\x00\x02l%\x94\xf5v\x89`\x8965\u026d\xc5\u07a0\x00\x00\xe0\x949\xeeO\xe0\x0f\xbc\xeddph\xd4\xf5|\x01\xcb\"\xa8\v\xcc\u044a\x01EB\xba\x12\xa37\xc0\x00\x00\u07d49\xf1\x983\x1eK!\xc1\xb7`\xa3\x15_J\xb2\xfe\x00\xa7F\x19\x89lk\x93[\x8b\xbd@\x00\x00\u07d49\xf4Fc\xd9%a\t\x1b\x82\xa7\r\xcfY=u@\x05\x97:\x89\n\u05cb.\xdc!Y\x80\x00\u07d4:\x03U\x94\xc7GGmB\xd1\xee\x96l6\"L\xdd\"I\x93\x89\x13J\xf7Ei\xf9\xc5\x00\x00\u07d4:\x04W(G\xd3\x1e\x81\xf7v\\\xa5\xbf\xc9\xd5W\x15\x9f6\x83\x89\a6-\r\xab\xea\xfd\x80\x00\xe0\x94:\x06\xe3\xbb\x1e\xdc\xfd\fD\xc3\aM\xe0\xbb`k\x04\x98\x94\xa2\x8a\x02\x1e\x19\xe0\u027a\xb2@\x00\x00\u0794:\x10\x88\x8b~\x14\x9c\xae',\x010,2}\n\xf0\x1a\v$\x88\xeb\xec!\xee\x1d\xa4\x00\x00\u07d4:1\b\xc1\u6023;3l!\x13\x134@\x9d\x97\xe5\xad\xec\x89\x01\x15\x8eF\t\x13\xd0\x00\x00\u07d4:6\x8e\xfeJ\u05c6\xe2c\x95\xec\x9f\u01adi\x8c\xae)\xfe\x01\x89\"E\x89\x96u\xf9\xf4\x00\x00\u07d4:=\xd1\x04\xcd~\xb0O!\x93/\xd43\xeaz\xff\u04d3i\xf5\x89\x13aO#\xe2B&\x00\x00\u07d4:B\x97\xda<U^F\xc0sf\x9d\x04x\xfc\xe7_/y\x0e\x89j\xc5\xc6-\x94\x86\a\x00\x00\u07d4:Gk\xd2\xc9\xe6d\xc6:\xb2f\xaaLnJH%\xf5\x16\u00c9\n\u05ce\xbcZ\xc6 \x00\x00\u07d4:H\xe0\xa7\t\x8b\x06\xa9\x05\x80+\x87TW1\x11\x8e\x89\xf49\x89lk\x93[\x8b\xbd@\x00\x00\u07d4:M\xa7\x8d\xce\x05\xae\xb8}\u9bad\x91\x85rm\xa1\x92g\x98\x89\n\u05ce\xbcZ\xc6 \x00\x00\u07d4:Y\xa0\x82F\xa8 o\x8dX\xf7\v\xb1\xf0\xd3\\[\xccq\xbd\x89\n\ad\a\xd3\xf7D\x00\x00\xe0\x94:r\xd65\xaa\xde\xeeC\x824\x9d\xb9\x8a\x18\x13\xa4\xcf\xeb=\xf1\x8a*Z\x05\x8f\u0095\xed\x00\x00\x00\xe0\x94:}\xb2$\xac\xae\x17\xdew\x98y}\x82\xcd\xf8%0\x17\u07e8\x8a\x01\x0f\f\xf0d\xddY \x00\x00\u07d4:\x80_\xa0\xf78\u007fs\x05[xX\u0285\x19\xed\xd9=cO\x89dI\xe8NG\xa8\xa8\x00\x00\xe0\x94:\x84\xe9P\xedA\x0eQ\xb7\xe8\x80\x10I\xab&4\xb2\x85\xfe\xa1\x8a\x03\xf5/\u06a8\"\xd2\xc8\x00\x00\u07d4:\x86\ue506+t=\xd3OA\ti\xd9N,VR\u052d\x89\n\xed\xe6\x9a\xd3\x0e\x81\x00\x00\u07d4:\x912\xb7\t=>\xc4.\x1eO\xb8\xcb1\xec\xddC\xaew<\x89lk\x93[\x8b\xbd@\x00\x00\xe0\x94:\x99`&m\xf6I cS\x8a\x99\xf4\x87\xc9P\xa3\xa5\uc78a\x05\x15\n\xe8J\x8c\xdf\x00\x00\x00\u07d4:\x9b\x11\x10)\xce\x1f \xc9\x10\x9czt\xee\xee\xf3OO.\xb2\x89\xd8\xd7&\xb7\x17z\x80\x00\x00\u07d4:\x9eTA\xd4K$;\xe5[u\x02z\x1c\ub7ac\xf5\r\xf2\x8965\u026d\xc5\u07a0\x00\x00\xe0\x94:\xa0z4\xa1\xaf\u0216}=\x13\x83\xb9kb\u03d6\xd5\xfa\x90\x8a\x04<3\xc1\x93ud\x80\x00\x00\xe0\x94:\xa4,!\xb9\xb3\x1c>'\xcc\xd1~\t\x9a\xf6y\xcd\xf5i\a\x8a\x01\xb1\xaeMn.\xf5\x00\x00\x00\u07d4:\xa9H\xea\x029wU\xef\xfb/\x9d\xc99-\xf1\x05\x8f~3\x89.\x14\x1e\xa0\x81\xca\b\x00\x00\u07d4:\xad\xf9\x8ba\xe5\u0216\xe7\xd1\x00\xa39\x1d2P\"]a\u07c9\f\xafg\x007\x01h\x00\x00\u07d4:\xaeHr\xfd\x90\x93\xcb\xca\xd1@o\x1e\x80x\xba\xb5\x03Y\xe2\x89\x02\"\xc8\xeb?\xf6d\x00\x00\u07d4:\xbb\x8a\xdf\xc6\x04\xf4\x8dY\x84\x81\x1d\u007f\x1dR\xfe\xf6u\x82p\x89\xf2\x97\x19\xb6o\x11\f\x00\x00\u07d4:\xc2\xf0\xff\x16\x12\xe4\xa1\xc3F\xd53\x82\xab\xf6\u0622[\xaaS\x89lk\x93[\x8b\xbd@\x00\x00\u07d4:\xc9\xdczCj\xe9\x8f\xd0\x1cz\x96!\xaa\x8e\x9d\v\x8bS\x1d\x89a\t=|,m8\x00\x00\xe0\x94:\xd0aI\xb2\x1cU\xff\x86|\xc3\xfb\x97@\u04bc\xc7\x10\x121\x8a)\xb7d2\xb9DQ \x00\x00\u07d4:\xd7\x02C\u060b\xf0@\x0fW\xc8\xc1\xfdW\x81\x18H\xaf\x16*\x89.\x9e\xe5\u00c6S\xf0\x00\x00\u07d4:\xd9\x15\xd5P\xb7#AV \xf5\xa9\xb5\xb8\x8a\x85\xf3\x82\xf05\x8965\u026d\xc5\u07a0\x00\x00\u07d4:\xe1`\xe3\xcd`\xae1\xb9\xd6t-h\xe1Nv\xbd\x96\xc5\x17\x89\x01\xa0Ui\r\x9d\xb8\x00\x00\u07d4:\xe6+\xd2q\xa7`c\u007f\xady\xc3\x1c\x94\xffb\xb4\xcd\x12\xf7\x89lk\x93[\x8b\xbd@\x00\x00\u07d4:\xeaN\x82\xd2@\x02H\xf9\x98q\xa4\x1c\xa2W\x06\r:\"\x1b\x8965\u026d\xc5\u07a0\x00\x00\u07d4:\xf6[>(\x89ZJ\x00\x11S9\x1d\x1ei\xc3\x1f\xb9\xdb9\x89\u0556{\xe4\xfc?\x10\x00\x00\u07d4;\a\xdbZ5\u007fZ\xf2HL\xbc\x9dw\xd7;\x1f\xd0Q\x9f\u01c9\x1b\x1a\xe4\xd6\xe2\xefP\x00\x00\u07d4;\n\u032fK`|\xfea\xd1s4\xc2\x14\xb7\\\xde\xfd\xbd\x89\x89lk\x93[\x8b\xbd@\x00\x00\u07d4;\x13c\x1a\x1b\x89\xcbVeH\x89\x9a\x1d`\x91\\\xdc\xc4 [\x89lk\x93[\x8b\xbd@\x00\x00\u07d4;\x15\x90\x99\aR\a\u0180vc\xb1\xf0\xf7\xed\xa5J\xc8\xcc\xe3\x89j\xc4\xe6[i\xf9-\x80\x00\u07d4;\x197\xd5\u74f8\x9bc\xfb\x8e\xb5\xf1\xb1\xc9\xcak\xa0\xfa\x8e\x89lk\x93[\x8b\xbd@\x00\x00\u07d4;\"\xda*\x02q\xc8\xef\xe1\x02S'scji\xb1\xc1~\t\x89\x1b6\xa6DJ>\x18\x00\x00\u07d4;\"\u07a3\xc2_\x1bY\u01fd'\xbb\x91\u04e3\xea\xec\xef9\x84\x89\x05k\xc7^-c\x10\x00\x00\xe0\x94;#g\xf8IK_\xe1\x8dh<\x05]\x89\x99\x9c\x9f=\x1b4\x8a\x02\x1e\x19\xe0\u027a\xb2@\x00\x00\u07d4;,E\x99\x0e!GDQ\xcfOY\xf0\x19U\xb31\xc7\xd7\u0249lk\x93[\x8b\xbd@\x00\x00\xe0\x94;A\x00\xe3\ns\xb0\xc74\xb1\x8f\xfa\x84&\u045b\x191/\x1a\x8a\v\xb5\u046ap\n\xfd\x90\x00\x00\u07d4;B\xa6m\x97\x9fX(4tz\x8b`B\x8e\x9bN\xec\xcd#\x89!\xa1\u01d0\xfa\xdcX\x00\x00\u07d4;Gh\xfdq\xe2\xdb,\xbe\u007f\xa0PH<'\xb4\xeb\x93\x1d\xf3\x89lk\x93[\x8b\xbd@\x00\x00\u07d4;Vj\x8a\xfa\u0456\x82\xdc,\xe8g\x9a<\xe4D\xa5\xb0\xfdO\x89lk\x93[\x8b\xbd@\x00\x00\xe0\x94;\\%\x1d\u007f\u05c9;\xa2\t\xfeT\x1c\xec\xd0\xce%:\x99\r\x8a\x06ZM\xa2]0\x16\xc0\x00\x00\u07d4;^\x8b<w\xf7\x92\xde\xcbz\x89\x85\u07d1n\xfbI\n\xac#\x89lk\x93[\x8b\xbd@\x00\x00\u07d4;n\x81Ow\aH\xa7\u00d9x\x064v\x05H\n?\xd5\t\x89lk\x93[\x8b\xbd@\x00\x00\u07d4;{OS\xc4VU\xf3\xdc_\x01~\xdc#\xb1o\x9b\xc56\xfa\x89\x05k\xc7^-c\x10\x00\x00\xe0\x94;{\x8e'\xde3\xd3\xceya\xb9\x8d\x19\xa5/\xe7\x9fl%\xbe\x8a\x15-\x02\xc7\xe1J\xf6\x80\x00\x00\u07d4;|w\xdb\xe9]\xc2`,\xe3&\x9a\x95E\xd0Ie\xfe\xfd\xbd\x89lk\x93[\x8b\xbd@\x00\x00\u07d4;\x80\x98S?}\x9b\xdc\xd3\a\u06f2>\x17w\xca\x18A\x896\x89lk\x93[\x8b\xbd@\x00\x00\xe0\x94;\x93\xb1a6\xf1\x1e\xaf\x10\x99l\x95\x99\r;'9\xcc\xea_\x8a\x02\x1e\x19\xe0\u027a\xb2@\x00\x00\u07d4;\xabK\x01\xa7\xc8K\xa1?\uea70\xbb\x19\x1bw\xa3\xaa\u0723\x89\n\u05ce\xbcZ\xc6 \x00\x00\u07d4;\xb55\x98\xcc \xe2\x05]\xc5S\xb0I@J\u0277\xdd\x1e\x83\x89!W\x1d\xf7|\x00\xbe\x00\x00\u07d4;\xbc\x13\xd0J\xcc\xc0pz\xeb\u072e\xf0\x87\u0438~\v^\u327e\xd1\xd0&=\x9f\x00\x00\x00\u07d4;\xc6\xe3\xeezV\u038f\x14\xa3u2Y\x0fcqk\x99f\xe8\x89lk\x93[\x8b\xbd@\x00\x00\u07d4;\xc8]ls[\x9c\xdaK\xba_H\xb2K\x13\xe7\x0600{\x89j\xcb=\xf2~\x1f\x88\x00\x00\u07d4;\xd6$\xb5H\xcbe\x976\x90~\u062a<\fp^$\xb5u\x89lk\x93[\x8b\xbd@\x00\x00\u07d4;\u0660m\x1b\xd3lN\xdd'\xfc\r\x1f[\b\x8d\xda\xe3\xc7*\x89\x1b\x1azB\v\xa0\r\x00\x00\u0794;\u077c\x814\xf7}UY\u007f\xc9|&\xd2f\x98\t\x06\x04\ub23e -j\x0e\xda\x00\x00\xe0\x94;\xf8n\u0623\x15>\xc93xj\x02\xac\t\x03\x01\x85^Wk\x8a_J\x8c\x83u\xd1U@\x00\x00\u07d4;\xfb\u04c4|\x17\xa6\x1c\xf3\xf1{R\xf8\ub879`\xb3\U000df262\xa1]\tQ\x9b\xe0\x00\x00\u07d4<\x03\xbb\xc0#\xe1\xe9?\xa3\xa3\xa6\xe4(\xcf\f\xd8\xf9^\x1e\u0189Rf<\u02b1\xe1\xc0\x00\x00\u07d4<\f=\ufb1c\xeaz\xcc1\x9a\x96\xc3\v\x8e\x1f\xed\xabEt\x89i*\xe8\x89p\x81\xd0\x00\x00\u07d4<\x15\xb3Q\x1d\xf6\xf04.sH\u0309\xaf9\xa1h\xb7s\x0f\x8965\u026d\xc5\u07a0\x00\x00\u07d4<\x1f\x91\xf3\x01\xf4\xb5e\xbc\xa2GQ\xaa\x1fv\x13\"p\x9d\u0749a\t=|,m8\x00\x00\xe0\x94<(l\xfb0\x14n_\u05d0\xc2\xc8T\x15RW\x8d\xe34\u060a\x02)\x1b\x11\xaa0n\x8c\x00\x00\u07d4<2.a\x1f\u06c2\rG\xc6\xf8\xfcd\xb6\xfa\xd7L\xa9_^\x89\r%\x8e\xce\x1b\x13\x15\x00\x00\u07d4<Z$\x14Y\u01ab\xbfc\x029\u024a0\xd2\v\x8b:\xc5a\x89\b\x8b#\xac\xff\u0650\x00\x00\u07d4<y\xc8c\xc3\xd3r\xb3\xff\foE'4\xa7\xf9pB\xd7\x06\x89\t\x8a}\x9b\x83\x14\xc0\x00\x00\xe0\x94<\x83\xc1p\x1d\xb08\x8bh!\r\x00\xf5q|\u067d2,j\x8a\x06ZM\xa2]0\x16\xc0\x00\x00\u07d4<\x86\x0e.f?F\xdbSB{)\xfe>\xa5\xe5\xbfb\xbb\u0309\x05V\xf6L\x1f\xe7\xfa\x00\x00\u07d4<\x86\x9c\tie#\xce\xd8$\xa0pAF\x05\xbbv#\x1f\xf2\x8965\u026d\xc5\u07a0\x00\x00\u07d4<\x92V\x19\u02731DF?\x057\u06165\x87\x06\xc5 \xb0\x89lk\x93[\x8b\xbd@\x00\x00\u07d4<\x98YK\xf6\x8bW5\x1e\x88\x14\xae\x9em\xfd-%J\xa0o\x89\x10CV\x1a\x88)0\x00\x00\u07d4<\xad\xeb=>\xed?b1\x1dRU>p\xdfJ\xfc\xe5o#\x89\xd8\xd7&\xb7\x17z\x80\x00\x00\xe0\x94<\xae\xdbS\x19\xfe\x80eC\xc5nP!\xd3r\xf7\x1b\xe9\x06.\x8a\bxg\x83&\xea\xc9\x00\x00\x00\u07d4<\xaf\xaf^bPV\x15\x06\x8a\xf8\xeb\"\xa1:\u0629\xe5Pp\x89lf\x06E\xaaG\x18\x00\x00\u07d4<\xb1y\xcbH\x01\xa9\x9b\x95\u00f0\xc3$\xa2\xbd\xc1\x01\xa6S`\x89\x01h\u048e?\x00(\x00\x00\u07d4<\xb5a\u0386BK5\x98\x91\xe3d\xec\x92_\xfe\xff'}\xf7\x89\n\u05ce\xbcZ\xc6 \x00\x00\u07d4<\xcbq\xaah\x80\xcb\v\x84\x01-\x90\xe6\a@\xec\x06\xac\u05cf\x89lk\x93[\x8b\xbd@\x00\x00\u07d4<\xce\xf8\x86yW9G\xe9I\x97y\x8a\x1e2~\b`:e\x89+\xc9\x16\u059f;\x02\x00\x00\xe0\x94<\xd1\xd9s\x1b\xd5H\xc1\xddo\u03a6\x1b\xebu\xd9\x17T\xf7\u04ca\x01\x16\x1d\x01\xb2\x15\xca\xe4\x80\x00\u07d4<\u04e6\xe95y\xc5mIAq\xfcS>z\x90\xe6\xf5\x94d\x89lk\x93[\x8b\xbd@\x00\x00\u07d4<\u05b7Y<\xbe\xe7x0\xa8\xb1\x9d\b\x01\x95\x8f\xcdK\xc5z\x89\x1b\x1a\xe4\xd6\xe2\xefP\x00\x00\u07d4<\xd7\xf7\xc7\xc257\x80\xcd\xe0\x81\xee\xecE\x82+%\xf2\x86\f\x89\n\u05ce\xbcZ\xc6 \x00\x00\u07d4<\xe1\u0717\xfc\u05f7\xc4\u04e1\x8aI\xd6\xf2\xa5\xc1\xb1\xa9\x06\u05c9\n\u05ce\xbcZ\xc6 \x00\x00\u07d4<\xea0*G*\x94\x03y\xdd9\x8a$\xea\xfd\xba\u07c8\xady\x89\xa2\xa1]\tQ\x9b\xe0\x00\x00\xe0\x94<\xec\xa9k\xb1\xcd\xc2\x14\x02\x9c\xbc^\x18\x1d9\x8a\xb9M=A\x8a\x10\xf0\xcf\x06M\u0552\x00\x00\x00\u07d4<\xf4\x84RO\xbd\xfa\xda\xe2m\xc1\x85\xe3++c\x0f\xd2\xe7&\x89\x18TR\xcb*\x91\xc3\x00\x00\u07d4<\xf9\xa1\xd4e\xe7\x8bp9\xe3iDx\xe2b{6\xfc\xd1A\x89J`S*\xd5\x1b\xf0\x00\x00\u07d4<\xfb\xf0fVYpc\x9e\x13\r\xf2\xa7\xd1k\x0e\x14\xd6\t\x1c\x89\\(=A\x03\x94\x10\x00\x00\xe0\x94=\th\x8d\x93\xad\a\xf3\xab\xe6\x8cr'#\xcdh\t\x90C^\x8a\x06ZL\xe9\x9fv\x9en\x00\x00\u07d4=1X{_\u0546\x98Ex\x87%\xa6c)\nI\xd3g\x8c\x89\x1b\x1a\xe4\xd6\xe2\xefP\x00\x00\u07d4=?\xadI\xc9\xe5\xd2u\x9c\x8e\x8eZzM`\xa0\xdd\x13V\x92\x89\x01\x15\x8eF\t\x13\xd0\x00\x00\u07d4=WO\xcf\x00\xfa\xe1\u064c\u023f\x9d\u07e1\xb3\x95;\x97A\xbc\x89j\xcb=\xf2~\x1f\x88\x00\x00\u07d4=Z\x8b+\x80\xbe\x8b5\xd8\xec\xf7\x89\xb5\xedz\au\xc5\al\x89\x01\x15\x8eF\t\x13\xd0\x00\x00\u07d4=f\xcdK\xd6M\\\x8c\x1b^\xea(\x1e\x10m\x1cZ\xad#s\x89i\xc4\xf3\xa8\xa1\x10\xa6\x00\x00\u0794=j\xe0S\xfc\xbc1\x8do\xd0\xfb\xc3S\xb8\xbfT.h\r'\x88\xc6s\xce<@\x16\x00\x00\u07d4=o\xf8,\x93w\x05\x9f\xb3\r\x92\x15r?`\xc7u\u0211\xfe\x89\r\x8e\\\xe6\x17\xf2\xd5\x00\x00\u07d4=y\xa8S\xd7\x1b\xe0b\x1bD\xe2\x97Yel\xa0u\xfd\xf4\t\x89lk\x93[\x8b\xbd@\x00\x00\u07d4=~\xa5\xbf\x03R\x81\x00\xed\x8a\xf8\xae\xd2e>\x92\x1bng%\x8965\u026d\xc5\u07a0\x00\x00\u07d4=\x81?\xf2\xb6\xedW\xb97\u06bf+8\x1d\x14\x8aA\x1f\xa0\x85\x89\x05k\xc7^-c\x10\x00\x00\u07d4=\x88\x143\xf0J}\r'\xf8ID\xe0\x8aQ-\xa3UR\x87\x89A\rXj \xa4\xc0\x00\x00\u07d4=\x89\xe5\x05\xcbF\xe2\x11\xa5?2\xf1g\xa8w\xbe\xc8\u007fK\n\x89\x01[5W\xf1\x93\u007f\x80\x00\xe0\x94=\x8d\a#r\x1es\xa6\xc0\xd8`\xaa\x05W\xab\xd1L\x1e\xe3b\x8a\x01\x0f\f\xf0d\xddY \x00\x00\u07d4=\x8f9\x88\x1b\x9e\xdf\xe9\x12'\xc3?\xa4\xcd\xd9\x1eg\x85D\xb0\x89\x04\xab\a\xbaC\xad\xa9\x80\x00\u07d4=\x9dk\xe5\u007f\xf8>\x06Y\x85fO\x12VD\x83\xf2\xe6\x00\xb2\x89n\xac\xe4?#\xbd\x80\x00\x00\u07d4=\xa3\x9c\xe3\xefJz9f\xb3.\xe7\xeaN\xbc#5\xa8\xf1\x1f\x89lk\x93[\x8b\xbd@\x00\x00\u07d4=\xaa\x01\u03b7\x0e\xaf\x95\x91\xfaR\x1b\xa4\xa2~\xa9\xfb\x8e\xdeJ\x89Zc\xd2\u027cvT\x00\x00\u07d4=\xb5\xfejh\xbd6\x12\xac\x15\xa9\x9aa\xe5U\x92\x8e\xec\xea\xf3\x89U\xa6\xe7\x9c\xcd\x1d0\x00\x00\u07d4=\xb9\xed\u007f\x02L~&7/\xea\xcf+\x05\b\x03D^8\x10\x89E\xb1H\xb4\x99j0\x00\x00\u07d4=\xbf\r\xbf\xd7x\x90\x80\x053\xf0\x9d\xea\x83\x01\xb9\xf0%\u04a6\x8965\u026d\xc5\u07a0\x00\x00\u07d4=\xce\U0005c18b\x15\xd3N\xdaBn\xc7\xe0K\x18\xb6\x01p\x02\x89lh\xcc\u041b\x02,\x00\x00\xe0\x94=\xd1.Uj`76\xfe\xbaJo\xa8\xbdJ\xc4]f*\x04\x8a#u{\x91\x83\xe0x(\x00\x00\u07d4=\u078b\x15\xb3\u033a\xa5x\x01\x12\xc3\xd6t\xf3\x13\xbb\xa6\x80&\x89`\x1dQZ>O\x94\x00\x00\xe0\x94=\xde\xdb\xe4\x89#\xfb\xf9\xe56\xbf\x9f\xfb\aG\xc9\xcd\u04de\xef\x8a\x03h\xc8b:\x8bM\x10\x00\x00\u07d4=\xea\xe43'\x91?b\x80\x8f\xaa\x1bbv\xa2\xbdch\xea\u0649lk\x93[\x8b\xbd@\x00\x00\u07d4=\xf7b\x04\x9e\u068a\u0192}\x90Lz\xf4/\x94\xe5Q\x96\x01\x89lk\x93[\x8b\xbd@\x00\x00\u07d4>\x04\r@\u02c0\xba\x01%\xf3\xb1_\xde\xfc\xc8?0\x05\xda\x1b\x898E$\xccp\xb7x\x00\x00\u07d4>\v\x8e\xd8n\xd6i\xe1'#\xafur\xfb\xac\xfe\x82\x9b\x1e\x16\x89QM\xe7\xf9\xb8\x12\xdc\x00\x00\xe0\x94>\f\xbejm\xcba\xf1\x10\xc4[\xa2\xaa6\x1d\u007f\xca\xd3\xdas\x8a\x01\xb2\u07dd!\x9fW\x98\x00\x00\u07d4>\x19KN\xce\xf8\xbbq\x1e\xa2\xff$\xfe\xc4\xe8{\xd02\xf7\u0449\x8b\x9d\xc1\xbc\x1a\x03j\x80\x00\xe0\x94>\x1b\"0\xaf\xbb\xd3\x10\xb4\x92jLwmZ\u705cf\x1d\x8a\x06ZM\xa2]0\x16\xc0\x00\x00\u07d4>\x1cS0\x0eL\x16\x89\x12\x16<~\x99\xb9]\xa2h\xad(\n\x896b2\\\u044f\xe0\x00\x00\u07d4>\x1c\x96 c\xe0\xd5)YA\xf2\x10\u0723\xabS\x1e\xec\x88\t\x89\xa2\xa1]\tQ\x9b\xe0\x00\x00\u07d4>,\xa0\xd24\xba\xf6\a\xadFj\x1b\x85\xf4\xa6H\x8e\xf0\n\xe7\x89\x04\xda!\xa3H=V\x80\x00\u07d4>/&#^\x13zs$\xe4\xdc\x15K]\xf5\xafF\xea\x1aI\x89\x017\xaa\xd8\x03-\xb9\x00\x00\xe0\x94>1a\xf1\xea/\xbf\x12ny\xda\x18\x01\u0695\x12\xb3y\x88\u024a\nm\xd9\f\xaeQ\x14H\x00\x00\xe0\x94>6\xc1rS\xc1\x1c\xf3\x89t\xed\r\xb1\xb7Y\x16\r\xa67\x83\x8a\x01{x\x83\xc0i\x16`\x00\x00\u07d4><\u04fe\xc0e\x91\xd64o%Kb\x1e\xb4\x1c\x89\x00\x8d1\x895\u07fe\u069f74\x00\x00\u07d4>E\xbdU\u06d0`\xec\xed\x92;\xb9\xcbs<\xb3W?\xb51\x89X\xe7\x92n\xe8X\xa0\x00\x00\u07d4>M\x13\xc5Z\x84\xe4n\xd7\xe9\u02d0\xfd5^\x8a\u0651\u33c965\u026d\xc5\u07a0\x00\x00\u07d4>N\x92e\"<\x9782L\xf2\v\xd0`\x06\xd0\a>\u06cc\x89\a?u\u0460\x85\xba\x00\x00\xe0\x94>O\xbdf\x10\x15\xf6F\x1e\xd6s\\\xef\xef\x01\xf3\x14E\xde:\x8a\x03n4)\x98\xb8\xb0 \x00\x00\xe0\x94>S\xff!\a\xa8\u07be3(I:\x92\xa5\x86\xa7\xe1\xf4\x97X\x8a\x04\xe6\x9c*q\xa4\x05\xab\x00\x00\u07d4>Z9\xfd\xdap\xdf\x11&\xab\r\u011asx1\x1aSz\x1f\x89\x82\x1a\xb0\xd4AI\x80\x00\x00\xe0\x94>Z\xbd\t\xceZ\xf7\xba\x84\x87\xc3Y\xe0\xf2\xa9:\x98k\v\x18\x8a\x02\x1e\x19\xe0\u027a\xb2@\x00\x00\u07d4>\\\xb8\x92\x8cAx%\xc0:;\xfc\xc5!\x83\xe5\xc9\x1eB\u05c9\xe71\xd9\xc5,\x96/\x00\x00\u07d4>^\x93\xfbL\x9c\x9d\x12F\xf8\xf2G5\x8e\"\xc3\xc5\xd1{j\x89\b!\xab\rD\x14\x98\x00\x00\u07d4>a\x83P\xfa\x01ez\xb0\xef>\xba\xc8\xe3p\x12\xf8\xfc+o\x89\x98\x06\xde=\xa6\xe9x\x00\x00\u07d4>c\xce;$\xca(e\xb4\u0166\x87\xb7\xae\xa3Y~\xf6\xe5H\x89lk\x93[\x8b\xbd@\x00\x00\u07d4>f\xb8GiVj\xb6yE\xd5\xfa\x8175V\xbc\u00e1\xfa\x89\b=lz\xabc`\x00\x00\xe0\x94>v\xa6-\xb1\x87\xaat\xf68\x17S;0l\xea\xd0\xe8\u03be\x8a\x06\x9bZ\xfa\xc7P\xbb\x80\x00\x00\u07d4>z\x96k]\xc3W\xff\xb0~\x9f\xe0g\xc4W\x91\xfd\x8e0I\x89\x034-`\xdf\xf1\x96\x00\x00\xe0\x94>\x81w!u#~\xb4\xcb\xe0\xfe-\xca\xfd\xad\xff\xebj\x19\x99\x8a\x01\xdd\f\x88_\x9a\r\x80\x00\x00\u07d4>\x83I\xb6\u007fWED\x9fe\x93g\u066dG\x12\xdb[\x89Z\x89b\xa9\x92\xe5:\n\xf0\x00\x00\u07d4>\x83TO\x00\x82U%r\u01c2\xbe\xe5\xd2\x18\xf1\xef\x06J\x9d\x89\x05l\xd5_\xc6M\xfe\x00\x00\u07d4>\x84\xb3\\[\"ePpa\xd3\vo\x12\xda\x03?\xe6\xf8\xb9\x89a\t=|,m8\x00\x00\u07d4>\x86A\xd4<B\x00?\n3\xc9)\xf7\x11\a\x9d\xeb+\x9eF\x89\x1b\x1a\xe4\xd6\xe2\xefP\x00\x00\xe0\x94>\x87E\xba2/_\xd6\xcbP\x12N\xc4f\x88\u01e6\x9a\u007f\xae\x8a\x01\n\xfc\x1a\xde;N\xd4\x00\x00\u07d4>\x91N0\x18\xac\x00D\x93A\u011d\xa7\x1d\x04\xdf\xee\xedb!\x89\xd8\xd7&\xb7\x17z\x80\x00\x00\u07d4>\x94\x10\u04f9\xa8~\xd5\xe4Q\xa6\xb9\x1b\xb8\x92?\xe9\x0f\xb2\xb5\x89\n\u05ce\xbcZ\xc6 \x00\x00\u07d4>\x94\xdfS\x13\xfaR\x05p\xef#+\xc31\x1d_b/\xf1\x83\x89lk\x93[\x8b\xbd@\x00\x00\u0794>\x9b4\xa5\u007f3u\xaeY\xc0\xa7^\x19\u0136A\"\x8d\x97\x00\x88\xf8i\x93)g~\x00\x00\u07d4>\xad\xa8\xc9/V\x06~\x1b\xb7<\xe3x\xdaV\xdc,\xdf\xd3e\x89w\xcd\xe9:\xeb\rH\x00\x00\xe0\x94>\xaf\by\xb5\xb6\xdb\x15\x9bX\x9f\x84W\x8bjt\xf6\xc1\x03W\x8a\x01\x898\xb6q\xfae\xa2\x80\x00\u07d4>\xaf1k\x87a]\x88\xf7\xad\xc7|X\xe7\x12\xedMw\x96k\x89\x05m\xbcL\xee$d\x80\x00\u07d4>\xb8\xb3;!\xd2<\u0686\xd8(\x88\x84\xabG\x0e\x16F\x91\xb5\x89\x1b\x1a\xe4\xd6\xe2\xefP\x00\x00\u07d4>\xb9\xef\x06\xd0\xc2Y\x04\x03\x19\x94~\x8czh\x12\xaa\x02S\u0609\t\r\x97/22<\x00\x00\u07d4>\u030e\x16h\xdd\xe9\x95\xdcW\x0f\xe4\x14\xf4B\x11\xc54\xa6\x15\x89lk\x93[\x8b\xbd@\x00\x00\u07d4>\u03752\xe3\x97W\x96b\xb2\xa4aA\u73c25\x93j_\x89\x03\x9f\xba\xe8\xd0B\xdd\x00\x00\u07d4>\xeeo\x1e\x966\vv\x89\xb3\x06\x9a\xda\xf9\xaf\x8e\xb6\f\u404965\u026d\xc5\u07a0\x00\x00\xe0\x94?\b\u066d\x89O\x81>\x8e!H\xc1`\xd2K5:\x8et\xb0\x8a\f\xb4\x9bD\xba`-\x80\x00\x00\u07d4?\f\x83\xaa\xc5qybsN\\\xea\xea\xec\u04db(\xad\x06\xbe\x89lk\x93[\x8b\xbd@\x00\x00\xe0\x94?\x10\x80\x02\x82\u0477\xdd\u01cf\xa9-\x820\aN\x1b\xf6\xae\xae\x8a\x01\n\xfc\x1a\xde;N\xd4\x00\x00\u07d4?\x123qO M\xe9\xdeN\xe9m\a;6\x8d\x81\x97\x98\x9f\x89\x02\x17\xc4\x10t\xe6\xbb\x00\x00\u07d4?\x17:\xa6\xed\xf4i\u0445\xe5\x9b\xd2j\xe4#k\x92\xb4\xd8\xe1\x89\x11X\xe4`\x91=\x00\x00\x00\u07d4?\x1b\xc4 \xc5<\x00,\x9e\x90\x03|D\xfej\x8e\xf4\xdd\xc9b\x89\t`\xdbwh\x1e\x94\x00\x00\u07d4?#a\b\xee\xc7\"\x89\xba\u00e6\\\u0483\xf9^\x04\x1d\x14L\x8964\xbf9\xab\x98x\x80\x00\u07d4?-\xa0\x93\xbb\x16\xeb\x06O\x8b\xfa\x9e0\xb9)\xd1_\x8e\x1cL\x89lk\x93[\x8b\xbd@\x00\x00\u07d4?-\xd5]\xb7\xea\xb0\xeb\xeee\xb3>\xd8 ,\x1e\x99.\x95\x8b\x89,s\xc97t,P\x00\x00\u07d4?/8\x14\x91y|\xc5\xc0\u0502\x96\xc1O\xd0\xcd\x00\xcd\xfa-\x89+\x95\xbd\xcc9\xb6\x10\x00\x00\u07d4?0\u04fc\x9f`\"2\xbcrB\x88\xcaF\xcd\v\a\x88\xf7\x15\x89\xd8\xd7&\xb7\x17z\x80\x00\x00\u07d4?<\x8ea\xe5`L\xef\x06\x05\xd46\xdd\"\xac\u0346\"\x17\xfc\x89Hz\x9a0E9D\x00\x00\u07d4??F\xb7\\\xab\xe3{\xfa\u0307`(\x1fCA\xca\u007fF=\x89 \xacD\x825\xfa\xe8\x80\x00\u07d4?G)c\x19x\x83\xbb\xdaZ\x9b}\xfc\xb2-\xb1\x14@\xad1\x89\x1a\x19d<\xb1\xef\xf0\x80\x00\u07d4?L\xd19\x9f\x8a4\xed\u06da\x17\xa4q\xfc\x92+Xp\xaa\xfc\x89\n\u05ce\xbcZ\xc6 \x00\x00\u07d4?U\x1b\xa9<\xd5F\x93\xc1\x83\xfb\x9a\xd6\re\xe1`\x96s\u0249lk\x93[\x8b\xbd@\x00\x00\xe0\x94?bzv\x9ej\x95\x0e\xb8p\x17\xa7\u035c\xa2\bq\x13h1\x8a\x02\ub3b1\xa1r\u0738\x00\x00\u07d4?m\xd3e\x0e\xe4(\u0737u\x95S\xb0\x17\xa9j\x94(j\u0249Hz\x9a0E9D\x00\x00\u07d4?tr7\x80o\xed?\x82\x8ahR\xeb\bg\xf7\x90'\xaf\x89\x89QP\xae\x84\xa8\xcd\xf0\x00\x00\u07d4?u\xaea\xcc\x1d\x80Be;[\xae\xc4D>\x05\x1c^z\xbd\x89\x05-T(\x04\xf1\xce\x00\x00\u07d4?\xb7\u0457\xb3\xbaO\xe0E\xef\xc2=P\xa1E\x85\xf5X\u0672\x89\x01\x15\x8eF\t\x13\xd0\x00\x00\xe0\x94?\xbc\x1eE\x18\xd74\x00\xc6\xd0F5\x949\xfbh\xea\x1aI\xf4\x8a\x03y\v\xb8U\x13v@\x00\x00\u07d4?\xbe\xd6\xe7\xe0\u029c\x84\xfb\xe9\xeb\u03ddN\xf9\xbbIB\x81e\x89lk\x93[\x8b\xbd@\x00\x00\u07d4?\u043bGy\x8c\xf4L\u07feM3=\xe67\xdfJ\x00\xe4\\\x89\x05lUy\xf7\"\x14\x00\x00\xe0\x94?\xe4\x0f\xbd\x91\x9a\xad(\x18\xdf\x01\xeeM\xf4lF\x84*\xc59\x8a\x01EB\xba\x12\xa37\xc0\x00\x00\u07d4?\xe8\x01\xe6\x135\xc5\x14\r\xc7\xed\xa2\xefR\x04F\nP\x120\x89lk\x93[\x8b\xbd@\x00\x00\u07d4?\xf86\xb6\xf5{\x90\x1bD\f0\xe4\xdb\xd0e\xcf7\xd3\u050c\x89\n\u05ce\xbcZ\xc6 \x00\x00\u07d4?\xfc\xb8p\xd4\x02=%]Qg\u0625\a\xce\xfc6kh\xba\x89#4<CT\u04ac\x00\x00\u0794@\x13T\xa2\x97\x95/\xa9r\xad8<\xa0z\n(\x11\xd7Jq\x88\xc2I\xfd\xd3'x\x00\x00\u07d4@0\xa9%pk,\x10\x1c\x8c\\\xb9\xbd\x05\xfb\xb4\xf6u\x9b\x18\x89\xd8\xd7&\xb7\x17z\x80\x00\x00\xe0\x94@1E\xcbJ\xe7H\x9f\u0310\u0358\\m\u01c2\xb3\xccND\x8a\x01E?\xf3\x87\xb2|\xac\x00\x00\u07d4@2 `\n6\xf7?$\xe1\x90\xd1\xed\xb2\xd6\x1b\xe3\xf4\x13T\x89\x10z\xd8\xf5V\xc6\xc0\x00\x00\u07d4@9\xbdP\xa2\xbd\xe1_\xfe7\x19\x1fA\x03\x90\x96*+\x88\x86\x89\n\u05ce\xbcZ\xc6 \x00\x00\u07d4@<d\x89ju\xca\xd8\x16\xa9\x10^\x18\u062a[\xf8\x0f#\x8e\x895e\x9e\xf9?\x0f\xc4\x00\x00\xe0\x94@=S\xcfb\x0f\t\"\xb4\x17\x84\x8d\xee\x96\xc1\x90\xb5\xbc\x82q\x8a\x02\x15\xf85\xbcv\x9d\xa8\x00\x00\u07d4@A\x00\xdbL]\x0e\xecUx#\xb5\x83Cu\x8b\xcc,\x80\x83\x89\x01\x15\x8eF\t\x13\xd0\x00\x00\u07d4@A7K\x0f\xee\xf4y.K3i\x1f\xb8h\x97\xa4\xffV\f\x89\x13\xc9d~%\xa9\x94\x00\x00\u07d4@F}\x80\xe7L5@{}\xb5\x17\x89#F\x15\xfe\xa6h\x18\x89\x15\b\x94\xe8I\xb3\x90\x00\x00\u07d4@XR\x00h:@9\x017)\x12\xa8\x984\xaa\u0735_\u06c9lk\x93[\x8b\xbd@\x00\x00\u07d4@X\x80\x88\x16\xfd\xaa:_\u024e\xd4|\xfa\xe6\xc1\x83\x15B.\x89\n\xd4\xc81j\v\f\x00\x00\u07d4@_Yk\x94\xb9G4L\x03<\xe2\u073f\xf1.%\xb7\x97\x84\x89lk\x93[\x8b\xbd@\x00\x00\u07d4@c\x00$\xbd,X\xd2H\xed\xd8FV\x17\xb2\xbf\x16G\xda\x0e\x8965\u026d\xc5\u07a0\x00\x00\xe0\x94@e#`\xd6qm\xc5\\\xf9\xaa\xb2\x1f4\x82\xf8\x16\xcc,\xbd\x8a\x02\x1e\x19\xe0\u027a\xb2@\x00\x00\xe0\x94@r\x95\xeb\xd9KH&\x9c-V\x9c\x9b\x9a\xf9\xaa\x05\xe8>^\x8a\x02\x1e\x19\xe0\u027a\xb2@\x00\x00\u07d4@s\xfaI\xb8q\x17\u02d0\x8c\xf1\xabQ-\xa7T\xa92\xd4w\x89j\xcb=\xf2~\x1f\x88\x00\x00\u07d4@\x8ai\xa4\a\x15\xe1\xb3\x13\xe15N`\b\x00\xa1\xe6\xdc\x02\xa5\x89\x01\u7e11\u0312T\x00\x00\u07d4@\x9b\xd7P\x85\x82\x1c\x1d\xe7\f\xdc;\x11\xff\xc3\xd9#\xc7@\x10\x89\xd8\xd7&\xb7\x17z\x80\x00\x00\u07d4@\x9dZ\x96.\xde\uefa1x\x01\x8c\x0f8\xb9\u0372\x13\xf2\x89\x89\x01\x15\x8eF\t\x13\xd0\x00\x00\u07d4@\xa31\x19[\x97s%\u00aa(\xfa/B\xcb%\xec<%<\x89lk\x93[\x8b\xbd@\x00\x00\u07d4@\xa7\xf7(g\xa7\u0706w\v\x16+uW\xa44\xedP\xcc\xe9\x8965\u026d\xc5\u07a0\x00\x00\u07d4@\xab\n>\x83\xd0\u022c\x93f\x91\x05 \xea\xb1w+\xac;\x1a\x894\xf1\f-\xc0^|\x00\x00\u07d4@\xabf\xfe!>\xa5l:\xfb\x12\xc7[\xe3?\x8e2\xfd\b]\x89\xd8\xd7&\xb7\x17z\x80\x00\x00\xe0\x94@\xadt\xbc\v\xce*E\xe5/6\xc3\u07bb\x1b:\xda\x1bv\x19\x8a\x01p\x16-\xe1\t\xc6X\x00\x00\u07d4@\u03c9\x05\x91\xea\u484f\x81*)T\xcb)_c3'\xe6\x89\x02\x9b\xf76\xfcY\x1a\x00\x00\u07d4@\u03d0\xef[v\x8c]\xa5\x85\x00,\xcb\xe6avP\xd8\xe87\x8963\x03\"\xd5#\x8c\x00\x00\xe0\x94@\xd4]\x9dv%\xd1QV\xc92\xb7q\xca{\x05'\x13\tX\x8a\x15-\x02\xc7\xe1J\xf6\x80\x00\x00\u07d4@\xdb\x1b\xa5\x85\xce4S\x1e\xde\xc5IHI9\x13\x81\xe6\xcc\u04c9a\t=|,m8\x00\x00\xe0\x94@\xdfI^\xcf?\x8bL\xef*l\x18\x99W$\x8f\u813c+\x8a\x02\x8a\x85t%Fo\x80\x00\x00\u07d4@\xe0\xdb\xf3\xef\uf404\xea\x1c\xd7\xe5\x03\xf4\v;J\x84C\xf6\x89\xd8\xd7&\xb7\x17z\x80\x00\x00\u07d4@\xe2D\n\xe1B\u02006j\x12\xc6\xd4\x10/K\x844\xb6*\x8965\u026d\xc5\u07a0\x00\x00\u07d4@\xe3\u0083\xf7\xe2M\xe0A\f\x12\x1b\xee`\xa5`\u007f>)\xa6\x8965\u026d\xc5\u07a0\x00\x00\xe0\x94@\xeaPD\xb2\x04\xb20v\xb1\xa5\x80;\xf1\xd3\f\x0f\x88\x87\x1a\x8a\x02\xf6\xf1\a\x80\xd2,\xc0\x00\x00\xe0\x94@\xed\xdbD\x8di\x0e\xd7.\x05\xc2%\xd3O\xc85\x0f\xa1\xe4\u014a\x01{x\x83\xc0i\x16`\x00\x00\xe0\x94@\xf4\xf4\xc0ls,\xd3[\x11\x9b\x89;\x12~}\x9d\aq\xe4\x8a\x02\x1e\x19\xe0\u027a\xb2@\x00\x00\u07d4A\x01\x0f\u023a\xf8C}\x17\xa0Ci\x80\x9a\x16\x8a\x17\xcaV\xfb\x89\x05k\xc7^-c\x10\x00\x00\u07d4A\x03)\x96q\xd4gc\x97\x8f\xa4\xaa\x19\xee4\xb1\xfc\x95'\x84\x89\n\u05ce\xbcZ\xc6 \x00\x00\u07d4A\x03<\x1bm\x05\xe1\u0289\xb0\x94\x8f\xc6DS\xfb\xe8z\xb2^\x89Hz\x9a0E9D\x00\x00\u07d4A\t\x8a\x81E#\x17\xc1\x9e>\xef\v\xd1#\xbb\xe1x\xe9\xe9\u0289\x97\xc9\xceL\xf6\xd5\xc0\x00\x00\u07d4A\x16\x10\xb1x\xd5a}\xfa\xb94\u0493\xf5\x12\xa9>\\\x10\xe1\x89\t79SM(h\x00\x00\u07d4A\x1c\x83\x1c\xc6\xf4O\x19e\xecWW\xabN[<\xa4\xcf\xfd\x1f\x89\x17\n\x0fP@\xe5\x04\x00\x00\xe0\x94A*h\xf6\xc6EU\x9c\xc9w\xfcId\x04z \x1d\x1b\xb0\xe2\x8a\n\x96\x81c\xf0\xa5{@\x00\x00\u07d4A?K\x02f\x9c\xcf\xf6\x80k\xc8&\xfc\xb7\xde\xca;\x0e\xa9\xbc\x89\x01\x15\x8eF\t\x13\xd0\x00\x00\u07d4AE\x99\t.\x87\x9a\xe2Sr\xa8MsZ\xf5\xc4\xe5\x10\xcdm\x89\x15\xaf\x1dx\xb5\x8c@\x00\x00\u07d4AHV\x12\xd04F\xecL\x05\xe5$NV?\x1c\xba\xe0\xf1\x97\x894\x95tD\xb8@\xe8\x00\x00\u07d4A]\tj\xb0b\x93\x18?<\x03=%\xf6\xcfqx\xac;\u01c9\x02+\x1c\x8c\x12'\xa0\x00\x00\u07d4Af\xfc\b\u0285\xf7f\xfd\xe81F\x0e\x9d\xc9<\x0e!\xaal\x8965\u026d\xc5\u07a0\x00\x00\xe0\x94Ag\x84\xaf`\x960\xb0p\u051a\x8b\xcd\x12#\\d(\xa4\b\x8a\x04<3\xc1\x93ud\x80\x00\x00\u07d4Ag\xcdH\xe73A\x8e\x8f\x99\xff\xd14\x12\x1cJJ\xb2x\u0109\xc5S%\xcat\x15\xe0\x00\x00\u07d4Al\x86\xb7 \x83\xd1\xf8\x90}\x84\xef\xd2\xd2\u05c3\xdf\xfa>\xfb\x89lj\xccg\u05f1\xd4\x00\x00\u07d4AsA\x9d\\\x9fc)U\x1d\xc4\xd3\xd0\u03ac\x1bp\x1b\x86\x9e\x89\x04\xc5>\xcd\xc1\x8a`\x00\x00\u07d4At\xfa\x1b\xc1*;q\x83\u02eb\xb7z\vYU{\xa5\xf1\u06c9lk\x93[\x8b\xbd@\x00\x00\u07d4Axj\x10\xd4G\xf4\x84\xd32D\u0337\xfa\u034bB{[\x8c\x8965\u026d\xc5\u07a0\x00\x00\xe0\x94Az<\u0454\x96S\nmB\x04\u00f5\xa1|\xe0\xf2\a\xb1\xa5\x8a\x01\xb1\xaeMn.\xf5\x00\x00\x00\u07d4A~N&\x88\xb1\xfdf\xd8!R\x9eF\xedOB\xf8\xb3\xdb=\x89lk\x93[\x8b\xbd@\x00\x00\xe0\x94A\x9aq\xa3l\x11\xd1\x05\xe0\xf2\xae\xf5\xa3\xe5\x98\a\x8e\x85\xc8\v\x8a\x01\x0f\f\xf0d\xddY \x00\x00\xe0\x94A\x9b\xdes\x16\xcc\x1e\u0495\u0205\xac\xe3B\u01db\xf7\xee3\xea\x8a\x01EB\xba\x12\xa37\xc0\x00\x00\u07d4A\xa2\xf2\xe6\xec\xb8c\x94\xec\x0e3\x8c\x0f\xc9~\x9cU\x83\xde\u0489l\xee\x06\u077e\x15\xec\x00\x00\u07d4A\xa8\u0083\x00\x81\xb1\x02\xdfn\x011e|\a\xabc[T\u0389lj\xccg\u05f1\xd4\x00\x00\u07d4A\xa8\xe26\xa3\x0emc\xc1\xffdM\x13*\xa2\\\x89S~\x01\x89\x01\x15\x8eF\t\x13\xd0\x00\x00\u07d4A\xa9\xa4\x04\xfc\x9f[\xfe\xe4\x8e\xc2e\xb1%#3\x8e)\xa8\xbf\x89\x15\b\x94\xe8I\xb3\x90\x00\x00\u07d4A\xad6\x9fu\x8f\xef8\xa1\x9a\xa3\x14\x93y\x83,\x81\x8e\xf2\xa0\x8966\x9e\xd7t}&\x00\x00\u07d4A\xb2\xd3O\xde\v\x10)&+Ar\xc8\x1c\x15\x90@[\x03\xae\x8965\u026d\xc5\u07a0\x00\x00\u07d4A\xb2\xdb\u05dd\u069b\x86Ojp0'T\x19\u00dd>\xfd;\x89\xadx\xeb\u016cb\x00\x00\x00\u07d4A\xc3\xc26u4\xd1;\xa2\xb3?\x18\\\xdb\xe6\xacC\xc2\xfa1\x89\xd8\xd7&\xb7\x17z\x80\x00\x00\u07d4A\u02d8\x96D_p\xa1\n\x14!R\x96\xda\xf6\x14\xe3,\xf4\u0549g\x8a\x93 b\xe4\x18\x00\x00\u07d4A\xcey\x95\t5\xcf\xf5[\xf7\x8eL\xce\xc2\xfec\x17\x85\u06d5\x89lk\x93[\x8b\xbd@\x00\x00\u07d4A\u04f71\xa3&\xe7hX\xba\xa5\xf4\xbd\x89\xb5{6\x93#C\x89\x15[\xd90\u007f\x9f\xe8\x00\x00\xe0\x94A\xe4\xa2\x02u\xe3\x9b\xdc\xef\xebe\\\x03\"tKvQ@\u008a\x02\x1e\x19\xe0\u027a\xb2@\x00\x00\u07d4A\xed-\x8ep\x81H,\x91\x9f\xc2=\x8f\x00\x91\xb3\xc8,F\x85\x89F:\x1ev[\u05ca\x00\x00\xe0\x94A\xf2~tK\u049d\xe2\xb0Y\x8f\x02\xa0\xbb\x9f\x98\xe6\x81\ua90a\x01\xa4\xab\xa2%\xc2\a@\x00\x00\u07d4A\xf4\x89\xa1\xect{\u009c>_\x9d\x8d\xb9xw\xd4\u0474\xe9\x89\a?u\u0460\x85\xba\x00\x00\u07d4B\x0f\xb8n}+Q@\x1f\xc5\xe8\xc7 \x15\xde\xcbN\xf8\xfc.\x8965\u026d\xc5\u07a0\x00\x00\u07d4B\x16\x84\xba\xa9\xc0\xb4\xb5\xf5S8\xe6\xf6\xe7\xc8\xe1F\xd4\x1c\xb7\x89QP\xae\x84\xa8\xcd\xf0\x00\x00\u07d4B9\x96Y\xac\xa6\xa5\xa8c\xea\"E\xc93\xfe\x9a5\xb7\x88\x0e\x89n\xce2\xc2l\x82p\x00\x00\xe0\x94B;\xcaG\xab\xc0\fpW\xe3\xad4\xfc\xa6>7_\xbd\x8bJ\x8a\x03\xcf\xc8.7\xe9\xa7@\x00\x00\u07d4B<1\a\xf4\xba\xceANI\x9cd9\nQ\xf7F\x15\xca^\x89lk\x93[\x8b\xbd@\x00\x00\u07d4B<\xc4YL\xf4\xab\xb66\x8d\xe5\x9f\u04b1#\a4a!C\x89lk\x93[\x8b\xbd@\x00\x00\xe0\x94BD\xf13\x11X\xb9\xce&\xbb\xe0\xb9#k\x92\x03\xca5\x144\x8a\x02\x1e\x19\xe0\u027a\xb2@\x00\x00\u0794BQw\xebt\xad\n\x9d\x9aWR\"\x81G\xeemcV\xa6\u6239\x8b\xc8)\xa6\xf9\x00\x00\u07d4BW%\xc0\xf0\x8f\b\x11\xf5\xf0\x06\xee\xc9\x1c\\\\\x12k\x12\xae\x89\b!\xab\rD\x14\x98\x00\x00\xe0\x94BX\xfdf/\xc4\xce2\x95\xf0\xd4\xed\x8f{\xb1D\x96\x00\xa0\xa9\x8a\x01lE.\xd6\b\x8a\xd8\x00\x00\xe0\x94B\\\x18\x16\x86\x8fww\xcc+\xa6\xc6\u048c\x9e\x1eylR\xb3\x8a\x02\x1e\x19\xe0\u027a\xb2@\x00\x00\u07d4B\\3\x8a\x13%\xe3\xa1W\x8e\xfa)\x9eW\u0646\xebGO\x81\x89lk\x93[\x8b\xbd@\x00\x00\xe0\x94BbY\xb0\xa7Vp\x1a\x8bf5(R!V\xc0(\x8f\x0f$\x8a\x02\x18\xae\x19k\x8dO0\x00\x00\u07d4Bm\x15\xf4\a\xa0\x115\xb1:kr\xf8\xf2R\v51\xe3\x02\x89\x01\x15\x8eF\t\x13\xd0\x00\x00\u07d4Box\xf7\r\xb2Y\xac\x854\x14[)4\xf4\xef\x10\x98\xb5\u0609\x13\x84\x00\xec\xa3d\xa0\x00\x00\u07d4Bs-\x8e\xf4\x9f\xfd\xa0K\x19x\x0f\xd3\xc1\x84i\xfb7A\x06\x89\x17\v\x00\xe5\u4a7e\x00\x00\u07d4Bt\x17\xbd\x16\xb1\xb3\xd2-\xbb\x90-\x8f\x96W\x01o$\xa6\x1c\x89lk\x93[\x8b\xbd@\x00\x00\u07d4Btj\xee\xa1O'\xbe\xff\f\r\xa6BS\xf1\xe7\x97\x18\x90\xa0\x89T\x06\x923\xbf\u007fx\x00\x00\u07d4B{F*\xb8NP\x91\xf4\x8aF\xeb\f\u0712\xdd\xcb&\xe0x\x89lk\x93[\x8b\xbd@\x00\x00\u07d4B~GQ\u00fa\xbex\xcf\xf8\x83\b\x86\xfe\xbc\x10\xf9\x90\x8dt\x89j\xcb=\xf2~\x1f\x88\x00\x00\xe0\x94B~\xc6h\xac\x94\x04\xe8\x95\u0306\x15\x11\xd1b\nI\x12\xbe\x98\x8a\bxg\x83&\xea\xc9\x00\x00\x00\u07d4B\x80\xa5\x8f\x8b\xb1\v\x94@\u0794\xf4+OY! \x82\x01\x91\x89lk\x93[\x8b\xbd@\x00\x00\u07d4B\x8a\x1e\xe0\xed3\x1dyR\u033e\x1cyt\xb2\x85+\u0453\x8a\x89w\xb7JN\x8d\xe5e\x00\x00\u0794B\x9c\x06\xb4\x87\xe8Tj\xbd\xfc\x95\x8a%\xa3\xf0\xfb\xa5?o\x00\x88\xbbdJ\xf5B\x19\x80\x00\xe0\x94B\xa9\x8b\xf1`'\xceX\x9cN\xd2\xc9X1\xe2rB\x05\x06N\x8a\x02\x1e\x19\xe0\u027a\xb2@\x00\x00\u07d4B\xc6\xed\xc5\x15\xd3UW\x80\x8d\x13\xcdD\xdc\xc4@\v%\x04\xe4\x89\n\xba\x14\u015b\xa72\x00\x00\u07d4B\xce\xcf\u0492\x10y\xc2\xd7\xdf?\b\xb0z\xa3\xbe\xee^!\x9a\x8965\u026d\xc5\u07a0\x00\x00\u07d4B\u04669\x9b0\x16\xa8Y\u007f\x8bd\t'\xb8\xaf\xbc\xe4\xb2\x15\x89\xa1\x8b\xce\xc3H\x88\x10\x00\x00\u07d4B\xd3I@\xed\xd2\xe7\x00]F\xe2\x18\x8eL\xfe\u0383\x11\xd7M\x89\b\x90\xb0\xc2\xe1O\xb8\x00\x00\u07d4B\u04e5\xa9\x01\xf2\xf6\xbd\x93V\xf1\x12\xa7\x01\x80\xe5\xa1U\v`\x892$\xf4'#\xd4T\x00\x00\u07d4B\u05b2c\xd9\xe9\xf4\x11lA\x14$\xfc\x99Ux<v00\x89lk\x93[\x8b\xbd@\x00\x00\u07d4B\xdb\v\x90%Y\xe0@\x87\xdd\\D\x1b\xc7a\x194\x18K\x89\x89m3\xb1}%:b\x00\x00\u07d4B\xdd\xd0\x14\xdcR\xbf\xbc\xc5U2Z@\xb5\x16\xf4\x86j\x1d\u04c9lk\x93[\x8b\xbd@\x00\x00\u07d4C\x19&?u@,\vS%\xf2c\xbeJP\x80e\x10\x87\xf0\x895K\x0f\x14c\x1b\xab\x00\x00\u07d4C\x1f,\x19\xe3\x16\xb0D\xa4\xb3\xe6\x1a\fo\xf8\xc1\x04\xa1\xa1/\x8965\u026d\xc5\u07a0\x00\x00\xe0\x94C\"}e3Ni\x1c\xf21\xb4\xa4\xe1\xd39\xb9]Y\x8a\xfb\x8a\x02\x1e\x19\xe0\u027a\xb2@\x00\x00\xe0\x94C(\t\xa29\x0f\a\xc6e\x92\x1f\xf3}T}\x12\xf1\u0256j\x8a\x06ZM\xa2]0\x16\xc0\x00\x00\u07d4C)\xfc\t1\xcb\xeb\x038\x80\xfeL\x93\x98\xcaE\xb0\xe2\xd1\x1a\x89lq qm3h\x00\x00\u07d4C-\x88K\u059d\xb1\xac\xc0\u061cd\xad\xe4\xcbO\u00e8\x8bz\x89\x86\x9a\x8c\x10\x80\x8e\xec\x00\x00\u07d4C1\xab7G\xd3W \xa9\xd8\xca%\x16\\\u0485\xac\u053d\xa8\x89lk\x93[\x8b\xbd@\x00\x00\u07d4C:;h\xe5k\r\xf1\x86+\x90Xk\xbd9\xc8@\xff\x196\x89lk\x93[\x8b\xbd@\x00\x00\xe0\x94C>;\xa1\xc5\x1b\x81\x0f\xc4g\u057aM\xeaB\xf7\xa9\x88^i\x8a\bxg\x83&\xea\xc9\x00\x00\x00\xe0\x94C>\xb9J3\x90\x86\xed\x12\u067d\xe9\xcd\x1dE\x86\x03\xc9}\u058a\x15-\x02\xc7\xe1J\xf6\x80\x00\x00\u07d4CI\"Zb\xf7\n\xeaH\n\x02\x99\x15\xa0\x1eSy\xe6O\xa5\x89\x8c\xd6~#4\xc0\xd8\x00\x00\u07d4CT\"\x1eb\xdc\t\xe6@d6\x16:\x18^\xf0m\x11J\x81\x89lk\x93[\x8b\xbd@\x00\x00\xe0\x94CTC\xb8\x1d\xfd\xb9\xbd\x8cg\x87\xbc%\x18\xe2\xd4~W\xc1_\x8a\x01C\x8d\x93\x97\x88\x1e\xf2\x00\x00\u07d4Ca\u0504o\xaf\xb3w\xb6\xc0\xeeI\xa5\x96\xa7\x8d\xdf5\x16\xa3\x89\xc2\x12z\xf8X\xdap\x00\x00\xe0\x94Cd0\x9a\x9f\xa0p\x95`\x0fy\xed\xc6Q \xcd\xcd#\xdcd\x8a\x02\x1e\x19\xe0\u027a\xb2@\x00\x00\u07d4Cg\xaeK\f\xe9d\xf4\xa5J\xfdK\\6\x84\x96\xdb\x16\x9e\x9a\x89lk\x93[\x8b\xbd@\x00\x00\u07d4Ct\x89(\xe8\xc3\xecD6\xa1\u0412\xfb\xe4:\xc7I\xbe\x12Q\x89\x15\xaf\x1dx\xb5\x8c@\x00\x00\u07d4Cv{\xf7\xfd*\xf9[r\xe91-\xa9D<\xb1h\x8eCC\x89\x10CV\x1a\x88)0\x00\x00\xe0\x94Cy\x838\x8a\xb5\x9aO\xfc!_\x8e\x82iF\x10)\xc3\xf1\xc1\x8a\x04<3\xc1\x93ud\x80\x00\x00\u07d4C\x89\x8cI\xa3MP\x9b\xfe\xd4\xf7`A\xee\x91\xca\xf3\xaaj\xa5\x89\x10CV\x1a\x88)0\x00\x00\u07d4C\x8c/T\xff\x8eb\x9b\xab6\xb1D+v\v\x12\xa8\x8f\x02\xae\x89lk\x93[\x8b\xbd@\x00\x00\u07d4C\x98b\x8e\xa6c-9>\x92\x9c\xbd\x92\x84d\xc5h\xaaJ\f\x89K\xe4\xe7&{j\xe0\x00\x00\u07d4C\x9d//Q\x10\xa4\u054b\x17W\x93P\x15@\x87@\xfe\xc7\xf8\x89\u03e5\xc5\x15\x0fL\x88\x80\x00\u07d4C\x9d\xee?vy\xff\x100s?\x93@\xc0\x96hkI9\v\x89lk\x93[\x8b\xbd@\x00\x00\u07d4C\xb0y\xba\xf0ry\x99\xe6k\xf7C\u057c\xbfwl;\t\"\x89lk\x93[\x8b\xbd@\x00\x00\u07d4C\xbc-M\xdc\xd6X;\xe2\u01fc\tK(\xfbr\xe6+\xa8;\x89lk\x93[\x8b\xbd@\x00\x00\u07d4C\xc7\xeb\u0173\xe7\xaf\x16\xf4}\xc5az\xb1\x0e\x0f9\xb4\xaf\xbb\x89g\x8a\x93 b\xe4\x18\x00\x00\u07d4C\u02d6R\x81\x8coMg\x96\xb0\xe8\x94\t0ly\xdbcI\x89lk\x93[\x8b\xbd@\x00\x00\u07d4C\xcc\b\xd0s*\xa5\x8a\xde\xf7a\x9b\xedFU\x8a\xd7wAs\x89\xf0\xe7\u0730\x12*\x8f\x00\x00\xe0\x94C\u0567\x1c\xe8\xb8\xf8\xae\x02\xb2\xea\xf8\xea\xf2\xca(@\xb9?\xb6\x8a\x01EB\xba\x12\xa37\xc0\x00\x00\u0794C\xdb\u007f\xf9Z\bm(\ubff8/\xb8\xfb_#\n^\xbc\u0348\xdfn\xb0\xb2\xd3\xca\x00\x00\u07d4C\xe7\xec\x84cX\xd7\xd0\xf97\xad\x1c5\v\xa0i\u05ffr\xbf\x89\x06p\xaeb\x92\x14h\x00\x00\u07d4C\xf1o\x1eu\xc3\xc0j\x94x\xe8\u0157\xa4\n<\xb0\xbf\x04\u0309\x9d\xf7\u07e8\xf7`H\x00\x00\u07d4C\xf4p\xede\x9e)\x91\xc3u\x95~]\xde\u017d\x1d8\"1\x89\x05k\xc7^-c\x10\x00\x00\u07d4C\xf7\xe8n8\x1e\xc5\x1e\u0110m\x14v\u02e9z=\xb5\x84\xe4\x8965\u026d\xc5\u07a0\x00\x00\u07d4C\xff8t>\xd0\xcdC0\x8c\x06e\t\u030e~r\xc8b\xaa\x89i*\xe8\x89p\x81\xd0\x00\x00\xe0\x94C\xff\x88S\xe9\x8e\xd8@k\x95\x00\n\u0684\x83b\u05a09*\x8a\x04\xae\v\x1cM.\x84\xd0\x00\x00\u07d4D\t\x88f\xa6\x9bh\xc0\xb6\xbc\x16\x82)\xb9`5\x87\x05\x89g\x89\n1\x06+\xee\xedp\x00\x00\u07d4D\x19\xaca\x8d]\xea|\xdc`w o\xb0}\xbd\xd7\x1c\x17\x02\x89\xd8\xd7&\xb7\x17z\x80\x00\x00\u07d4D\x1aR\x00\x16a\xfa\xc7\x18\xb2\u05f3Q\xb7\xc6\xfbR\x1az\xfd\x89\x15\xaf\x1dx\xb5\x8c@\x00\x00\xe0\x94D\x1a\u0282c\x13$\xac\xbf\xa2F\x8b\xda2[\xbdxG{\xbf\x8a\x01EB\xba\x12\xa37\xc0\x00\x00\u07d4D\x1f7\xe8\xa0)\xfd\x02H/(\x9cI\xb5\xd0m\x00\xe4\b\xa4\x89\x12\x11\xec\xb5m\x13H\x80\x00\u07d4D \xaa5F[\xe6\x17\xad$\x98\xf3p\xde\n<\xc4\xd20\xaf\x89lk\x93[\x8b\xbd@\x00\x00\u07d4D#/\xf6m\xda\xd1\xfd\x84\x12f8\x006\xaf\xd7\xcf}\u007fB\x89\n\u05ce\xbcZ\xc6 \x00\x00\u07d4D%\rGn\x06$\x84\xe9\b\n9g\xbf:Js*\xd7?\x89\x01\x15\x8eF\t\x13\xd0\x00\x00\u07d4D)\xa2\x9f\xee\x19\x84Pg,\f\x1d\a1b%\v\xecdt\x896*\xaf\x82\x02\xf2P\x00\x00\u07d4D5RS\xb2wH\xe3\xf3O\xe9\xca\xe1\xfbq\x8c\x8f$\x95)\x89\n\u05ce\xbcZ\xc6 \x00\x00\u07d4D8\xe8\x80\xcb'f\xb0\xc1\u03ae\xc9\xd2A\x8f\u03b9R\xa0D\x89\a?\xa0s\x90?\b\x00\x00\u07d4DL\xafy\xb7\x138\ue6a7\xc73\xb0*\u02a7\xdc\x02YH\x89\x02+\x1c\x8c\x12'\xa0\x00\x00\u07d4D\\\xb8\xde^=\xf5 \xb4\x99\xef\u0240\xf5+\xff@\xf5\\v\x89lk\x93[\x8b\xbd@\x00\x00\xe0\x94Dj\x809\xce\u03dd\xceHy\xcb\xca\xf3I;\xf5E\xa8\x86\x10\x8a\x01{x\x83\xc0i\x16`\x00\x00\u07d4Dt)\x9d\x0e\xe0\x90\u0710x\x9a\x14\x86H\x9c=\rd^m\x8965\u026d\xc5\u07a0\x00\x00\u07d4D\x8b\xf4\x10\xad\x9b\xbc/\xec\xc4P\x8d\x87\xa7\xfc.K\x85a\xad\x89\n\xd6\xee\xdd\x17\xcf;\x80\x00\u07d4D\x90\x1e\r\x0e\b\xac=^\x95\xb8\xec\x9d^\x0f\xf5\xf1.\x03\x93\x89\x16\xa1\xf9\xf5\xfd}\x96\x00\x00\xe0\x94D\x93\x12<\x02\x1e\xce;3\xb1\xa4R\xc9&\x8d\xe1@\a\xf9\u04ca\x01je\x02\xf1Z\x1eT\x00\x00\xe0\x94D\x9a\xc4\xfb\xe3\x83\xe3g8\x85^6JW\xf4q\xb2\xbf\xa11\x8a)\xb7d2\xb9DQ \x00\x00\u07d4D\xa0\x1f\xb0J\xc0\xdb,\xce]\xbe(\x1e\x1cF\xe2\x8b9\xd8x\x89lj\xccg\u05f1\xd4\x00\x00\u07d4D\xa6=\x18BE\x87\xb9\xb3\a\xbf\xc3\xc3d\xae\x10\xcd\x04\xc7\x13\x89\x01\x15\x8eF\t\x13\xd0\x00\x00\xe0\x94D\xa8\x98\x9e20\x81!\xf7$f\x97\x8d\xb3\x95\xd1\xf7l:K\x8a\x01\x88P)\x9fB\xb0j\x00\x00\u07d4D\xc1\x11\v\x18\x87\x0e\xc8\x11x\xd9=!X8\xc5Q\u050ed\x89\n\xd6\xf9\x85\x93\xbd\x8f\x00\x00\u07d4D\xc1Ge\x12|\xde\x11\xfa\xb4l],\xf4\u0532\x89\x00#\xfd\x89lk\x93[\x8b\xbd@\x00\x00\xe0\x94D\xc5N\xaa\x8a\xc9@\xf9\xe8\x0f\x1et\xe8/\xc1O\x16v\x85j\x8a\x01\xab,\xf7\xc9\xf8~ \x00\x00\u07d4D\xcdwSZ\x89?\xa7\xc4\xd5\xeb:$\x0ey\u0419\xa7--\x89,s\xc97t,P\x00\x00\u07d4D\u07faP\xb8)\xbe\xcc_O\x14\u0470J\xab3 \xa2\x95\xe5\x8965\u026d\xc5\u07a0\x00\x00\u07d4D\xe2\xfd\xc6y\xe6\xbe\xe0\x1e\x93\xefJ:\xb1\xbc\xce\x01*\xbc|\x89\x16=\x19I\x00\xc5E\x80\x00\xe0\x94D\xf6/*\xaa\xbc)\xad:k\x04\xe1\xffo\x9c\xe4R\xd1\xc1@\x8a\x03\x99\x92d\x8a#\u0220\x00\x00\u07d4D\xff\xf3{\xe0\x1a8\x88\u04f8\xb8\u1200\xa7\xdd\xef\xee\xea\u04c9\x0e\f[\xfc}\xae\x9a\x80\x00\u07d4E\x06\xfe\x19\xfaK\x00k\xaa9\x84R\x9d\x85\x16\xdb++P\xab\x89lk\x93[\x8b\xbd@\x00\x00\u07d4E\x1b6\x99G[\xed]y\x05\xf8\x90Z\xa3Eo\x1e\u05c8\xfc\x89\x8a\xc7#\x04\x89\xe8\x00\x00\x00\u0794E\x1bpp%\x9b\u06e2q\x00\xe3n#B\x8aS\xdf\xe3\x04\u9239\x8b\xc8)\xa6\xf9\x00\x00\u07d4E'+\x8fb\xe9\xf9\xfa\x8c\xe0D \u1ba3\xeb\xa9hn\xac\x89\xd8\xd7&\xb7\x17z\x80\x00\x00\xe0\x94E+d\u06ce\xf7\xd6\u07c7\u01c8c\x9c\"\x90\xbe\x84\x82\xd5u\x8a\x01\xb1\xaeMn.\xf5\x00\x00\x00\u07d4E>5\x9a3\x97\x94LZ'Z\xb1\xa2\xf7\n^Z?i\x89\x89\r\x02\xabHl\xed\xc0\x00\x00\u07d4EI\xb1Yy%_~e\xe9\x9b\rV\x04\u06d8\xdf\xca\u023f\x89\xd8\xd7&\xb7\x17z\x80\x00\x00\u07d4EKa\xb3D\xc0\xef\x96Qy#\x81U\xf2w\u00c2\x9d\v8\x89lk\x93[\x8b\xbd@\x00\x00\xe0\x94EO\x01A\xd7!\xd3<\xbd\xc4\x10\x18\xbd\x01\x11\x9a\xa4xH\x18\x8a\x01EB\xba\x12\xa37\xc0\x00\x00\u07d4ES3\x90\xe3@\xfe\r\xe3\xb3\xcf_\xb9\xfc\x8e\xa5R\xe2\x9eb\x89O%\x91\xf8\x96\xa6P\x00\x00\u07d4ES\x96\xa4\xbb\u067a\u8bdf\xb7\xc4\xd6MG\x1d\xb9\xc2E\x05\x89\b\xbaR\xe6\xfcE\xe4\x00\x00\u07d4E[\x92\x96\x92\x1at\xd1\xfcAa\u007fC\xb80>o>\xd7l\x89\u3bb5sr@\xa0\x00\x00\u07d4E\\\xb8\xee9\xff\xbcu#1\xe5\xae\xfcX\x8e\xf0\xeeY4T\x8965F:x\r\xef\x80\x00\u07d4Ej\u0b24\x8e\xbc\xfa\xe1f\x06\x02PR_c\x96^v\x0f\x89\x10CV\x1a\x88)0\x00\x00\u07d4Eo\x8dtf\x82\xb2$g\x93I\x06M\x1b6\x8c|\x05\xb1v\x89\u0213\u041c\x8fQP\x00\x00\u07d4Ep)\xc4i\xc4T\x8d\x16\x8c\xec>e\x87.D(\xd4+g\x89lk\x93[\x8b\xbd@\x00\x00\u07d4Eq\xdeg+\x99\x04\xba\xd8t6\x92\xc2\x1cO\xdc\xeaL.\x01\x89\xd8\xd7&\xb7\x17z\x80\x00\x00\u07d4Ex\x1b\xbew\x14\xa1\xc8\xf7;\x1cty!\xdfO\x84'\x8bp\x89lk\x93[\x8b\xbd@\x00\x00\u07d4E{\xce\xf3}\xd3\xd6\v-\xd0\x19\xe3\xfea\xd4k?\x1erR\x89\x01\x15\x8eF\t\x13\xd0\x00\x00\xe0\x94E\x8e<\u025e\x94xD\xa1\x8ejB\x91\x8f\xef~\u007f_^\xb3\x8a\a\xb5?y\xe8\x88\xda\xc0\x00\x00\u07d4E\x93\x93\xd6:\x06>\xf3r\x1e\x16\xbd\x9f\xdeE\ue77dw\xfb\x89j\xba\u05a3\xc1S\x05\x00\x00\u07d4E\xa5p\xdc\xc2\t\f\x86\xa6\xb3\xea)\xa6\bc\xdd\xe4\x1f\x13\xb5\x89\f\x9a\x95\xee)\x86R\x00\x00\u07d4E\xa8 \xa0g/\x17\xdct\xa0\x81\x12\xbcd?\xd1\x16w6\u00c9\n\xd6\xc4;(\x15\xed\x80\x00\u07d4E\xb4q\x05\xfeB\xc4q-\xcen*!\xc0[\xff\xd5\xeaG\xa9\x89lk\x93[\x8b\xbd@\x00\x00\u07d4E\xbb\x82\x96R\u063f\xb5\x8b\x85'\xf0\xec\xb6!\u009e!.\u00c9lk\x93[\x8b\xbd@\x00\x00\xe0\x94E\xc0\u045f\v\x8e\x05O\x9e\x8986\xd5\xec\xaey\x01\xaf(\x12\x8a\x01\x0f\f\xf0d\xddY \x00\x00\u07d4E\xc4\xec\xb4\xee\x89\x1e\xa9\x84\xa7\xc5\xce\xfd\x8d\xfb\x001\v(P\x89kV\x05\x15\x82\xa9p\x00\x00\u07d4E\u028d\x95f\b\xf9\xe0\n/\x99t\x02\x86@\x88\x84ef\x8f\x89lk\x93[\x8b\xbd@\x00\x00\xe0\x94E\u0298b\x00;N@\xa3\x17\x1f\xb5\xca\xfa\x90(\xca\xc8\xde\x19\x8a\x02\ub3b1\xa1r\u0738\x00\x00\u07d4E\xd1\xc9\xee\xdf|\xabA\xa7y\x05{y9_T(\xd8\x05(\x89lk\x93[\x8b\xbd@\x00\x00\u07d4E\u0535M7\xa8\xcfY\x98!#_\x06/\xa9\xd1p\xed\u8909\x11\x90g;_\u0690\x00\x00\xe0\x94E\xdb\x03\xbc\xcf\u05a5\xf4\xd0&k\x82\xa2*6\x87\x92\xc7}\x83\x8a\x01\xb1\xaeMn.\xf5\x00\x00\x00\u07d4E\xe3\xa9>r\x14J\u0686\f\xbcV\xff\x85\x14Z\xda8\xc6\u0689WG=\x05\u06ba\xe8\x00\x00\u07d4E\u6378\u06fa\xba_\xc2\xcb3|b\xbc\xd0\xd6\x1b\x05\x91\x89\x89lk\x93[\x8b\xbd@\x00\x00\xe0\x94E\u6379L}\n\xb7\xacA\x85zq\xd6qG\x87\x0fNq\x8aT\xb4\v\x1f\x85+\xda\x00\x00\x00\u07d4E\xf4\xfc`\xf0\x8e\xac\xa1\x05\x98\xf03c)\x80\x1e<\x92\xcbF\x89\n\u05ce\xbcZ\xc6 \x00\x00\u07d4F\rSU\xb2\xce\xebnb\x10}\x81\xe5\x12p\xb2k\xf4V \x89l\xb7\xe7Hg\xd5\xe6\x00\x00\xe0\x94F\"O2\xf4\xec\xe5\u0206p\x90\xd4@\x9dU\xe5\v\x18C-\x8a\x01EB\xba\x12\xa37\xc0\x00\x00\u07d4F'\xc6\x06\x84&q\xab\u0782\x95\xee]\xd9L\u007fT\x954\xf4\x89\x0f\x89_\xbd\x872\xf4\x00\x00\u07d4F+g\x8bQ\xb5\x84\xf3\xedz\xda\a\v\\\u065c\v\xf7\xb8\u007f\x89\x05k\xc7^-c\x10\x00\x00\u07d4FM\x9c\x89\xcc\xe4\x84\xdf\x00\x02w\x19\x8e\xd8\a_\xa65r\u0449\x01\x15\x8eF\t\x13\xd0\x00\x00\u07d4FPNj!Z\xc8;\xcc\xf9V\xbe\xfc\x82\xabZg\x93q\u0209\x1c!(\x05\u00b4\xa5\x00\x00\xe0\x94FQ\xdcB\x0e\b\xc3);'\xd2Ix\x90\xebP\":\xe2\xf4\x8a\x04<3\xc1\x93ud\x80\x00\x00\u07d4FS\x1e\x8b\x1b\xde\t\u007f\u07c4\x9dm\x11\x98\x85`\x8a\x00\x8d\xf7\x89\n\u05ce\xbcZ\xc6 \x00\x00\u07d4Fb\x92\xf0\xe8\rC\xa7\x87t'u\x90\xa9\xebE\x96\x12\x14\xf4\x894\x95tD\xb8@\xe8\x00\x00\xe0\x94Fb\xa1v^\xe9!\x84-\u0708\x89\x8d\x1d\xc8bu\x97\xbd~\x8a\x02\x1e\x19\xe0\u027a\xb2@\x00\x00\u07d4Fe\xe4s\x96\xc7\u06d7\xeb*\x03\xd9\bc\xd5\u053a1\x9a\x94\x89 \x86\xac5\x10R`\x00\x00\u07d4Fo\xdak\x9bX\xc5S'P0j\x10\xa2\xa8\xc7h\x10;\a\x89\n\xd6\xee\xdd\x17\xcf;\x80\x00\u07d4Fq$\xae\u007fE/&\xb3\xd5t\xf6\b\x88\x94\xfa]\x1c\xfb;\x89\x92^\x06\xee\xc9r\xb0\x00\x00\u0794Fr*6\xa0\x1e\x84\x1d\x03\xf7\x80\x93^\x91}\x85\u0566z\xbd\x88\xce\xc7o\x0eqR\x00\x00\u07d4Fw\x9aVV\xff\x00\xd7>\xac:\xd0\u00cbl\x850\x94\xfb@\x89\f\x82S\xc9lj\xf0\x00\x00\u07d4Fw\xb0N\x03C\xa3!1\xfdj\xbb9\xb1\xb6\x15k\xba=[\x89\n\u05ce\xbcZ\xc6 \x00\x00\u07d4F}Y\x88$\x9ahaG\x16e\x98@\xed\n\xe6\xf6\xf4W\xbc\x89\x15\x01\xa4\x8c\xef\xdf\xde\x00\x00\u07d4F~\x0e\xd5O;v\xae\x066\x17n\aB\b\x15\xa0!sn\x89lk\x93[\x8b\xbd@\x00\x00\u07d4F~\xa1\x04E\x82~\xf1\xe5\x02\xda\xf7k\x92\x8a \x9e\r@2\x89lk\x93[\x8b\xbd@\x00\x00\xe0\x94F\u007f\xbfAD\x16\x00u\u007f\xe1X0\xc8\xcd_O\xfb\xbb\xd5`\x8a\x02\x1e\x19\xe0\u027a\xb2@\x00\x00\xe0\x94F\x93Xp\x932\xc8+\x88~ \xbc\xdd\xd0\"\x0f\x8e\u06e7\u040a\x03\xa9\u057a\xa4\xab\xf1\xd0\x00\x00\u07d4F\x97\xba\xaf\x9c\xcb`?\xd3\x040h\x9dCTE\xe9\u024b\xf5\x89\n\xd2\x01\xa6yO\xf8\x00\x00\u07d4F\xa3\v\x8a\x80\x891!tE\xc3\xf5\xa9>\x88,\x03E\xb4&\x89\r\x8d\xb5\xeb\u05f2c\x80\x00\u07d4F\xa40\xa2\u0528\x94\xa0\u062a?\xea\xc6\x156\x14\x15\xc3\xf8\x1f\x89lk\x93[\x8b\xbd@\x00\x00\u07d4F\xaaP\x18pg~\u007f\nPHv\xb4\xe8\x80\x1a\n\xd0\x1cF\x89+^:\xf1k\x18\x80\x00\x00\u07d4F\xbf\u0172\a\xeb \x13\xe2\xe6\x0fw_\xec\xd7\x18\x10\u0159\f\x89T\x06\x923\xbf\u007fx\x00\x00\u07d4F\xc1\xaa\"D\xb9\u0229W\u028f\xacC\x1b\x05\x95\xa3\xb8h$\x89\xd8\xd7&\xb7\x17z\x80\x00\x00\u07d4F\xd8\x061(B\x03\xf6(\x8e\xcdNWX\xbb\x9dA\xd0]\xbe\x89lk\x93[\x8b\xbd@\x00\x00\u07d4G\n\xc5\xd1\xf3\xef\xe2\x8f8\x02\xaf\x92[W\x1ec\x86\x8b9}\x89lk\x93[\x8b\xbd@\x00\x00\u07d4G\x10\x10\xdaI/@\x18\x83;\b\x8d\x98r\x90\x1e\x06\x12\x91t\x89\x1b\x1a\xe4\xd6\xe2\xefP\x00\x00\u07d4G\x12T\x02e\xcb\xee\u00c4p\"\u015f\x1b1\x8dC@\n\x9e\x89\xbd\xbcA\xe04\x8b0\x00\x00\xe0\x94G\x14\u03e4\xf4k\u05bdps}u\x87\x81\x97\xe0\x8f\x88\xe61\x8a\x02\u007f>\u07f3Nn@\x00\x00\u07d4G H\xcc`\x9a\xeb$!e\uaa87\x05\x85\f\xf3\x12]\xe0\x8965\u026d\xc5\u07a0\x00\x00\u07d4G!\x92)\xe8\xcdVe\x9ae\u00a9C\xe2\u075a\x8fK\xfd\x89\x89Rf<\u02b1\xe1\xc0\x00\x00\u07d4G7\xd0B\xdcj\xe7>\xc7:\xe2Qz\u03a2\xfd\xd9d\x87\u014965\u026d\xc5\u07a0\x00\x00\u07d4GAX\xa1\xa9\xdci<\x13?e\xe4{\\:\xe2\xf7s\xa8o\x89\n\xdaUGK\x814\x00\x00\u07d4GE\xab\x18\x1a6\xaa\x8c\xbf\"\x89\xd0\xc4Qe\xbc~\xbe#\x81\x89\x02\"\xc8\xeb?\xf6d\x00\x00\u07d4GPf\xf9\xad&eQ\x96\xd5SS'\xbb\xeb\x9by)\xcb\x04\x89\xa4\xccy\x95c\u00c0\x00\x00\xe0\x94GR!\x8eT\xdeB?\x86\xc0P\x193\x91z\xea\b\xc8\xfe\u054a\x04<3\xc1\x93ud\x80\x00\x00\u07d4GZa\x93W-JNY\u05fe\t\u02d6\r\u074cS\x0e/\x89$,\xf7\x8c\xdf\a\xff\x80\x00\u07d4Gd\x8b\xed\x01\xf3\xcd2I\bNc]\x14\u06a9\xe7\xec<\x8a\x89\n\x84Jt$\xd9\xc8\x00\x00\u07d4Gh\x84\x10\xff%\xd6T\xd7.\xb2\xbc\x06\xe4\xad$\xf83\xb0\x94\x89\b\xb2\x8da\xf3\u04ec\x00\x00\u07d4GkU\x99\b\x9a?\xb6\xf2\x9clr\xe4\x9b.G@\ua00d\x89\x97\xc9\xceL\xf6\xd5\xc0\x00\x00\u07d4Gs\x0f_\x8e\xbf\x89\xacr\xef\x80\xe4l\x12\x19P8\xec\xdcI\x89\xabM\xcf9\x9a:`\x00\x00\xe0\x94G{$\xee\u80deO\u045d\x12P\xbd\vfEyJa\u028a\x01\xb1\xaeMn.\xf5\x00\x00\x00\u07d4G\x81\xa1\nM\xf5\uef02\xf4\xcf\xe1\a\xba\x1d\x8av@\xbdf\x89a\t=|,m8\x00\x00\u07d4G\x88Z\xba\xbe\xdfM\x92\x8e\x1c<q\xd7\xca@\xd5c\xedY_\x89b\xa9\x92\xe5:\n\xf0\x00\x00\u07d4G\x8d\xc0\x9a\x13\x117|\t?\x9c\u022et\x11\x1fe\xf8/9\x89\xd8\xd7&\xb7\x17z\x80\x00\x00\xe0\x94G\x8eRN\xf2\xa3\x81\xd7\f\x82X\x8a\x93\xcaz_\xa9\xd5\x1c\xbf\x8a5\xfa\x97\"o\x88\x99p\x00\x00\xe0\x94G\x92\x98\xa9\xde\x14~c\xa1\xc7\xd6\xd2\xfc\xe0\x89\xc7\xe6@\x83\xbd\x8a\x02\x1e\x19\xdd<<\ry\x80\x00\u07d4G\x9a\xbf-\xa4\u0547\x16\xfd\x97:\r\x13\xa7_S\x01P&\n\x89\x01\x15\x8eF\t\x13\xd0\x00\x00\u07d4G\xa2\x81\xdf\xf6Ag\x19xU\xbfnp^\xb9\xf2\xce\xf62\xea\x8966\xc9yd6t\x00\x00\u07d4G\xbe\xb2\x0fu\x91\x00T*\xa9=A\x11\x8b2\x11\xd6d\x92\x0e\x89lk\x93[\x8b\xbd@\x00\x00\xe0\x94G\xc2G\xf5;\x9f\xbe\xb1{\xba\a\x03\xa0\f\x00\x9f\xdb\x0fn\xae\x8a\x04<3\xc1\x93ud\x80\x00\x00\u0794G\xc7\xe5\ufd0b:\xedK|n\x82KC_5}\xf4\xc7#\x88\xfc\x93c\x92\x80\x1c\x00\x00\u07d4G\u03dc\xda\xf9/\u0259\xcc^\xfb\xb7 <a\xe4\xf1\xcd\xd4\u00c9\a\x1f\x8a\x93\xd0\x1eT\x00\x00\u07d4G\xd2\x0ej\xe4\xca\xd3\xf8)\xea\xc0~Z\xc9{f\xfd\xd5l\xf5\x8965\u026d\xc5\u07a0\x00\x00\u07d4G\u05d2\xa7Vw\x9a\xed\xf14>\x88\x83\xa6a\x9cl(\x11\x84\x89lk\x93[\x8b\xbd@\x00\x00\xe0\x94G\xe2]\xf8\x82%8\xa8Yk(\xc67\x89kM\x14<5\x1d\x8a\x11\v\xe9\xeb$\xb8\x81P\x00\x00\u07d4G\xf4ik\xd4b\xb2\r\xa0\x9f\xb8>\xd2\x03\x98\x18\xd7v%\xb3\x89\b\x13\xcaV\x90m4\x00\x00\u07d4G\xfe\xf5\x85\x84FRH\xa0\x81\r`F>\xe9>Zn\xe8\u04c9\x0fX\xcd>\x12i\x16\x00\x00\u07d4G\xffo\xebC! `\xbb\x15\x03\u05e3\x97\xfc\b\xf4\xe7\x03R\x89lk\x93[\x8b\xbd@\x00\x00\u07d4G\xff\xf4,g\x85Q\xd1A\xebu\xa6\xee9\x81\x17\xdf>J\x8d\x89\x05k\xea\xe5\x1f\xd2\xd1\x00\x00\u07d4H\x01\x0e\xf3\xb8\xe9^?0\x8f0\xa8\xcb\u007fN\xb4\xbf`\xd9e\x89lk\x93[\x8b\xbd@\x00\x00\u07d4H\n\xf5 v\x00\x9c\xa77\x81\xb7\x0eC\xb9Y\x16\xa6\"\x03\xab\x892\x19r\xf4\b=\x87\x80\x00\u07d4H\x0f1\xb9\x891\x1eA$\u01a7F_ZD\tM6\xf9\u04097\x90\xbb\x85Q7d\x00\x00\xe0\x94H\x11\x15)j\xb7\xdbRI/\xf7\xb6G\xd63)\xfb\\\xbck\x8a\x03h\xc8b:\x8bM\x10\x00\x00\u07d4H\x1e:\x91\xbf\xdc/\x1c\x84(\xa0\x11\x9d\x03\xa4\x16\x01A~\x1c\x8965\u026d\xc5\u07a0\x00\x00\u07d4H(\xe4\xcb\xe3N\x15\x10\xaf\xb7,+\ueb0aE\x13\xea\xeb\u0649\u0556{\xe4\xfc?\x10\x00\x00\xe0\x94H)\x82\xac\x1f\x1cm\x17!\xfe\xec\u0679\xc9l\xd9I\x80PU\x8a\x02\x1e\x19\xe0\u027a\xb2@\x00\x00\u07d4H0,1\x1e\xf8\xe5\xdcfAX\xddX<\x81\x19Mn\rX\x89\xb6gl\xe0\xbc\xcb\\\x00\x00\u07d4H;\xa9\x904\xe9\x00\xe3\xae\xdfaI\x9d;+\xce9\xbe\xb7\xaa\x895e\x9e\xf9?\x0f\xc4\x00\x00\u07d4HT\x8bK\xa6+\xcb/\r4\xa8\x8d\u019ah\x0eS\x9c\xf0F\x89\x05l\xf1\u02fbt2\x00\x00\u07d4Hc\x84\x979&Zc\xb0\xa2\xbf#jY\x13\xe6\xf9Y\xce\x15\x89Rf<\u02b1\xe1\xc0\x00\x00\u07d4He\x9d\x8f\x8c\x9a/\xd4Oh\u06a5]#\xa6\b\xfb\xe5\x00\u0709lk\x93[\x8b\xbd@\x00\x00\xe0\x94Hf\x9e\xb5\xa8\x01\u0637_\xb6\xaaX\xc3E\x1bpX\xc2C\xbf\x8a\x06\x8dB\xc18\u06b9\xf0\x00\x00\u07d4Hjl\x85\x83\xa8D\x84\xe3\xdfC\xa1#\x83\u007f\x8c~#\x17\u0409\x11\x87\xc5q\xab\x80E\x00\x00\u07d4Hz\xdf}p\xa6t\x0f\x8dQ\xcb\xddh\xbb?\x91\u0125\xceh\x89\x03\x9f\xba\xe8\xd0B\xdd\x00\x00\u07d4H~\x10\x85\x02\xb0\xb1\x89\uf70cm\xa4\xd0\xdbba\xee\xc6\xc0\x89g\x8a\x93 b\xe4\x18\x00\x00\xe0\x94H\x88\xfb%\xcdP\u06f9\xe0H\xf4\x1c\xa4}x\xb7\x8a'\xc7\u064a\x03\xa9\u057a\xa4\xab\xf1\xd0\x00\x00\u0794H\x934\u00b6\x95\xc8\xee\a\x94\xbd\x86B\x17\xfb\x9f\xd8\xf8\xb15\x88\xfc\x93c\x92\x80\x1c\x00\x00\u07d4H\xa3\r\xe1\xc9\x19\xd3\xfd1\x80\xe9}_+*\x9d\xbd\x96M-\x89\x02b\x9ff\xe0\xc50\x00\x00\u07d4H\xbf\x14\u05f1\xfc\x84\xeb\xf3\xc9k\xe1/{\xce\x01\xaai\xb0>\x89\x06\x81U\xa46v\xe0\x00\x00\u07d4H\xc2\ue465\aV\xd8\u039a\xbe\xebu\x89\xd2,o\xee]\xfb\x89\xae\x8ez\v\xb5u\xd0\x00\x00\u07d4H\xc5\u0197\v\x91a\xbb\x1c{z\xdf\xed\x9c\xde\u078a\x1b\xa8d\x89\xd8\xd7&\xb7\x17z\x80\x00\x00\xe0\x94H\xd2CKz}\xbb\xff\b\";c\x87\xb0]\xa2\xe5\t1&\x8a\x03\xcf\xc8.7\xe9\xa7@\x00\x00\u07d4H\xd4\xf2F\x8f\x96?\u05da\x00a\x98\xbbg\x89]-Z\xa4\u04c9K\xe4\xe7&{j\xe0\x00\x00\u07d4H\xe0\xcb\xd6\u007f\x18\xac\xdbzb\x91\xe1%M\xb3.\trs\u007f\x89\x05k\xe0<\xa3\xe4}\x80\x00\u07d4H\xf6\n5HO\xe7y+\u030a{c\x93\xd0\u0761\xf6\xb7\x17\x89\xc3(\t>a\xee@\x00\x00\u07d4H\xf8\x83\xe5g\xb46\xa2{\xb5\xa3\x12M\xbc\x84\xde\xc7u\xa8\x00\x89)\xd7n\x86\x9d\u0340\x00\x00\xe0\x94I\x01E\xaf\xa8\xb5E\"\xbb!\xf3R\xf0m\xa5\xa7\x88\xfa\x8f\x1d\x8a\x01\xf4lb\x90\x1a\x03\xfb\x00\x00\u07d4I\t\xb3\x19\x98\xea\xd4\x14\xb8\xfb\x0e\x84k\xd5\xcb\xde995\xbe\x89\xd8\xd7&\xb7\x17z\x80\x00\x00\u07d4I\x12\xd9\x02\x93\x16v\xff9\xfc4\xfe<<\xc8\xfb!\x82\xfaz\x89\x01\x15\x8eF\t\x13\xd0\x00\x00\u07d4I\x13o\xe6\xe2\x8btS\xfc\xb1kk\xbb\u9aac\xba\x837\xfd\x89lk\x93[\x8b\xbd@\x00\x00\xe0\x94I\x15a\u06cbo\xaf\xb9\x00~b\xd0P\u0082\xe9,Kk\u020a\x06ZM\xa2]0\x16\xc0\x00\x00\u07d4I\x18]\xd7\xc262\xf4lu\x94s\ubb96`\b\xcd5\x98\x89\r\xc5_\xdb\x17d{\x00\x00\u07d4I,\xb5\xf8a\xb1\x87\xf9\xdf!\xcdD\x85\xbe\xd9\vP\xff\xe2-\x89\x1b\x19\xe5\vD\x97|\x00\x00\u07d4I-\xe4j\xaf\x8f\x1dp\x8dY\u05da\xf1\xd0:\xd2\xcb`\x90/\x89lk\x93[\x8b\xbd@\x00\x00\u07d4I.p\xf0M\x18@\x8c\xb4\x1e%`70Pk5\xa2\x87k\x89\x02\"\xc8\xeb?\xf6d\x00\x00\u07d4I:g\xfe#\xde\xccc\xb1\r\xdau\xf3(v\x95\xa8\x1b\u056b\x89/\xb4t\t\x8fg\xc0\x00\x00\u07d4I=H\xbd\xa0\x15\xa9\xbf\xcf\x16\x03\x93n\xabh\x02L\xe5Q\xe0\x89\x018\xa3\x88\xa4<\x00\x00\x00\xe0\x94IBV\xe9\x9b\x0f\x9c\xd6\xe5\xeb\xca8\x99\x862R\x90\x01e\u020a\x02\xf6\xf1\a\x80\xd2,\xc0\x00\x00\u07d4IM\xecM^\xe8\x8a'q\xa8\x15\xf1\xeerd\x94/\xb5\x8b(\x89lk\x93[\x8b\xbd@\x00\x00\u07d4I[d\x1b\x1c\u07a3b\u00f4\u02fd\x0f\\\xc5\v\x1e\x17k\x9c\x8965\u026d\xc5\u07a0\x00\x00\xe0\x94Ih\xa2\xce\xdbEuU\xa19)Z\xea(wnT\x00<\x87\x8a\x02#\x1a\xef\u0266b\x8f\x00\x00\u07d4Im6U4S\n_\xc1W|\nRA\u02c8\xc4\xdapr\x89a\t=|,m8\x00\x00\xe0\x94In1\x95\x92\xb3A\xea\xcc\xd7x\u0767\xc8\x19mT\xca\xc7u\x8a\x01\xf5q\x89\x87fKH\x00\x00\u07d4IoXC\xf6\xd2L\u064d%^L#\xd1\xe1\xf0#\"uE\x89_\x17\x9f\u0526\xee\t\x80\x00\xe0\x94Ip\u04ec\xf7+[\x1f2\xa7\x00<\xf1\x02\xc6N\xe0TyA\x8a\x1d\xa5jK\b5\xbf\x80\x00\x00\u07d4Iw\xa7\x93\x9d\t9h\x94U\xce&9\xd0\xeeZL\xd9\x10\xed\x89b\xa9\x92\xe5:\n\xf0\x00\x00\u07d4Iy\x19N\xc9\xe9}\xb9\xbe\xe84;|w\xd9\xd7\xf3\xf1\u071f\x89\x01\x15\x8eF\t\x13\xd0\x00\x00\u07d4Iy4c\xe1h\x10\x83\u05ab\xd6\xe7%\u057b\xa7E\xdc\xcd\xe8\x89\x1d\x98\xe9LNG\x1f\x00\x00\u07d4I\x81\xc5\xfff\xccN\x96\x80%\x1f\xc4\xcd/\xf9\a\xcb2xe\x89(\xa8WBTf\xf8\x00\x00\u07d4I\x89\u007f\xe92\xbb\xb3\x15L\x95\u04fc\xe6\xd9;ms)\x04\u0749\xd8\xd7&\xb7\x17z\x80\x00\x00\u07d4I\x89\xe1\xab^|\xd0\aF\xb3\x93\x8e\xf0\xf0\xd0d\xa2\x02[\xa5\x89lk\x93[\x8b\xbd@\x00\x00\u07d4I\x8a\xbd\xeb\x14\xc2k{r4\xd7\x0f\u03ae\xf3a\xa7m\xffr\x89\xa2\xa1]\tQ\x9b\xe0\x00\x00\u07d4I\xa6E\xe0f}\xfd{2\xd0u\xcc$g\u074ch\t\a\u0109\a\x06\x01\x95\x8f\u02dc\x00\x00\xe0\x94I\xb7N\x16\x92e\xf0\x1a\x89\xecL\x90r\u0164\xcdr\xe4\xe85\x8a\x03h\xc8b:\x8bM\x10\x00\x00\u07d4I\xbd\xbc{\xa5\xab\xeb\xb68\x9e\x91\xa3(R \xd3E\x1b\xd2S\x8965\u026d\xc5\u07a0\x00\x00\u07d4I\xc9A\xe0\xe5\x01\x87&\xb7)\x0f\xc4s\xb4q\xd4\x1d\xae\x80\u0449\x1b\x1a\xe4\xd6\xe2\xefP\x00\x00\xe0\x94I\xc9w\x1f\xca\x19\u0579\xd2E\u0211\xf8\x15\x8f\xe4\x9fG\xa0b\x8a\x02\x1e\x19\xe0\u027a\xb2@\x00\x00\u07d4I\xcf\x1eT\xbe61\x06\xb9 r\x9d-\v\xa4o\bg\x98\x9a\x89\x0e\x87?D\x13<\xb0\x00\x00\u07d4I\xd2\u008e\xe9\xbcT^\xaa\xf7\xfd\x14\xc2|@s\xb4\xbb_\x1a\x89O\xe9\xb8\x06\xb4\r\xaf\x00\x00\u07d4I\xdd\xee\x90.\x1d\f\x99\u0471\x1a\xf3\u030a\x96\xf7\x8eM\xcf\x1a\x89\n\u03a5\xe4\xc1\x8cS\x00\x00\u07d4I\xf0(9[Z\x86\xc9\xe0\u007fwxc\x0eL.=7:w\x89\x06\xa7JP8\u06d1\x80\x00\xe0\x94J\x19 5\xe2a\x9b$\xb0p\x9dVY\x0e\x91\x83\xcc\xf2\xc1\u064a\x02\x1e\x19\xe0\u027a\xb2@\x00\x00\u07d4J@S\xb3\x1d\x0e\xe5\u06ef\xb1\xd0k\u05ec\u007f\xf3\",G\u0589K\xe4\xe7&{j\xe0\x00\x00\u07d4JC\x01p\x15-\xe5\x17&3\u0742b\xd1\a\xa0\xaf\xd9j\x0f\x89\xabM\xcf9\x9a:`\x00\x00\u07d4JG\xfc>\x17\u007fVz\x1e8\x93\xe0\x00\xe3k\xba#R\n\xb8\x89lk\x93[\x8b\xbd@\x00\x00\u07d4JR\xba\xd2\x03W\"\x8f\xaa\x1e\x99k\xedy\f\x93gK\xa7\u0409Hz\x9a0E9D\x00\x00\u07d4JS\xdc\xdbV\xceL\xdc\xe9\xf8.\xc0\xeb\x13\xd6sR\xe7\u020b\x89\u3bb5sr@\xa0\x00\x00\u07d4J_\xae;\x03r\xc20\xc1%\xd6\xd4p\x14\x037\xab\x91VV\x89V\xbcu\xe2\xd61\x00\x00\x00\u07d4Jq\x90a\xf5(T\x95\xb3{\x9d~\xf8\xa5\x1b\a\xd6\u6b2c\x89\n\xd4\xc81j\v\f\x00\x00\u07d4Js8\x92\x98\x03\x1b\x88\x16\u0329FB\x1c\x19\x9e\x18\xb3C\u0589\"8h\xb8y\x14o\x00\x00\u07d4Js]\"G\x927m3\x13g\xc0\x93\xd3\x1c\x87\x944\x15\x82\x89f\xff\xcb\xfd^Z0\x00\x00\u07d4Jt\x94\xcc\xe4HU\u0300X(B\xbe\x95\x8a\r\x1c\x00r\ue242\x1a\xb0\xd4AI\x80\x00\x00\u07d4Ju\xc3\xd4\xfao\u033d]\u0567\x03\xc1Sy\xa1\xe7\x83\u9dc9b\xa9\x92\xe5:\n\xf0\x00\x00\xe0\x94J\x81\xab\xe4\x98L|k\xefc\u0598 \xe5WC\xc6\x1f \x1c\x8a\x03d\x01\x00N\x9a\xa3G\x00\x00\u07d4J\x82iO\xa2\x9d\x9e!2\x02\xa1\xa2\t(]\xf6\xe7E\xc2\t\x89\xd8\xd7&\xb7\x17z\x80\x00\x00\u07d4J\x83\\%\x82LG\xec\xbf\u01d49\xbf?\\4\x81\xaau\u0349K\xe4\xe7&{j\xe0\x00\x00\u07d4J\x91\x802C\x91Y\xbb1[g%\xb6\x83\r\xc86\x97s\x9f\x89\x12\xa3.\xf6x3L\x00\x00\u07d4J\x97\xe8\xfc\xf4c^\xa7\xfc^\x96\xeeQu.\u00c8qk`\x89\x1d\x99E\xab+\x03H\x00\x00\u07d4J\x9a&\xfd\n\x8b\xa1\x0f\x97}\xa4\xf7|1\x90\x8d\xabJ\x80\x16\x89a\t=|,m8\x00\x00\u07d4J\xa1H\xc2\xc34\x01\xe6j+Xnew\u0132\x92\xd3\xf2@\x89\v\xb8`\xb2\x85\xf7t\x00\x00\u07d4J\xa6\x93\xb1\"\xf3\x14H*G\xb1\x1c\xc7|h\xa4\x97\x87ab\x89j\xcb=\xf2~\x1f\x88\x00\x00\u07d4J\xb2\xd3O\x04\x83O\xbftyd\x9c\xab\x92=,G%\xc5S\x89\xbe\xd1\xd0&=\x9f\x00\x00\x00\u07d4J\xc0vs\xe4/d\xc1\xa2^\xc2\xfa-\x86\xe5\xaa+4\xe09\x89lk\x93[\x8b\xbd@\x00\x00\u07d4J\u016c\xad\x00\v\x88w!L\xb1\xae\x00\xea\u0263}Y\xa0\xfd\x89\xd8\xd7&\xb7\x17z\x80\x00\x00\u07d4J\u0250ZL\xb6\xab\x1c\xfdbTn\xe5\x91s\x00\xb8|O\u07897\b\xba\xed=h\x90\x00\x00\u07d4J\u03e9\xd9N\xdaf%\xc9\u07e5\xf9\xf4\xf5\xd1\a\xc4\x03\x1f\u07c9\x02\"\xc8\xeb?\xf6d\x00\x00\u07d4J\xd0G\xfa\xe6~\xf1b\xfeh\xfe\xdb\xc2};e\xca\xf1\f6\x89j\xcb=\xf2~\x1f\x88\x00\x00\u07d4J\xd9]\x18\x8dddp\x9a\xdd%U\xfbM\x97\xfe\x1e\xbf1\x1f\x89\x12\xc1\xb6\xee\xd0=(\x00\x00\u07d4J\xdb\xf4\xaa\xe0\xe3\xefD\xf7\xddM\x89\x85\u03ef\tn\u010e\x98\x89\b!\xab\rD\x14\x98\x00\x00\u07d4J\xe2\xa0M9\t\xefENTL\xcf\xd6\x14\xbf\xef\xa7\x10\x89\xae\x89\x18\x01\x15\x9d\xf1\xee\xf8\x00\x00\xe0\x94J\xe90\x82\xe4Q\x87\xc2a`\xe6g\x92\xf5\u007f\xad5Q\xc7:\x8a\x04\x96\x15 \xda\xff\x82(\x00\x00\u07d4J\xf0\xdb\a{\xb9\xba^D>!\xe1H\xe5\x9f7\x91\x05\u0152\x89 \x86\xac5\x10R`\x00\x00\u07d4K\x06\x19\xd9\u062a1:\x951\xac}\xbe\x04\xca\rjZ\u0476\x89lk\x93[\x8b\xbd@\x00\x00\u07d4K\v\u062c\xfc\xbcS\xa6\x01\v@\xd4\u040d\xdd-\x9dib-\x89$=M\x18\"\x9c\xa2\x00\x00\u07d4K\x19\xeb\f5K\xc199`\xeb\x06\x06;\x83\x92o\rg\xb2\x89\x01\x92t\xb2Y\xf6T\x00\x00\u07d4K)C|\x97\xb4\xa8D\xbeq\u0323\xb6H\xd4\xca\x0f\u075b\xa4\x89\b$q\x984\u03ec\x00\x00\u07d4K1\xbfA\xab\xc7\\\x9a\xe2\u034f\u007f5\x16;n+tPT\x89\x14\xb5P\xa0\x13\xc78\x00\x00\u07d4K:|\u00e7\u05f0\x0e\xd5(\"!\xa6\x02Y\xf2[\xf6S\x8a\x8965\u026d\xc5\u07a0\x00\x00\xe0\x94K:\xab3^\xbb\xfa\xa8p\xccM`^}.t\xc6h6\x9f\x8a\f\xb4\x9bD\xba`-\x80\x00\x00\u07d4K<s\x88\xccv\xda=b\xd4\x00g\u06bc\xcd~\xf0C=#\x89\x05l\xd5_\xc6M\xfe\x00\x00\u07d4K=\xfb\xdbEK\xe5'\x9a;\x8a\xdd\xfd\x0e\xd1\xcd7\xa9B\r\x89lk\x93[\x8b\xbd@\x00\x00\u07d4KG\x0f{\xa00\xbc|\xfc\xf38\u053f\x042\xa9\x1e.\xa5\xff\x89lk\x93[\x8b\xbd@\x00\x00\u07d4KS\xaeY\u01c4\xb6\xb5\xc46\x16\xb9\xa0\x80\x95X\xe6\x84\xe1\f\x89A\rXj \xa4\xc0\x00\x00\u07d4KX\x10\x1fD\xf7\xe3\x89\xe1-G\x1d\x165\xb7\x16\x14\xfd\xd6\x05\x89\b\xacr0H\x9e\x80\x00\x00\u07d4K\\\xdb\x1eB\x8c\x91\xdd|\xb5Jj\xedEq\xda\x05K\xfeR\x89\x04\xc5>\xcd\xc1\x8a`\x00\x00\u07d4K`\xa3\xe2S\xbf8\xc8\xd5f \x10\xbb\x93\xa4s\xc9e\xc3\xe5\x89P\xc5\xe7a\xa4D\b\x00\x00\u07d4Kt\xf5\xe5\x8e.\xdfv\xda\xf7\x01Q\x96J\v\x8f\x1d\xe0f<\x89\x11\x90\xaeID\xba\x12\x00\x00\u07d4Kv!f\xdd\x11\x18\xe8Ci\xf8\x04\xc7_\x9c\xd6W\xbfs\f\x89\x1b\x1a\xe4\xd6\xe2\xefP\x00\x00\u07d4Ky.)h>\xb5\x86\u353b3Rl`\x01\xb3\x97\x99\x9e\x89 \x86\xac5\x10R`\x00\x00\u07d4K\x90N\x93K\xd0\u030b p_\x87\x9e\x90[\x93\xea\f\xcc0\x89lk\x93[\x8b\xbd@\x00\x00\xe0\x94K\x92\x06\xbakT\x9a\x1a\u007f\x96\x9e\x1d]\xba\x86u9\xd1\xfag\x8a\x01\xab,\xf7\xc9\xf8~ \x00\x00\u07d4K\x98N\xf2lWn\x81Z.\xae\xd2\xf5\x17\u007f\a\u06f1\xc4v\x89T\x91YV\xc4\t`\x00\x00\u07d4K\x9e\x06\x8f\xc4h\tv\xe6\x15\x04\x91)\x85\xfd\\\xe9K\xab\r\x89$=M\x18\"\x9c\xa2\x00\x00\u07d4K\xa0\xd9\xe8\x96\x01w+IhG\xa2\xbbC@\x18g\x87\xd2e\x8965\u026d\xc5\u07a0\x00\x00\u07d4K\xa5:\xb5I\xe2\x01m\xfa\"<\x9e\u0563\x8f\xad\x91(\x8d\a\x89K\xe4\xe7&{j\xe0\x00\x00\xe0\x94K\xa8\xe0\x11\u007f\xc0\xb6\xa3\xe5k$\xa3\xa5\x8f\xe6\xce\xf4B\xff\x98\x8a\x011\xbe\xb9%\xff\xd3 \x00\x00\u07d4K\xac\x84j\xf4\x16\x9f\x1d\x95C\x1b4\x1d\x88\x00\xb2!\x80\xaf\x1a\x89\x01\x15\x8eF\t\x13\xd0\x00\x00\u07d4K\xb6\xd8k\x83\x14\xc2-\x8d7\xeaQm\x00\x19\xf1V\xaa\xe1-\x8965\u026d\xc5\u07a0\x00\x00\xe0\x94K\xb9e\\\xfb*6\xea|cz{\x85\x9bJ1T\xe2n\xbe\x8a\x03c\\\x9a\xdc]\xea\x00\x00\x00\xe0\x94K\xbc\xbf8\xb3\xc9\x01c\xa8K\x1c\u04a9;X\xb2\xa34\x8d\x87\x8a\x01\xb1\xaeMn.\xf5\x00\x00\x00\xe0\x94K\xd6\xdd\f\xff#@\x0e\x170\xba{\x89E\x04W}\x14\xe7J\x8a+\xa0\xcc\xdd\xd0\xdfs\xb0\x00\x00\u07d4K\xe8b\x8a\x81T\x87N\x04\x8d\x80\xc1B\x18\x10\"\xb1\x80\xbc\xc1\x89\x03@\xaa\xd2\x1b;p\x00\x00\u07d4K\xe9\rA!)\u0564\xd0BCa\xd6d\x9dNG\xa6#\x16\x897\b\xba\xed=h\x90\x00\x00\xe0\x94K\xea(\x8e\xeaB\u0115^\xb9\xfa\xad*\x9f\xafG\x83\xcb\u076c\x8a\x06\x18\xbe\x16c\u012fI\x00\x00\u07d4K\xf4G\x97\x99\xef\x82\xee\xa2\tC7OV\xa1\xbfT\x00\x1e^\x89\u0556{\xe4\xfc?\x10\x00\x00\u07d4K\xf8\xbf\x1d5\xa211Wd\xfc\x80\x01\x80\x9a\x94\x92\x94\xfcI\x89\x03\x9f\xba\xe8\xd0B\xdd\x00\x00\u07d4K\xf8\xe2oL'\x90\xdae3\xa2\xac\x9a\xba\xc3\u019a\x19\x943\x89\n\u05ce\xbcZ\xc6 \x00\x00\u0794L\n\xcaP\x8b<\xaf^\xe0(\xbcp}\xd1\xe8\x00\xb88\xf4S\x88\xfc\x93c\x92\x80\x1c\x00\x00\xe0\x94L\v\x15\x15\xdf\xce\u05e1>\x13\xee\x12\xc0\xf5#\xaePO\x03+\x8a\n\x96\x81c\xf0\xa5{@\x00\x00\u07d4L\x13\x98\f2\xdc\xf3\x92\vx\xa4\xa7\x903\x12\x90|\x1b\x12?\x89\x03A\x00\x15\xfa\xae\f\x00\x00\u07d4L\x15y\xaf3\x12\xe4\xf8\x8a\xe9<h\xe9D\x9c.\x9ah\xd9\u0109lk\x93[\x8b\xbd@\x00\x00\xe0\x94L#\xb3p\xfc\x99+\xb6|\xec\x06\xe2g\x15\xb6/\v:J\u00ca\x02\x1e\x19\xe0\u027a\xb2@\x00\x00\u07d4L$\xb7\x8b\xaf+\xaf\xc7\xfc\u0190\x16Bk\xe9s\xe2\nP\xb2\x89\xa2\xa1]\tQ\x9b\xe0\x00\x00\xe0\x94L/\x1a\xfe\xf7\u0146\x8cD\x83/\xc7|\xb0;U\xf8\x9emn\x8a\x04<3\xc1\x93ud\x80\x00\x00\u07d4L7{\xb0:\xb5,L\xb7\x9b\xef\xa1\xdd\x11I\x82\x92LJ\xe9\x89c\x16\x03\xcc\u04cd\xd7\x00\x00\u07d4L>\x95\xcc9W\xd2R\xce\v\xf0\xc8}[O\"4g.p\x89\x87\x86x2n\xac\x90\x00\x00\u07d4LB<v\x93\r\a\xf9<G\xa5\xccOaWE\xc4Z\x9dr\x89\x05k\xc7^-c\x10\x00\x00\u07d4LE\xd4\u0267%\xd1\x11\x12\xbf\xcb\xca\x00\xbf1\x18l\u02ad\xb7\x89\x15\xaf\x1dx\xb5\x8c@\x00\x00\u07d4LNo\x13\xfb^?p\xc3v\x02b\xa0>1y\x82i\x1d\x10\x89\x05k\xc7^-c\x10\x00\x00\u07d4LZ\xfe@\xf1\x8f\xfcH\u04e1\xae\xc4\x1f\u009d\xe1y\xf4\u0497\x89lk\x93[\x8b\xbd@\x00\x00\u07d4L[=\xc0\xe2\xb96\x0f\x91(\x9b\x1f\xe1<\xe1,\x0f\xbd\xa3\xe1\x89lk\x93[\x8b\xbd@\x00\x00\u07d4Lfk\x86\xf1\xc5\ue324\x12\x85\xf5\xbd\xe4\xf7\x90R\b\x14\x06\x89\x1b\x1a\xe4\xd6\xe2\xefP\x00\x00\u07d4Lik\xe9\x9f:i\x04@\xc3CjY\xa7\xd7\xe97\u05ba\r\x89\xbb\x91%T\"c\x90\x00\x00\u07d4Lj$\x8f\xc9}p]\xefI\\\xa2\aY\x16\x9e\xf0\xd3dq\x89)3\x1eeX\xf0\xe0\x00\x00\u07d4Lj\x9d\xc2\u02b1\n\xbb.|\x13p\x06\xf0\x8f\ucd77y\xe1\x89\x1b\r\x04 /G\xec\x00\x00\u07d4Lk\x93\xa3\xbe\xc1cIT\f\xbf\xca\xe9l\x96!\xd6dP\x10\x89lk\x93[\x8b\xbd@\x00\x00\u07d4Lu\x98\x13\xad\x13\x86\xbe\xd2\u007f\xfa\xe9\xe4\x81^60\u0323\x12\x89lk\x93[\x8b\xbd@\x00\x00\xe0\x94Lv\f\xd9\xe1\x95\xeeO-k\xce%\x00\xff\x96\xda|C\ue44a\f\xb4\x9bD\xba`-\x80\x00\x00\u07d4Lv{e\xfd\x91\x16\x1fO\xbd\xccji\xe2\xf6\xadq\x1b\xb9\x18\x89'\b\x01\xd9F\xc9@\x00\x00\u07d4L~.+w\xad\f\xd6\xf4J\xcb(a\xf0\xfb\x8b(u\x0e\xf9\x89\x01\x15\x8eF\t\x13\xd0\x00\x00\u07d4L\x85\xed6/$\xf6\xb9\xf0L\xdf\xcc\xd0\"\xaeSQG\u02f9\x89QP\xae\x84\xa8\xcd\xf0\x00\x00\u07d4L\x93[\xb2Pw\x8b<L\u007f~\a\xfc%\x1f\xa601J\xab\x89QP\xae\x84\xa8\xcd\xf0\x00\x00\u07d4L\x99y\x92\x03l[C:\xc3=%\xa8\xea\x1d\xc3\xd4\xe4\xe6\u0609\x01\x95;=J\xb1h\x00\x00\u07d4L\x99\xda\xe9d\x81\xe8\a\xc1\xf9\x9f\x8b\u007f\xbd\xe2\x9buG\u017f\x89\b!\xab\rD\x14\x98\x00\x00\u07d4L\x9a\x86*\xd1\x15\xd6\xc8'N\u0439D\xbd\u05a5P\x05\x10\xa7\x89\x05k\xc7^-c\x10\x00\x00\xe0\x94L\xa7\x83\xb5V\xe5\xbfS\xaa\x13\xc8\x11f\x13\xd6W\x82\u0276B\x8a\x05V\x18@\xb4\xad\x83\xc0\x00\x00\u07d4L\xa7\xb7\x17\u067c\x87\x93\xb0N\x05\x1a\x8d#\xe1d\x0f[\xa5\xe3\x89C\xb5\x14T\x9e\xcfb\x00\x00\u07d4L\xa8\xdbJ^\xfe\xfc\x80\xf4\u035b\xbc\u03302e\x93\x132\xb6\x89\n\u05ce\xbcZ\xc6 \x00\x00\u07d4L\xac\x91\xfb\x83\xa1G\xd2\xf7l2g\x98K\x91\ny\x933H\x89uy*\x8a\xbd\xef|\x00\x00\u07d4L\xad\xf5s\xceL\xee\u01cb\x8e\x1b!\xb0\xedx\xeb\x11;,\x0e\x89lk\x93[\x8b\xbd@\x00\x00\u07d4L\xb5\xc6\xcdq<\xa4G\xb8H\xae/V\xb7a\xca\x14\u05edW\x89\x0e~\xeb\xa3A\vt\x00\x00\u07d4L\xc2,\x9b\u026d\x05\xd8u\xa3\x97\xdb\xe8G\xed\"\x1c\x92\fg\x89lk\x93[\x8b\xbd@\x00\x00\u07d4L\u0430\xa6CcbY\\\xea\xde\x05.\xbc\x9b\x92\x9f\xb6\xc6\xc0\x89lk\x93[\x8b\xbd@\x00\x00\u07d4L\xdaA\xddS9\x91)\a\x94\xe2*\xe3$\x14>0\x9b==\x89\x82\x1a\xb0\xd4AI\x80\x00\x00\u07d4L\xee\x90\x1bJ\u0231V\xc5\xe2\xf8\xa6\xf1\xbe\xf5r\xa7\xdc\xeb~\x8965\u026d\xc5\u07a0\x00\x00\u07d4L\xef\xbe#\x98\xe4}R\u73743L\x8bivu\U00053b89\xd9o\u0390\u03eb\xcc\x00\x00\u07d4L\xf5S{\x85\x84/\x89\xcf\xee5\x9e\xaeP\x0f\xc4I\xd2\x11\x8f\x8965\u026d\xc5\u07a0\x00\x00\xe0\x94M\bG\x1dh\x00z\xff*\xe2y\xbc^?\xe4\x15o\xbb\xe3\u078a\bxg\x83&\xea\xc9\x00\x00\x00\u07d4M \x01\x10\x12@\b\xd5ov\x98\x12VB\f\x94jo\xf4\\\x89\n\xd6\xee\xdd\x17\xcf;\x80\x00\u07d4M$\xb7\xacG\xd2\xf2}\xe9\tt\xba=\xe5\xea\xd2\x03TK\u0349\x05k\xc7^-c\x10\x00\x00\u0794M)\xfcR:,\x16)S!!\u0699\x98\u9d6b\x9d\x1bE\x88\xdbD\xe0I\xbb,\x00\x00\u07d4M8\xd9\x0f\x83\xf4Q\\\x03\xccx2j\x15M5\x8b\u0602\xb7\x89\n\ad\a\xd3\xf7D\x00\x00\u07d4ML\xf5\x80t)a^0\xcd\xfa\xce\x1eZ\xaeM\xad0U\xe6\x89 \x86\xac5\x10R`\x00\x00\u07d4MW\xe7\x16\x87l\f\x95\xef^\xae\xbd5\xc8\xf4\x1b\x06\x9bk\xfe\x89lk\x93[\x8b\xbd@\x00\x00\xe0\x94Mg\U000ab159\xfe\xf5\xfcA9\x99\xaa\x01\xfd\u007f\xcep\xb4=\x8a\x02\x1e\x19\xe0\u027a\xb2@\x00\x00\u07d4Mn\x8f\xe1\t\xcc\xd2\x15\x8eM\xb1\x14\x13/\xe7_\xec\u023e[\x89\x01[5W\xf1\x93\u007f\x80\x00\xe0\x94Mq\xa6\xeb=\u007f2~\x184'\x8e(\v\x03\x9e\xdd\xd3\x1c/\x8a\x01EB\xba\x12\xa37\xc0\x00\x00\u07d4M|\xfa\xa8L\xb31\x06\x80\n\x8c\x80/\xb8\xaaF8\x96\u0159\x89a\t=|,m8\x00\x00\u07d4M\x80\x10\x93\xc1\x9c\xa9\xb8\xf3B\xe3<\xc9\xc7{\xbdL\x83\x12\u03c9\x12\xb3\xe7\xfb\x95\u0364\x80\x00\u07d4M\x82\x88\x94u/o%\x17]\xaf!w\tD\x87\x95Ko\x9f\x89O!+\xc2\u011c\x83\x80\x00\xe0\x94M\x82\xd7p\f\x12;\xb9\x19A\x9b\xba\xf0Fy\x9ck\x0e,f\x8a\x04<3\xc1\x93ud\x80\x00\x00\u07d4M\x83m\x9d;\x0e,\xbdM\xe0PYo\xaaI\f\xff\xb6\r]\x89\x10CV\x1a\x88)0\x00\x00\u07d4M\x86\x97\xaf\x0f\xbf,\xa3n\x87h\xf4\xaf\"\x135phZ`\x89\x01\x15\x8eF\t\x13\xd0\x00\x00\u07d4M\x92y\x96 )\xa8\xbdEc\x977\xe9\x8bQ\x1e\xff\aL!\x89Hz\x9a0E9D\x00\x00\u07d4M\x93io\xa2HY\xf5\u0493\x9a\xeb\xfaT\xb4\xb5\x1a\xe1\xdc\u0309\x01\t\x10\xd4\xcd\xc9\xf6\x00\x00\u07d4M\x9cw\xd0u\f^o\xbc$\u007f/\u05d2thl\xb3S\u0589\x01\x15\x8eF\t\x13\xd0\x00\x00\u07d4M\xa5\xed\u0188\xb0\xcbb\xe1@=\x17\x00\xd9\u0739\x9f\xfe?\u04c9lk\x93[\x8b\xbd@\x00\x00\xe0\x94M\xa8\x03\ai\x84K\xc3A\x86\xb8\\\xd4\xc74\x88I\xffI\xe9\x8a\x02\x1e\x19\xe0\u027a\xb2@\x00\x00\u07d4M\xb1\xc4:\x0f\x83M}\x04x\xb8\x96\ag\xec\x1a\xc4L\x9a\xeb\x89/Q\x810V'7\x00\x00\u07d4M\xb2\x12\x84\xbc\xd4\xf7\x87\xa7Ue\x00\xd6\xd7\xd8\xf3f#\xcf5\x89i(7Ow\xa3c\x00\x00\u07d4M\xc3\xda\x13\xb2\xb4\xaf\xd4O]\r1\x89\xf4D\xd4\xdd\xf9\x1b\x1b\x89lk\x93[\x8b\xbd@\x00\x00\u07d4M\u013f^u\x89\xc4{(7\x8du\x03\u03d6H\x80a\u06fd\x89_h\xe8\x13\x1e\u03c0\x00\x00\u07d4M\xc9\u057bK\x19\xce\u0354\xf1\x9e\xc2] \x0e\xa7/%\xd7\xed\x89lk\x93[\x8b\xbd@\x00\x00\xe0\x94M\xcd\x11\x81X\x18\xae)\xb8]\x016sI\xa8\xa7\xfb\x12\xd0k\x8a\x01\xacB\x86\x10\x01\x91\xf0\x00\x00\u07d4M\xcfb\xa3\xde?\x06\x1d\xb9\x14\x98\xfda\x06\x0f\x1fc\x98\xffs\x89lj\xccg\u05f1\xd4\x00\x00\u07d4M\xd11\xc7J\x06\x8a7\xc9\n\xde\xd4\xf3\t\xc2@\x9fdx\u04c9\x15\xaf9\u4ab2t\x00\x00\xe0\x94M\u0767Xk\"7\xb0S\xa7\xf3(\x9c\xf4`\xdcW\xd3z\t\x8a\x02\x1e\x19\xe0\u027a\xb2@\x00\x00\u07d4M\xe3\xfe4\xa6\xfb\xf64\xc0Q\x99\u007fG\xcc\u007fHy\x1fX$\x89l]\xb2\xa4\xd8\x15\xdc\x00\x00\u07d4M\xf1@\xbaye\x85\xddT\x891[\xcaK\xbah\n\u06f8\x18\x89\x90\xf54`\x8ar\x88\x00\x00\u07d4N\x02\ay\xb5\xdd\xd3\xdf\"\x8a\x00\xcbH\xc2\xfc\x97\x9d\xa6\xae8\x89lk\x93[\x8b\xbd@\x00\x00\u07d4N\v\xd3$s\xc4\xc5\x1b\xf2VT\xde\xf6\x9fy|k)\xa22\x89V\xc9]\xe8\xe8\xca\x1d\x00\x00\u07d4N\"%\xa1\xbbY\xbc\x88\xa21ft\xd33\xb9\xb0\xaf\xcafU\x89\bg\x0e\x9e\xc6Y\x8c\x00\x00\u07d4N#\x10\x19\x1e\xad\x8d;\xc6H\x98s\xa5\xf0\xc2\xeck\x87\u1f8965\u026d\xc5\u07a0\x00\x00\u07d4N#-S\xb3\u6f8f\x89Sa\xd3\x1c4\xd4v+\x12\xc8.\x89_h\xe8\x13\x1e\u03c0\x00\x00\u07d4N+\xfaJFo\x82g\x1b\x80\x0e\xeeBj\xd0\f\a\x1b\xa1p\x89\xd8\xd7&\xb7\x17z\x80\x00\x00\u07d4N>\xda\u0506M\xabd\xca\xe4\xc5Azvw@S\xdcd2\x89 \b\xfbG\x8c\xbf\xa9\x80\x00\u07d4NC\x18\xf5\xe1>\x82JT\xed\xfe0\xa7\xedO&\xcd=\xa5\x04\x89lk\x93[\x8b\xbd@\x00\x00\u07d4N[w\xf9\x06aY\xe6\x15\x93?-\xdatw\xfaNG\xd6H\x89\n\u05ce\xbcZ\xc6 \x00\x00\xe0\x94Nf\x00\x80b\x89EJ\u03630\xa2\xa3U`\x10\u07ec\xad\xe6\x8a\x01EB\xba\x12\xa37\xc0\x00\x00\u07d4Ns\xcf#y\xf1$\x86\x0fs\xd6\xd9\x1b\xf5\x9a\xcc\\\xfc\x84[\x89\x02,\xa3X|\xf4\xeb\x00\x00\xe0\x94Nz\xa6~\x12\x18>\xf9\xd7F\x8e\xa2\x8a\xd29\xc2\xee\xf7\x1bv\x8a\x01\n\xfc\x1a\xde;N\xd4\x00\x00\xe0\x94N{TGM\x01\xfe\xfd8\x8d\xfc\xd5;\x9ff&$A\x8a\x05\x8a\x01\xb1\xaeMn.\xf5\x00\x00\x00\xe0\x94N\x89.\x80\x81\xbf6\xe4\x88\xfd\xdb;&0\xf3\xf1\xe8\xda0\u048a\x02\x8a\xba0u$Q\xfc\x00\x00\xe0\x94N\x8amcH\x9c\xcc\x10\xa5\u007f\x88_\x96\xeb\x04\xec\xbbT`$\x8a\x03\xea\xe3\x13\x0e\u0316\x90\x00\x00\u07d4N\x8eG\xae;\x1e\xf5\f\x9dT\xa3\x8e\x14 \x8c\x1a\xbd6\x03\u0089y(\xdb\x12vf\f\x00\x00\u0794N\x90\u03312X\xac\xaa\x9fO\xeb\xc0\xa3B\x92\xf9Y\x91\xe20\x88\xdbD\xe0I\xbb,\x00\x00\u07d4N\xa5n\x11\x12d\x1c\x03\x8d\x05e\xa9\u0096\xc4c\xaf\xef\xc1~\x89\t\xdd\xc1\xe3\xb9\x01\x18\x00\x00\xe0\x94N\xa7\x0f\x041?\xaee\xc3\xff\"J\x05\\=-\xab(\xdd\u07ca\x04<0\xfb\b\x84\xa9l\x00\x00\u07d4N\xb1EKW8\x05\u022c\xa3~\xde\xc7\x14\x9aA\xf6\x12\x02\xf4\x89\x10CV\x1a\x88)0\x00\x00\u07d4N\xb8{\xa8x\x8e\xba\r\xf8~[\x9b\xd5\n\x8eE6\x80\x91\xc1\x89\x01\x15\x8eF\t\x13\xd0\x00\x00\u07d4N\xbcV)\xf9\xa6\xa6k,\xf36:\u0109\\\x03H\u8fc7\x8967\tlK\xcci\x00\x00\u07d4N\xc7h)^\xea\xba\xfcB\x95\x84\x15\xe2+\xe2\x16\xcd\xe7v\x18\x89\x03;\x1d\xbc9\xc5H\x00\x00\u07d4N\xcc\x19\x94\x8d\xd9\u0347\xb4\xc7 \x1a\xb4\x8eu\x8f(\xe7\xccv\x89\x1b\x1d\xaba\u04ead\x00\x00\u07d4N\xd1M\x81\xb6\v#\xfb%\x05M\x89%\u07e5s\u072eah\x89\x12nr\xa6\x9aP\xd0\x00\x00\xe0\x94N\xe1<\rA \vF\u045d\xee\\K\xce\xc7\x1d\x82\xbb\x8e8\x8a\x01\xab\xee\x13\u033e\ufbc0\x00\u07d4N\xea\xd4\n\xad\x8cs\xef\b\xfc\x84\xbc\n\x92\xc9\t/j6\xbf\x89\x01s\x17\x90SM\xf2\x00\x00\u07d4N\xeb\xe8\f\xb6\xf3\xaeY\x04\xf6\xf4\xb2\x8d\x90\u007f\x90q\x89\xfc\xab\x89lj\xccg\u05f1\xd4\x00\x00\u07d4N\xeb\xf1 ]\f\xc2\f\xeel\u007f\x8f\xf3\x11_V\u050f\xba&\x89\x01\r:\xa56\xe2\x94\x00\x00\u07d4N\xf1\xc2\x14c:\xd9\xc0p;N#t\xa2\xe3>>B\x92\x91\x89Hz\x9a0E9D\x00\x00\u07d4N\xfc\xd9\u01df\xb43L\xa6${\n3\xbd\x9c\xc32\b\xe2r\x89Hz\x9a0E9D\x00\x00\xe0\x94O\x06$k\x8dK\u0496a\xf4>\x93v\"\x01\u0486\x93Z\xb1\x8a\x01\x059O\xfcF6\x11\x00\x00\u07d4O\x15+/\xb8e\x9dCwn\xbb\x1e\x81g:\xa8Ai\xbe\x96\x89lk\x93[\x8b\xbd@\x00\x00\u07d4O\x17\u007f\x9dV\x95=\xedq\xa5a\x1f93\"\xc3\x02y\x89\\\x89\rU\uf422\xda\x18\x00\x00\u07d4O\x1a-\xa5JLm\xa1\x9d\x14$\x12\xe5n\x81WA\xdb#%\x89\x05k\xc7^-c\x10\x00\x00\u07d4O#\xb6\xb8\x17\xff\xa5\xc6d\xac\xda\u05db\xb7\xb7&\xd3\n\xf0\xf9\x89_h\xe8\x13\x1e\u03c0\x00\x00\xe0\x94O&i\f\x99+z1*\xb1.\x13\x85\xd9J\xcdX(\x8e{\x8a\x02\xf6\xf1\a\x80\xd2,\xc0\x00\x00\u07d4O+G\xe2wZ\x1f\xa7\x17\x8d\xad\x92\x98Z[\xbeI;\xa6\u0589\n\u05ce\xbcZ\xc6 \x00\x00\u07d4O:HT\x91\x11E\xea\x01\xc6D\x04K\xdb.Z\x96\n\x98/\x89\xd8\xd7&\xb7\x17z\x80\x00\x00\u07d4O?,g0i\xac\x97\xc2\x026\a\x15)\x81\xf5\xcd`c\xa0\x89 \x86\xac5\x10R`\x00\x00\xe0\x94OJ\x9b\xe1\f\xd5\xd3\xfb]\xe4\x8c\x17\xbe)o\x89V\x90d[\x8a\bxg\x83&\xea\xc9\x00\x00\x00\u07d4OR\xadap\xd2[*.\x85\x0e\xad\xbbRA?\xf20>\u007f\x89\xa4\xccy\x95c\u00c0\x00\x00\u07d4OX\x01\xb1\xeb0\xb7\x12\u0620WZ\x9aq\xff\x96]O4\xeb\x89\x10CV\x1a\x88)0\x00\x00\u07d4O]\xf5\xb9CW\u0794\x86\x04\xc5\x1bx\x93\xcd\xdf`v\xba\xad\x89\xcb\xd4{n\xaa\x8c\xc0\x00\x00\u07d4Od\xa8^\x8e\x9a@I\x8c\fu\xfc\xeb\x037\xfbI\b>^\x8965\u026d\xc5\u07a0\x00\x00\u07d4Og9m%S\xf9\x98x_pN\a\xa69\x19}\u0454\x8d\x89\x10DrR\x1b\xa78\x00\x00\u07d4OmG7\u05e9@8$\x87&H\x86i|\xf7c\u007f\x80\x15\x89Z\x87\xe7\xd7\xf5\xf6X\x00\x00\u07d4Os0\toy\xed&N\xe0\x12\u007f]0\xd2\xf7<R\xb3\u0609\x1b\x1azB\v\xa0\r\x00\x00\u07d4Ov{\xc8yJ\xef\x9a\n8\xfe\xa5\xc8\x1f\x14iO\xf2\x1a\x13\x89\x1b\xc43\xf2?\x83\x14\x00\x00\u07d4O\x85\xbc\x1f\xc5\xcb\xc9\xc0\x01\xe8\xf17.\aPSp\xd8\xc7\x1f\x892\xf5\x1e\u06ea\xa30\x00\x00\u07d4O\x88\xdf\xd0\x10\x91\xa4Z\x9e&v\x02\x1ed(l\xd3k\x8d4\x8965\u026d\xc5\u07a0\x00\x00\u07d4O\x89r\x83\x8fp\xc9\x03\u0276\xc6\xc4ab\xe9\x9db\x16\xd4Q\x89\xf9\xe8\x9a\x0f,V\xc8\x00\x00\u07d4O\x8a\xe8\x028\xe6\x00\bUpu\xabj\xfe\n\u007f.t\xd7)\x89\x05k\xc7^-c\x10\x00\x00\u07d4O\x8e\x8d'O\xb2*?\xd3jG\xfer\x98\x04qTK44\x89\n\u05ce\xbcZ\xc6 \x00\x00\xe0\x94O\x9c\u2bdb\x8c^B\u0180\x8a8p\xecWo15E\u044a\x02\x1e\x19\xe0\u027a\xb2@\x00\x00\u07d4O\xa3\xf3.\xf4\bdH\xb3D\xd5\xf0\xa9\x89\r\x1c\xe4\xd6\x17\u00c9QP\xae\x84\xa8\xcd\xf0\x00\x00\u07d4O\xa5T\xab\x95\\$\x92\x178jM2c\xbb\xf7(\x95CN\x89\x01\x15NS!}\xdb\x00\x00\u07d4O\xa9\x83\xbb^0s\xa8\xed\xb5W\xef\xfe\xb4\xf9\xfb\x1d`\uf189V\xb9\xafW\xe5u\xec\x00\x00\u07d4O\xaf\x90\xb7n\u03f9c\x1b\xf9\x02!v\x03-\x8b, p\t\x8966;]\x9awp\x00\x00\u07d4O\xc4l9ngHi\xad\x94\x81c\x8f\x00\x13c\f\x87\u02ac\x8965\u026d\xc5\u07a0\x00\x00\xe0\x94O\xcc\x19\xea\x9fLW\u073c\xe8\x93\x19<\xfb\x16j\xa9\x14\xed\u014a\x01{\x8b\xaa\u007f\x19Tj\x00\x00\xe0\x94O\u0384)\xbaI\u02a06\x9d\x1eIM\xb5~\x89\uacad9\x8a*Z\x05\x8f\u0095\xed\x00\x00\x00\u07d4O\xda\xc1\xaaQp\a\xe0\b\x940\xb31j\x1b\xad\xd1,\x01\u01c9\x1b\x1a\xe4\xd6\xe2\xefP\x00\x00\u07d4O\xe5j\xb3\xba\u1c24D3E\x833\u0130Z$\x8f\x82A\x89v-\x93\xd1\xddo\x90\x00\x00\u07d4O\xeb\x84k\xe40A\xfdk4 (\x97\x94>?!\xcb\u007f\x04\x89\x04\x82\xfe&\f\xbc\xa9\x00\x00\u07d4O\xeeP\xc5\xf9\x88 k\t\xa5sF\x9f\xb1\u0434.\xbbm\u0389l\xee\x06\u077e\x15\xec\x00\x00\u07d4O\xf6v\xe2\u007fh\x1a\x98-\x8f\xd9\xd2\x0ed\x8b=\xce\x05\xe9E\x89\x97\xc9\xceL\xf6\xd5\xc0\x00\x00\u07d4O\xf6\u007f\xb8\u007fn\xfb\xa9'\x990\u03fd\x1bz4<y\xfa\u0789\x15\xaf\x1dx\xb5\x8c@\x00\x00\u07d4P\x06\xfeL\"\x179\x80\xf0\ft4+9\xcd#\x1ce1)\x89lk\x93[\x8b\xbd@\x00\x00\u07d4P\f\x165.\x90\x1dH\xba\x8d\x04\xe2\xc7g\x12\x17ry\v\x02\x89\x01\xa3\xa6\x82Is\t\x80\x00\u07d4P\f\x90)X\xf6B\x15\x94\u0476\xde\xd7\x12I\rR\xedlD\x89j\xcb=\xf2~\x1f\x88\x00\x00\xe0\x94P\x0e4\xcd\u5f5e+q\xbb\x92\xd7\xcfU\xee\xe1\x88\xd5\xfa\f\x8a\x01!\xeah\xc1\x14\xe5\x10\x00\x00\u07d4P2\xe4\xbc\xf7\x93+I\xfd\xba7{o\x14\x99ce\x13\xcf\u00c9\x05k\xc7^-c\x10\x00\x00\u07d4P7\x8a\xf7\xefT\x04?\x89*\xb7\u0397\xd6Gy5\x11\xb1\b\x89\x01\x11du\x9f\xfb2\x00\x00\u07d4P;\xdb\u063cB\x1c2\xa4C\x03-\xeb.>L\u057a\x8bN\x89lk\x93[\x8b\xbd@\x00\x00\xe0\x94PFf\u03891\x17^\x11\xa5\xed\x11\xc1\u072a\x06\xe5\u007fNf\x8a\x02\u007f>\u07f3Nn@\x00\x00\u0794PXM\x92\x06\xa4l\xe1\\0\x11\x17\xee(\xf1\\0\xe6\x0eu\x88\xb9\xf6]\x00\xf6<\x00\x00\xe0\x94PZ3\xa1\x864\xddH\x00i<g\xf4\x8a\x1di=H3\xf8\x8a\x01\x89!\xb7\x99A\xdc\xd0\x00\x00\u0794P^O|'U\x88\xc53\xa2\x0e\xbd*\xc1;@\x9b\xbd\xea<\x88\xf4?\xc2\xc0N\xe0\x00\x00\u07d4Pb\xe5\x13La/\x12iM\xbd\x0e\x13\x1dL\xe1\x97\u0476\xa4\x8965\u026d\xc5\u07a0\x00\x00\u07d4Pd\x11\xfdy\x004\x80\xf6\xf2\xb6\xaa\xc2k{\xa7\x92\U00014c89\x1b\x1a\xe4\xd6\xe2\xefP\x00\x00\u07d4Pg\xf4T\x9a\xfb\xfe\x88LY\xcb\xc1+\x96\x93I#\xd4]\xb0\x8965\u026d\xc5\u07a0\x00\x00\u07d4Pv:\u0746\x8f\xd76\x11x4/\xc0U\ua8b9_hF\x89\x03\x9f\x90F\xe0\x89\x8f\x00\x00\u07d4P\x8c\xf1\x91\x19\xdbp\xaa\x86EBS\xdavJ,\xb1\xb2\xbe\x1a\x8965\u026d\xc5\u07a0\x00\x00\xe0\x94P\x99\x82\xf5b7\xeeE\x89Q\x04~\n\"0\xf8\x04\xe2\u854a\x03\xb4\xadIa\x06\xb7\xf0\x00\x00\u07d4P\x9a \xbcH\xe7+\xe1\u036f\x95i\xc7\x11\xe8d\x8d\x95s4\x89lk\x93[\x8b\xbd@\x00\x00\u07d4P\x9c\x86h\x03m\x14?\xb8\xaep\xb1\x19\x95c\x1f=\xfc\xad\x87\x8965\u026d\xc5\u07a0\x00\x00\u07d4P\xad\x18z\xb2\x11g\u00b6\xe7\x8b\xe0\x15?DPJ\a\x94^\x89\x05l\xd5_\xc6M\xfe\x00\x00\u07d4P\xb9\xfe\xf0\xa12\x9b\x02\xd1e\x06%_Z-\xb7\x1e\xc9-\x1f\x89G\u0682\x15d\b\\\x00\x00\u07d4P\xbbg\u0238\u063d\x0fc\xc4v\t\x04\xf2\xd33\xf4\x00\xaa\u0389lk\x93[\x8b\xbd@\x00\x00\u07d4P\xbe\xf2ubH\xf9\xa7\xa3\x80\xf9\x1b\x05\x1b\xa3\xbe(\xa6I\xed\x89li\xf7>)\x13N\x00\x00\u07d4P\u0286\xb5\xeb\x1d\x01\x87M\xf8\xe5\xf3IE\u051cl\x1a\xb8H\x8965\u026d\xc5\u07a0\x00\x00\u07d4P\u0357\xe97\x8b\\\xf1\x8f\x179c#l\x99Q\xeft8\xa5\x89K\xe4\xe7&{j\xe0\x00\x00\u07d4P\u073c'\xbc\xad\x98@\x93\xa2\x12\xa9\xb4\x17\x8e\xab\xe9\x01ua\x89\a\xe3by\v\\\xa4\x00\x00\u07d4P\xe10#\xbd\x9c\xa9j\xd4\xc5?\xdf\xd4\x10\xcbk\x1fB\v\u07c9\n\u05ce\xbcZ\xc6 \x00\x00\xe0\x94P\xe1\xc8\xec\x98A[\xefD&\x18p\x87\x99C{\x86\xe6\xc2\x05\x8a\x01EB\xba\x12\xa37\xc0\x00\x00\u07d4P\xf8\xfaK\xb9\xe2g|\x99\nN\xe8\xcep\xdd\x15#%\x1eO\x89\x01i=#\x16Ok\x00\x00\u07d4P\xfb6\xc2q\a\xee,\xa9\xa3#n'F\u0321\x9a\xcekI\x89lk\x93[\x8b\xbd@\x00\x00\u07d4P\xfe\xf2\x96\x95U\x88\u02aet\xc6.\xc3*#\xa4T\xe0\x9a\xb8\x89A\x1d\xff\xab\xc5\a8\x00\x00\u07d4Q\x02\xa4\xa4 w\xe1\x1cX\xdfGs\u3b14F#\xa6m\x9f\x89lp\x15\xfdR\xed@\x80\x00\u07d4Q\x03\x93w\xee\xd0\xc5s\xf9\x86\xc5\xe8\xa9_\xb9\x9aY\xe93\x0f\x89j\xcb=\xf2~\x1f\x88\x00\x00\u07d4Q\x03\xbc\t\x93>\x99!\xfdS\xdcSo\x11\xf0]\rG\x10}\x89\xd8\xd7&\xb7\x17z\x80\x00\x00\xe0\x94Q\x04\xec\xc0\xe30\xdd\x1f\x81\xb5\x8a\xc9\u06f1\xa9\xfb\xf8\x8a<\x85\x8a\x15-\x02\xc7\xe1J\xf6\x80\x00\x00\u07d4Q\r\x81Y\u0314Wh\xc7E\a\x90\xba\a>\xc0\xd9\xf8\x9e0\x89\x8a\xc7#\x04\x89\xe8\x00\x00\x00\u07d4Q\x0e\xdaV\x01I\x9a\r^\x1a\x00k\xff\xfd\x836r\xf2\xe2g\x89lk\x93[\x8b\xbd@\x00\x00\u07d4Q\x12dF\xab=\x802U~\x8e\xbaeY}u\xfa\u0701\\\x89\x11t\xa5\xcd\xf8\x8b\xc8\x00\x00\xe0\x94Q\x18U}`\r\x05\xc2\xfc\xbf8\x06\xff\xbd\x93\xd0 %\xd70\x8a\x02g\u04ebd#\xf5\x80\x00\x00\u07d4Q\x1e\x0e\xfb\x04\xacN?\xf2\xe6U\x0eI\x82\x95\xbf\xcdV\xff\u0549$=M\x18\"\x9c\xa2\x00\x00\u07d4Q!\x16\x81{\xa9\xaa\xf8C\xd1P|e\xa5\xead\n{\x9e\xec\x89\x02\xb5\xe3\xaf\x16\xb1\x88\x00\x00\u07d4Q&F\ri,q\u026fo\x05WM\x93\x99\x83h\xa27\x99\x89\x02\u0465\x1c~\x00P\x00\x00\u07d4Q'\u007f\xe7\xc8\x1e\xeb\xd2R\xa0=\xf6\x9ak\x9f2n'\"\a\x89\x03@.y\u02b4L\x80\x00\u07d4Q)oPD'\r\x17pvF\x12\x9c\x86\xaa\xd1d^\xad\xc1\x89H|r\xb3\x10\xd4d\x80\x00\xe0\x94Q+\x91\xbb\xfa\xa9\xe5\x81\xefh?\xc9\r\x9d\xb2*\x8fI\xf4\x8b\x8aA\xa5\"8m\x9b\x95\xc0\x00\x00\u07d4Q5\xfb\x87W`\f\xf4tTbR\xf7M\xc0tm\x06&,\x89lk\x93[\x8b\xbd@\x00\x00\u07d4QF2\xef\xbdd,\x04\xdel\xa3B1]@\u0750\xa2\u06e6\x89\x90\xf54`\x8ar\x88\x00\x00\u07d4QKu\x12\u026e^\xa6<\xbf\x11q[c\xf2\x1e\x18\u0496\xc1\x89lj\xccg\u05f1\xd4\x00\x00\u07d4QS\xa0\xc3\u0211(\x81\xbf\x1c5\x01\xbfd\xb4VI\xe4\x82\"\x89\xd8\xd7&\xb7\x17z\x80\x00\x00\xe0\x94QVQ\xd6\xdbO\xaf\x9e\xcd\x10:\x92\x1b\xbb\xbej\xe9p\xfd\u050a\x04<3\xc1\x93ud\x80\x00\x00\xe0\x94Q_0\xbc\x90\xcd\xf4W~\xe4}e\u05c5\xfb\xe2\xe87\u01bc\x8a\x02'\x1b^\x01\x8b\xa0X\x00\x00\u07d4Q`\xeda.\x1bH\xe7??\xc1[\xc42\x1b\x8f#\xb8\xa2K\x89\x1e\x82kB(e\xd8\x00\x00\u07d4Qa\xfdI\xe8G\xf6tU\xf1\u023bz\xbb6\xe9\x85&\r\x03\x89A\rXj \xa4\xc0\x00\x00\u07d4QiT\x02_\xca&\b\xf4}\xa8\x1c!^\xed\xfd\x84J\t\xff\x89\x14\xb5P\xa0\x13\xc78\x00\x00\u07d4Qi\xc6\n\xeeL\xee\u0444\x9a\xb3mfL\xff\x97\x06\x1e\x8e\xa8\x89\xa2\xa1]\tQ\x9b\xe0\x00\x00\u07d4Q|uC\r\xe4\x01\xc3A\x03&\x86\x11'\x90\xf4mM6\x9e\x89\x15\b\x94\xe8I\xb3\x90\x00\x00\u07d4Q|\xd7`\x8e]\r\x83\xa2kq\u007f6\x03\xda\xc2'}\u00e4\x89lk\x93[\x8b\xbd@\x00\x00\u07d4Q\x86]\xb1H\x88\x19Q\xf5\x12Qq\x0e\x82\xb9\xbe\r~\xad\xb2\x89lk\x93[\x8b\xbd@\x00\x00\u07d4Q\x89\x1b,\xcd\xd2\xf5\xa4K*\x8b\u011a]\x9b\xcadw%\x1c\x89\x10\xce\x1d=\x8c\xb3\x18\x00\x00\u07d4Q\x8c\xef'\xb1\x05\x82\xb6\xd1OiH=\u06a0\xdd<\x87\xbb\\\x89 \x86\xac5\x10R`\x00\x00\u07d4Q\xa6\xd6'\xf6j\x89#\u060d`\x94\xc4qS\x80\xd3\x05|\xb6\x89>s\xd2z5\x94\x1e\x00\x00\u07d4Q\xa8\xc2\x166\x02\xa3.\xe2L\xf4\xaa\x97\xfd\x9e\xa4\x14QiA\x89\x03h\xf7\xe6\xb8g,\x00\x00\u07d4Q\xb4u\x8e\x9e\x14P\xe7\xafBh\xc3\u01f1\xe7\xbdo\\uP\x8965\u026d\xc5\u07a0\x00\x00\u07d4Q\u028b\xd4\xdcdO\xacG\xafgUc\u0540J\r\xa2\x1e\xeb\x89*\xb7\xb2`\xff?\xd0\x00\x00\u07d4Q\xd2K\xc3so\x88\xddc\xb7\" &\x88f0\xb6\ub1cd\x89lk\x93[\x8b\xbd@\x00\x00\u07d4Q\u05cb\x17\x8dp~9n\x87\x10\x96\\OA\xb1\xa1\xd9\x17\x9d\x89\x05\xfe\xe2\"\x04\x1e4\x00\x00\u07d4Q\xe3/\x14\xf4\xca^(|\xda\xc0W\xa7y^\xa9\xe0C\x99S\x89\x1b\x1a\xe4\xd6\xe2\xefP\x00\x00\u07d4Q\xe4?\xe0\xd2\\x(`\xaf\x81\xea\x89\xddy<\x13\xf0\u02f1\x89\x03@\xaa\xd2\x1b;p\x00\x00\u07d4Q\xe7\xb5\\/\x98 \xee\xd78\x846\x1bPf\xa5\x9boE\u0189lk\x93[\x8b\xbd@\x00\x00\xe0\x94Q\xea\x1c\t4\xe3\xd0@\"\ud715\xa0\x87\xa1P\xefp^\x81\x8a\x01Tp\x81\xe7\"M \x00\x00\u07d4Q\xee\f\xca;\xcb\x10\xcd>\x987\"\xce\xd8I=\x92l\bf\x8965f3\xeb\xd8\xea\x00\x00\xe0\x94Q\xf4f:\xb4O\xf7\x93E\xf4'\xa0\xf6\xf8\xa6\u0225?\xf24\x8a\x04<3\xc1\x93ud\x80\x00\x00\u07d4Q\xf5^\xf4~dV\xa4\x18\xab2\xb9\"\x1e\xd2}\xbaf\b\xee\x89\u3bb5sr@\xa0\x00\x00\xe0\x94Q\xf9\xc42\xa4\xe5\x9a\xc8b\x82\u05ad\xabL.\xb8\x91\x91`\xeb\x8ap;[\x89\u00e6\xe7@\x00\x00\u07d4R\x0ff\xa0\xe2e\u007f\xf0\xacA\x95\xf2\xf0d\xcf/\xa4\xb2BP\x89\x02+\x1c\x8c\x12'\xa0\x00\x00\u07d4R\x10#T\xa6\xac\xa9]\x8a.\x86\xd5\u07bd\xa6\xdei4`v\x89lk\x93[\x8b\xbd@\x00\x00\u07d4R\x13\xf4Y\xe0x\xad:\xb9Z\t #\x9f\xcf\x163\xdc\x04\u0289\x8c\xf2\x18|*\xfb\x18\x80\x00\u07d4R\x15\x18;\x8f\x80\xa9\xbc\x03\xd2l\xe9\x12\a\x83*\r9\xe6 \x8965\u026d\xc5\u07a0\x00\x00\xe0\x94R!Cx\xb5@\x04\x05j|\xc0\x8c\x89\x13'y\x8a\u01b2H\x8a\x037\xfe_\xea\xf2\u0440\x00\x00\xe0\x94R##\xaa\xd7\x1d\xbc\x96\xd8Z\xf9\x0f\bK\x99\xc3\xf0\x9d\ucdca\x01EB\xba\x12\xa37\xc0\x00\x00\u07d4R>\x14\r\xc8\x11\xb1\x86\xde\xe5\xd6\u020b\xf6\x8e\x90\xb8\xe0\x96\xfd\x89lk\x93[\x8b\xbd@\x00\x00\u07d4R?mdi\x0f\xda\u0354(SY\x1b\xb0\xff \xd3em\x95\x89b\xa9\x92\xe5:\n\xf0\x00\x00\u07d4RO\xb2\x10R,^#\xbbg\u07ff\x8c&\xaaam\xa4\x99U\x8965b\xa6m4#\x80\x00\u07d4RU\xdci\x15ZE\xb9p\xc6\x04\xd3\x00G\xe2\xf50i\x0e\u007f\x89\x01\x15\x8eF\t\x13\xd0\x00\x00\u07d4R`\xdcQ\xee\a\xbd\u06ab\xab\xb9\xeetK9<\u007fG\x93\xa6\x89\x01\xd8f_\xa5\xfaL\x00\x00\u07d4Rg\xf4\xd4\x12\x92\xf3p\x86<\x90\u05d3)i\x03\x846%\u01c9K\xe4\xe7&{j\xe0\x00\x00\u07d4Rk\xb53\xb7n \xc8\xee\x1e\xbf\x12?\x1e\x9f\xf4\x14\x8e@\xbe\x89\n\xad\xec\x98?\xcf\xf4\x00\x00\u07d4Rl\xb0\x9c\u3b63g.\xec\x1d\xebF [\xe8\x9aKV>\x89\x85\xcaa[\xf9\xc0\x10\x00\x00\u07d4Rs\x8c\x90\xd8`\xe0L\xb1/I\x8d\x96\xfd\xb5\xbf6\xfc4\x0e\x89\x01\xa0Ui\r\x9d\xb8\x00\x00\u07d4Rz\x8c\xa1&\x863\xa6\xc99\xc5\xde\x1b\x92\x9a\ue4ae\xac\x8d\x890\xca\x02O\x98{\x90\x00\x00\u07d4R\x81\x01\xceF\xb7 \xa2!M\u036ef\x18\xa51w\xff\xa3w\x89\x1b\x96\x12\xb9\xdc\x01\xae\x00\x00\xe0\x94R\x81s4s\xe0\r\x87\xf1\x1e\x99U\u5275\x9fJ\u008ez\x8a\x8b\xd6/\xf4\xee\xc5Y \x00\x00\u07d4R\x98\xab\x18*\x195\x9f\xfc\xec\xaf\xd7\u0475\xfa!-\xed\xe6\u0749\x01\x15\x8eF\t\x13\xd0\x00\x00\u07d4R\x9a\xa0\x02\u0196*:\x85E\x02\u007f\u0630_\"\xb5\xbf\x95d\x89Z\x87\xe7\xd7\xf5\xf6X\x00\x00\u07d4R\x9e\x82O\xa0rX+@2h:\xc7\xee\xcc\x1c\x04\xb4\xca\xc1\x89lk\x93[\x8b\xbd@\x00\x00\xe0\x94R\xa5\xe4\xdeC\x93\xee\xcc\xf0X\x1a\xc1\x1bR\u0183\xc7n\xa1]\x8a\x04<0\xfb\b\x84\xa9l\x00\x00\u07d4R\xb4%|\xf4\x1bn(\x87\x8dP\xd5{\x99\x91O\xfa\x89\x87:\x89\xd5\r\u026a,Aw\x00\x00\u07d4R\xb8\xa9Y&4\xf70\v|\\Y\xa34[\x83_\x01\xb9\\\x89lk\x93[\x8b\xbd@\x00\x00\u07d4R\xbd\u066fYx\x85\v\xc2A\x10q\x8b7#u\x9bC~Y\x89]\u0212\xaa\x111\xc8\x00\x00\u07d4R\xcd @;\xa7\xed\xa6\xbc0z=c\xb5\x91\x1b\x81|\x12c\x89\x01\x15\x8eF\t\x13\xd0\x00\x00\u0794R\u04c0Q\x1d\xf1\x9d^\u0080{\xbc\xb6vX\x1bg\xfd7\xa3\x88\xb9\xf6]\x00\xf6<\x00\x00\xe0\x94R\xe1s\x13P\xf9\x83\xcc,A\x89\x84/\xde\x06\x13\xfa\xd5\f\xe1\x8a\x02w\x01s8\xa3\n\xe0\x00\x00\u07d4R\xe4g\x832\x9av\x93\x01\xb1u\x00\x9d4gh\xf4\xc8~\xe4\x89lk\x93[\x8b\xbd@\x00\x00\u07d4R\xf0X\xd4aG\xe9\x00m)\xbf,\t0J\xd1\xcd\xddn\x15\x89QP\xae\x84\xa8\xcd\xf0\x00\x00\u07d4R\xf1T#2<$\xf1\x9a\xe2\xabg7\x17\"\x9d?t}\x9b\x897\xa04\xcb\xe8\xe3\xf3\x80\x00\u07d4R\xf8\xb5\t\xfe\xe1\xa8t\xabo\x9d\x876\u007f\xbe\xaf\x15\xac\x13\u007f\x8965\u026d\xc5\u07a0\x00\x00\u07d4R\xfbF\xac]\x00\xc3Q\x8b,:\x1c\x17}D/\x81eU_\x89QP\xae\x84\xa8\xcd\xf0\x00\x00\u07d4S\x00w\xc9\xf7\xb9\a\xff\x9c\xec\fw\xa4\x1ap\xe9\x02\x9a\xddJ\x89lk\x93[\x8b\xbd@\x00\x00\u07d4S\x03\x19\xdb\n\x8f\x93\xe5\xbb}M\xbfH\x161O\xbe\xd86\x1b\x89lk\x93[\x8b\xbd@\x00\x00\u07d4S\x04}\u022c\x90\x83\xd9\x06r\xe8\xb3G<\x10\f\xcd'\x83#\x89\x02+\x1c\x8c\x12'\xa0\x00\x00\u07d4S\va\xe4/9Bm$\b\xd4\bR\xb9\xe3J\xb5\xeb\xeb\u0149\x0e~\xeb\xa3A\vt\x00\x00\u07d4S\x0f\xfa\u00fc4\x12\xe2\xec\x0e\xa4{y\x81\xc7p\xf5\xbb/5\x89\a?u\u0460\x85\xba\x00\x00\u07d4S\x17\xec\xb0#\x05,\xa7\xf5e+\xe2\xfa\x85L\xfeEc\xdfM\x89\x1b\x1a\xb3\x19\xf5\xecu\x00\x00\u07d4S\x19M\x8a\xfa>\x885\x02v~\xdb\xc3\x05\x86\xaf3\xb1\x14\u04c9lk\x93[\x8b\xbd@\x00\x00\u07d4S*}\xa0\xa5\xadt\aF\x8d;\xe8\xe0~i\xc7\xddd\xe8a\x89\x1b\x1a\xe4\xd6\xe2\xefP\x00\x00\u07d4S-2\xb0\x0f0[\xcc$\xdc\xefV\x81}b/4\xfb,$\x89a\x94\x04\x9f0\xf7 \x00\x00\u07d4S4DX@\x82\xeb\xa6T\xe1\xad0\xe1Is\\o{\xa9\"\x89]\u0212\xaa\x111\xc8\x00\x00\u07d4S8\xefp\xea\xc9\u075a\xf5\xa0P;^\xfa\xd1\x03\x9eg\xe7%\x89\x90\xf54`\x8ar\x88\x00\x00\xe0\x94S9oJ&\u00b4`D\x960lTB\xe7\xfc\xba'.6\x8a\x04?/\b\xd4\x0eZ\xfc\x00\x00\xe0\x94S:s\xa4\xa2\"\x8e\xee\x05\xc4\xff\xd7\x18\xbb\xf3\xf9\xc1\xb1)\xa7\x8a\x01EB\xba\x12\xa37\xc0\x00\x00\u07d4S<\x06\x92\x8f\x19\u0429V\xcc(\x86k\xf6\xc8\xd8\xf4\x19\x1a\x94\x89\x0f\xd8\xc1C8\xe60\x00\x00\u07d4S@e6\x1c\xb8T\xfa\xc4+\xfb\\\x9f\xcd\xe0`J\xc9\x19\u0689lk\x93[\x8b\xbd@\x00\x00\u07d4SC\u007f\xec\xf3J\xb9\xd45\xf4\u07b8\xca\x18\x15\x19\xe2Y 5\x89\n1\x06+\xee\xedp\x00\x00\u07d4SR\x01\xa0\xa1\xd74\"\x80\x1fU\xde\xd4\u07ee\xe4\xfb\xaan;\x89\x02&!\x1fy\x15B\x80\x00\xe0\x94S`\x81\x05\xceK\x9e\x11\xf8k\xf4\x97\xff\xca;x\x96{_\x96\x8a\x04<3\xc1\x93ud\x80\x00\x00\u07d4SnM\x80)\xb7?Uy\u0723>p\xb2N\xba\x89\xe1\x1d~\x89j\xcb=\xf2~\x1f\x88\x00\x00\u07d4Sp\rS%MC\x0f\"x\x1aJv\xa4c\x93;]k\b\x89j\xcb=\xf2~\x1f\x88\x00\x00\xe0\x94S\u007f\x9dM1\xefp\x83\x9d\x84\xb0\xd9\u0377+\x9a\xfe\xdb\xdf5\x8a\x0e\u04b5%\x84\x1a\xdf\xc0\x00\x00\xe0\x94S\x81D\x85\x03\xc0\xc7\x02T+\x1d\xe7\xcc_\xb5\xf6\xab\x1c\xf6\xa5\x8a\x01\xb1\xaeMn.\xf5\x00\x00\x00\xe0\x94S\x94.yI\xd6x\x8b\xb7\x80\xa7\xe8\xa0y'\x81\xb1aK\x84\x8a\x03]\xebFhO\x10\xc8\x00\x00\u07d4S\x95\xa4E]\x95\xd1x\xb4S*\xa4r[\x19?\xfeQ)a\x8965\u026d\xc5\u07a0\x00\x00\xe0\x94S\x98\x9e\xd30V?\xd5}\xfe\u027d4<7`\xb0y\x93\x90\x8a\x01P\x89N\x84\x9b9\x00\x00\x00\u07d4S\xa2Dg(\x95H\x0fJ+\x1c\xdf}\xa5\xe5\xa2B\xecM\xbc\x8965\u026d\xc5\u07a0\x00\x00\u07d4S\xa7\x14\xf9\x9f\xa0\x0f\xefu\x8e#\xa2\xe7F2m\xad$|\xa7\x89P\xc5\xe7a\xa4D\b\x00\x00\u07d4S\xaf2\xc2/\uf640?\x17\x8c\xf9\v\x80/\xb5q\xc6\x1c\xb9\x89\xd2U\xd1\x12\xe1\x03\xa0\x00\x00\u07d4S\xc0\xbb\u007f\u020e\xa4\"\xd2\xef~T\x0e-\x8f(\xb1\xbb\x81\x83\x89\x01\x15\x8eF\t\x13\xd0\x00\x00\xe0\x94S\xc5\xfe\x01\x19\xe1\xe8Hd\f\xee0\xad\ua594\x0f*]\x8b\x8a\x04\x9a\xda_\xa8\xc1\f\x88\x00\x00\u07d4S\xc9\xec\xa4\ts\xf6;\xb5\x92{\xe0\xbcj\x8a\x8b\xe1\x95\x1ft\x89lk\x93[\x8b\xbd@\x00\x00\u07d4S\u0388\xe6lZ\xf2\U0009bf4fY*V\xa3\xd1_ l2\x89\a\xa2\x8c1\xcc6\x04\x00\x00\u07d4S\xce\xc6\u0200\x92\xf7V\xef\xe5o}\xb1\x12(\xa2\xdbE\xb1\"\x89\xd8\xd7&\xb7\x17z\x80\x00\x00\u07d4S\xe3[\x12#\x1f\x19\xc3\xfdwL\x88\xfe\xc8\xcb\xee\xdf\x14\b\xb2\x89\x1b\xc1mgN\xc8\x00\x00\x00\u07d4S\xe4\xd9im\xcb?M{?p\u072aN\xec\xb7\x17\x82\xff\\\x89\n\u05ce\xbcZ\xc6 \x00\x00\u07d4S\xfa\xf1e\xbe\x03\x1e\xc1\x830\xd9\xfc\xe5\xbd\x12\x81\xa1\xaf\b\u06c9\a\x96\xe3\xea?\x8a\xb0\x00\x00\u07d4T\n\x18\x19\xbd|5\x86\x1ey\x18\x04\xe5\xfb\xb3\xbc\x97\u026b\xb1\x89N\xd7\xda\xc6B0 \x00\x00\xe0\x94T\f\a(\x02\x01N\xf0\xd5a4Z\xecH\x1e\x8e\x11\xcb5p\x8a\x01\xb1\xaeMn.\xf5\x00\x00\x00\xe0\x94T\f\xf2=\xd9\\MU\x8a'\x9dw\x8d+75\xb3\x16A\x91\x8a\x02\x1e\x19\xe0\u027a\xb2@\x00\x00\u07d4T\x10`\xfcX\xc7P\xc4\x05\x12\xf83i\xc0\xa63@\xc1\"\xb6\x89j\xcb=\xf2~\x1f\x88\x00\x00\u07d4T\x13\xc9\u007f\xfaJn*{\xba\x89a\u071f\u03850\xa7\x87\u05c965\u026d\xc5\u07a0\x00\x00\u07d4T\x1d\xb2\n\x80\xcf;\x17\xf1b\x1f\x1b?\xf7\x9b\x88/P\xde\xf3\x8965\u026d\xc5\u07a0\x00\x00\u07d4T.\x80\x96\xba\xfb\x88\x16&\x06\x00.\x8c\x8a>\u0458\x14\xae\xac\x89lk\x93[\x8b\xbd@\x00\x00\u07d4T1\v:\xa8\x87\x03\xa7%\u07e5}\xe6\xe6F\x93Qd\x80,\x89g\x8a\x93 b\xe4\x18\x00\x00\u07d4T1\xb1\u0447Q\xb9\x8f\xc9\u220a\xc7u\x9f\x155\xa2\xdbG\x89lk\x93[\x8b\xbd@\x00\x00\u07d4T1\xcaB~ae\xa6D\xba\xe3&\xbd\tu\n\x17\x8ce\r\x89lk\x93[\x8b\xbd@\x00\x00\u07d4T5\xc6\xc1y3\x17\xd3,\xe1;\xbaLO\xfe\xb9s\xb7\x8a\u0709\r\x8ek\x1c\x12\x85\xef\x00\x00\xe0\x94T6)\xc9\\\xde\xf4(\xad7\xd4S\u02958\xa9\xf9\t\x00\xac\x8a\t(\x96R\x9b\xad\u0708\x00\x00\u07d4T9\x1bM\x17mGl\xea\x16N_\xb55\u0197\x00\xcb%5\x89\x05l\xd5_\xc6M\xfe\x00\x00\xe0\x94T:\x8c\x0e\xfb\x8b\xcd\x15\xc5C\u29a4\xf8\aYv1\xad\xef\x8a\x01?\x80\xe7\xe1O-D\x00\x00\u07d4T?\x8cgN$b\xd8\xd5\u06a0\xe8\x01\x95\xa8p\x8e\x11\xa2\x9e\x89\x03wX\x83;:z\x00\x00\xe0\x94TK[5\x1d\x1b\xc8.\x92\x97C\x99H\xcfHa\xda\u026e\x11\x8a\x04\xa8\x9fT\xef\x01!\xc0\x00\x00\u07d4TM\xdaB\x1d\xc1\xebs\xbb$\xe3\xe5j$\x80\x13\xb8|\x0fD\x89j\xcb=\xf2~\x1f\x88\x00\x00\u07d4TW\\1\x14u\x1e<c\x19q\xdaj*\x02\xfd?\xfb\xfc\u0209i*\xe8\x89p\x81\xd0\x00\x00\u07d4T[\xb0p\xe7\x81\x17.\xb1`\x8a\xf7\xfc(\x95\xd6\u02c7\x19~\x89y\xa5\xc1~\xc7H\x90\x00\x00\xe0\x94Tu\xd7\xf1t\xbd\xb1\xf7\x89\x01||\x17\x05\x98\x96F\a\x9dI\x8a\x01\xfd\x934\x94\xaa_\xe0\x00\x00\u07d4T\x85X\u040c\xfc\xb1\x01\x18\x1d\xac\x1e\xb6\tKN\x1a\x89o\xa6\x89lj\xccg\u05f1\xd4\x00\x00\u07d4T\x93\x9f\xf0\x89!\xb4g\xcf)Fu\x1d\x85cx)lc\xed\x8965\u026d\xc5\u07a0\x00\x00\u07d4T\x9bGd\x9c\xfa\u0653\xe4\x06M&6\xa4\xba\xa0b3\x05\u0309 \x9d\x92/RY\xc5\x00\x00\u07d4T\x9dQ\xaf)\xf7$\xc9g\xf5\x94#\xb8[&\x81\xe7\xb1Q6\x89\xcb\xd4{n\xaa\x8c\xc0\x00\x00\u07d4T\xa17\x01\x16\xfe\"\t\x9e\x01]\a\xcd&i\xdd)\x1c\xc9\u0449\x01\x15\x8eF\t\x13\xd0\x00\x00\xe0\x94T\xa6+\xf9#>\x14o\xfe\u00c7nE\xf2\x0e\xe8AJ\u07ba\x8a\x02\x1e\x19\xe0\u027a\xb2@\x00\x00\u07d4T\xb4B\x9b\x18/\x03w\xbe~bi9\xc5\xdbd@\xf7]z\x89j\xcb=\xf2~\x1f\x88\x00\x00\u07d4T\xbc\xb8\xe7\xf7<\xda=s\xf4\u04cb-\bG\xe6\x00\xba\r\xf8\x89:pAX\x82\xdf\x18\x00\x00\u07d4T\xc9>\x03\xa9\xb2\xe8\xe4\xc3g(5\xa9\xeev\xf9a[\xc1N\x89\x01\r:\xa56\xe2\x94\x00\x00\u07d4T\u0388'YV\xde\xf5\xf9E\x8e;\x95\xde\xca\xcdH@!\xa0\x89lk\x93[\x8b\xbd@\x00\x00\u07d4T\xdb^\x06\xb4\x81]1\xcbV\xa8q\x9b\xa3:\xf2\xd7>rR\x89$R\x1e*0\x17\xb8\x00\x00\xe0\x94T\xe0\x12\x83\u030b8E8\xdddgp\xb3W\xc9`\xd6\xca\u034a\x01\x0f\f\xf0d\xddY \x00\x00\u07d4T\xecs\x00\xb8\x1a\xc8C3\xed\x1b\x03<\xd5\u05e39r\xe24\x89\n\u05ce\xbcZ\xc6 \x00\x00\u07d4T\xfe\xbc\xce \xfez\x90\x98\xa7U\xbd\x90\x98\x86\x02\xa4\x8c\b\x9e\x89\"\xb1\xc8\xc1\"z\x00\x00\x00\u07d4U\n\xad\xae\x12!\xb0z\xfe\xa3\x9f\xba.\xd6.\x05\u5df5\xf9\x89\x01\x15\x8eF\t\x13\xd0\x00\x00\u07d4U\f0o\x81\xef]\x95\x80\xc0l\xb1\xab \x1b\x95\xc7H\xa6\x91\x89$\x17\xd4\xc4p\xbf\x14\x00\x00\xe0\x94U\x19\x99\xdd\xd2\x05V3'\xb9\xb50xZ\xcf\xf9\xbcs\xa4\xba\x8a\x01EB\xba\x12\xa37\xc0\x00\x00\u07d4U\x1ew\x84w\x8e\xf8\xe0H\xe4\x95\xdfI\xf2aO\x84\xa4\xf1\u0709 \x86\xac5\x10R`\x00\x00\xe0\x94U)\x83\na\xc1\xf1<\x19~U\v\xed\xdf\u05bd\x19\\\x9d\x02\x8a\x02\x1e\x19\xe0\u027a\xb2@\x00\x00\u07d4U)\x87\xf0e\x1b\x91[.\x1eS(\xc1!\x96\rK\xddj\xf4\x89a\t=|,m8\x00\x00\u07d4U;k\x1cW\x05\x0e\x88\xcf\f1\x06{\x8dL\xd1\xff\x80\xcb\t\x89\x15\xaf\x1dx\xb5\x8c@\x00\x00\u07d4U?7\xd9$fU\x0e\x9f\xd7u\xaet6-\xf00\x17\x912\x89lk\x93[\x8b\xbd@\x00\x00\u07d4UC6\xeeN\xa1U\xf9\xf2O\x87\xbc\xa9\xcar\xe2S\xe1,\u0489\x05k\xc7^-c\x10\x00\x00\u0794UC\xddm\x16\x9e\xec\x8a!;\xbfz\x8a\xf9\xff\xd1]O\xf7Y\x88\xfc\x93c\x92\x80\x1c\x00\x00\u07d4UG\xfd\xb4\xae\x11\x95>\x01)+x\a\xfa\x92#\xd0\xe4`j\x89\x05]\x11}\xcb\x1d&\x00\x00\u07d4UR\xf4\xb3\xed>\x1d\xa7\x9a/x\xbb\x13\xe8\xaeZh\xa9\xdf;\x8965\u026d\xc5\u07a0\x00\x00\u07d4U\\\xa9\xf0\\\xc14\xabT\xae\x9b\xea\x1c?\xf8z\xa8Q\x98\u0289\x05k\xc7^-c\x10\x00\x00\xe0\x94U]\x8d<\xe1y\x8a\u0290'T\xf1d\xb8\xbe*\x022\x9cl\x8a\x02\x1e\x19\xe0\u027a\xb2@\x00\x00\u07d4U]\xf1\x93\x90\xc1m\x01)\x87r\xba\xe8\xbc:\x11R\x19\x9c\xbd\x89\n\u05ce\xbcZ\xc6 \x00\x00\u07d4U^\xbe\x84\u06a4+\xa2V\xeax\x91\x05\xce\u0136\x93\xf1/\x18\x89\x05k\xc7^-c\x10\x00\x00\xe0\x94U\u007f^e\xe0\xda3\x99\x82\x19\xadN\x99W\x05E\xb2\xa9\xd5\x11\x8a\x02U\x9c\xbb\x98XB@\x00\x00\u07d4U\x83` h\x83\xdd\x1bmJYc\x9eV)\xd0\xf0\xc6u\u0409lk\x93[\x8b\xbd@\x00\x00\u07d4U\x84B0P\xe3\xc2\x05\x1f\v\xbd\x8fD\xbdm\xbc'\xec\xb6,\x89\xa2\xa1]\tQ\x9b\xe0\x00\x00\u07d4U\x85)CI)p\xf8\xd6)\xa1Sf\xcd\xda\x06\xa9OE\x13\x89lk\x93[\x8b\xbd@\x00\x00\u0794U\x86d\x86\xec\x16\x8fy\xdb\xe0\u1af1\x88d\u0649\x91\xae,\x88\xdfn\xb0\xb2\xd3\xca\x00\x00\u07d4U\x8cTd\x9a\x8an\x94r+\xd6\xd2\x1d\x14qOqx\x054\x89lk\x93[\x8b\xbd@\x00\x00\u07d4U\x91\x940O\x14\xb1\xb9:\xfeDO\x06$\xe0S\xc2:\x00\t\x89\x15\xaf\x1dx\xb5\x8c@\x00\x00\u07d4U\x93\xc9\u0536ds\x0f\xd9<\xa6\x01Q\xc2\\.\xae\xd9<;\x89\n\u05ce\xbcZ\xc6 \x00\x00\u07d4U\x97\x06\xc32\xd2\ay\xc4_\x8am\x04ji\x91Y\xb7I!\x89\x14\x9bD.\x85\xa3\u03c0\x00\u07d4U\x98\xb3\xa7\x9aH\xf3+\x1f_\xc9\x15\xb8{d]\x80]\x1a\xfe\x89\x1b\x1a\xe4\xd6\xe2\xefP\x00\x00\u07d4U\xa3\xdfW\xb7\xaa\xec\x16\xa1b\xfdS\x16\xf3[\xec\b(!\u03c9j\xcb=\xf2~\x1f\x88\x00\x00\u07d4U\xa4\xca\xc0\u02cbX-\x9f\xef8\xc5\xc9\xff\xf9\xbdS\t=\x1f\x89j\xcb=\xf2~\x1f\x88\x00\x00\u07d4U\xa6\x1b\x10\x94\x80\xb5\xb2\xc4\xfc\xfd\xef\x92\xd9\x05\x84\x16\f\r5\x89\x02lVM+S\xf6\x00\x00\u07d4U\xaa]1>\xbb\bM\xa0\xe7\x80\x10\x91\u2792\xc5\xde\u00ea\x89lk\x93[\x8b\xbd@\x00\x00\u07d4U\xab\x99\xb0\xe0\xe5]{\xb8t\xb7\xcf\xe84\xdec\x1c\x97\xec#\x897\xe9\x8c\xe3h\x99\xe4\x00\x00\u07d4U\xaf\t/\x94\xbajy\x91\x8b\f\xf99\xea\xb3\xf0\x1b?Q\u01c9\b \xd5\xe3\x95v\x12\x00\x00\u07d4U\xc5dfAf\xa1\xed\xf3\x91>\x01i\xf1\xcdE\x1f\xdb]\f\x89\x82\x17\xeaIP\x8el\x00\x00\xe0\x94U\xcaj\xbey\xea$\x97\xf4o\u06f804`\x10\xfeF\x9c\xbe\x8a\x016\x9f\xb9a(\xacH\x00\x00\u07d4U\xca\xffK\xba\x04\xd2 \u0265\xd2\x01\x86r\xec\x85\xe3\x1e\xf8>\x89lk\x93[\x8b\xbd@\x00\x00\u07d4U\xd0W\xbc\xc0K\xd0\xf4\xaf\x96BQ:\xa5\t\v\xb3\xff\x93\xfe\x89;\xfeE,\x8e\xddL\x00\x00\u07d4U\xd4.\xb4\x95\xbfF\xa64\x99{_.\xa3b\x81I\x18\u2c09\x05\xc0\xd2e\xb5\xb2\xa8\x00\x00\u07d4U\u069d\xcd\xcaa\xcb\xfe\x1f\x13<{\xce\xfc\x86{\x9c\x81\"\xf9\x89/\xb4t\t\x8fg\xc0\x00\x00\u07d4U\xe2 \x87bb\xc2\x18\xafOVxG\x98\xc7\xe5]\xa0\x9e\x91\x89\a=\x99\xc1VE\xd3\x00\x00\u07d4U\xfd\b\u0440d\xbd ,\x0e\xc3\xd2\xcc\xe0\xce\v\x9d\x16\x9cM\x89j\xcb=\xf2~\x1f\x88\x00\x00\u07d4V\x00s\nU\xf6\xb2\x0e\xbd$\x81\x1f\xaa=\xe9m\x16b\xab\xab\x89e\xea=\xb7UF`\x00\x00\u07d4V\x03$\x1e\xb8\xf0\x8fr\x1e4\x8c\x9d\x9a\xd9/H\u342a$\x89\n\u05ce\xbcZ\xc6 \x00\x00\u07d4V\x056yJ\x9e+\x00I\xd1\x023\xc4\x1a\xdc_A\x8a&J\x8965\u026d\xc5\u07a0\x00\x00\u07d4V\aY\x00Y\xa9\xfe\xc1\x88\x11I\xa4K6\x94\x9a\xef\x85\xd5`\x89lk\x93[\x8b\xbd@\x00\x00\u07d4V\v\xec\xdfR\xb7\x1f=\x88'\xd9'a\x0f\x1a\x98\x0f3qo\x89\x17GMp_V\u0400\x00\xe0\x94V\r\xa3~\x95m\x86/\x81\xa7_\u0540\xa7\x13\\\x1b$cR\x8a\x02\x1e\x19\xe0\u027a\xb2@\x00\x00\xe0\x94V\x0f\xc0\x8d\a\x9f\x04~\xd8\xd7\xdfuU\x1a\xa55\x01\xf5p\x13\x8a\x01\x9b\xff/\xf5yh\xc0\x00\x00\u07d4V\x1b\xe9)\x9b>k>c\xb7\x9b\t\x16\x9d\x1a\x94\x8a\xe6\xdb\x01\x89\x1b\x1a\xe4\xd6\xe2\xefP\x00\x00\xe0\x94V \xe3\xedy-/\x185\xfe_UA}Q\x11F\fj\x8a\x04<3\xc1\x93ud\x80\x00\x00\u07d4V \xf4m\x14Q\xc25=bC\xa5\u0534'\x13\v\xe2\xd4\a\x89\x03@\xaa\xd2\x1b;p\x00\x00\xe0\x94V!\x05\xe8+\t\x975\xdeI\xf6&\x92\u0307\xcd8\xa8\xed\u034a\x01EB\xba\x12\xa37\xc0\x00\x00\xe0\x94V*\x8d\u02fe\xee\xf7\xb3`h]'0;\u059e\tJ\xcc\xf6\x8a\x02\x1e\x19\xe0\u027a\xb2@\x00\x00\u07d4V+\xce\u04ca\xb2\xabl\b\x0f;\x05A\xb8Enp\x82K?\x89\"\xca5\x87\xcfN\xb0\x00\x00\xe0\x94V+\xe9Z\xba\x17\xc57\x1f\u2e82\x87\x99\xb1\xf5]!w\u058a\b\x16\xd3~\x87\xb9\xd1\xe0\x00\x00\u07d4V/\x16\u05da\xbf\xce\u00d4>4\xb2\x0f\x05\xf9{\xdf\u0366\x05\x89\xd8\xd7&\xb7\x17z\x80\x00\x00\u07d4V7=\xaa\xb4c\x16\xfd~\x15v\xc6\x1ej\xff\xcbeY\xdd\u05c9\v\xacq]\x14l\x9e\x00\x00\u07d4V9v8\xbb<\xeb\xf1\xf6 byK^\xb9B\xf9\x16\x17\x1d\x89lk\x93[\x8b\xbd@\x00\x00\u07d4V:\x03\xab\x9cV\xb6\x00\xf6\xd2[f\f!\xe1c5Qzu\x8965\u026d\xc5\u07a0\x00\x00\u07d4V<\xb8\x80<\x1d2\xa2['\xb6A\x14\x85+\xd0M\x9c \u0349\v\x14\x9e\xad\n\xd9\xd8\x00\x00\u07d4VXc\x91\x04\fW\xee\xc6\xf5\xaf\xfd\x8c\u052b\xde\x10\xb5\n\u0309\xd8\xd7&\xb7\x17z\x80\x00\x00\u07d4Vl\x10\xd68\u8e0bG\xd6\xe6\xa4\x14Iz\xfd\xd0\x06\x00\u0509\x05k9Bc\xa4\f\x00\x00\u07d4Vl(\xe3L8\b\xd9vo\xe8B\x1e\xbfO+\x1cO}w\x89j\xcb=\xf2~\x1f\x88\x00\x00\u07d4V\x8d\xf3\x18Vi\x9b\xb5\xac\xfc\x1f\xe1\u0580\u07d9`\xcaCY\x89J\xcfUR\xf3\xb2I\x80\x00\u07d4V\x91\xdd/gE\xf2\x0e\"\xd2\xe1\u0479U\xaa)\x03\xd6VV\x89j\xc5\xc6-\x94\x86\a\x00\x00\u07d4V\xa1\xd6\r@\xf5\u007f0\x8e\xeb\xf0\x87\xde\xe3\xb3\u007f\x1e|,\xba\x89>\u072e\xc8-\x06\xf8\x00\x00\u07d4V\xac \xd6;\xd8\x03Y\\\xec\x03m\xa7\xed\x1d\xc6n\n\x9e\a\x89\x03w*S\xcc\xdce\x80\x00\u07d4V\xb6\xc2=\xd2\uc434r\x8f;\xb2\xe7d\xc3\xc5\f\x85\xf1D\x8965\u026d\xc5\u07a0\x00\x00\u07d4V\xdf\x05\xba\xd4l?\x00\xaeGn\xcf\x01{\xb8\xc8w8?\xf1\x89\n\xb1]\xaa\xefp@\x00\x00\u07d4V\xee\x19\u007fK\xbf\x9f\x1b\x06b\xe4\x1c+\xbd\x9a\xa1\xf7\x99\xe8F\x8965\u026d\xc5\u07a0\x00\x00\u07d4V\xf4\x93\xa3\xd1\b\xaa\xa2\u044d\x98\x92/\x8e\xfe\x16b\u03f7=\x89m\x81!\xa1\x94\xd1\x10\x00\x00\u07d4V\xfc\x1a{\xad@G#|\xe1\x16\x14b\x96#\x8e\a\x8f\x93\xad\x89\t\xa6?\b\xeac\x88\x00\x00\u07d4V\xfe\xbf\x9e\x10\x03\xaf\x15\xb1\xbdI\a\xec\b\x9aJ\x1b\x91\xd2h\x89\n\u05ce\xbcZ\xc6 \x00\x00\u07d4W\x17\u0313\x01Q\x1dJ\x81\xb9\xf5\x83\x14\x8b\xee\xd3\xd3\u0303\t\x89\x8c\xf2?\x90\x9c\x0f\xa0\x00\x00\u07d4W\x17\xf2\xd8\xf1\x8f\xfc\xc0\xe5\xfe$}:B\x19\x03|:d\x9c\x89\u063beI\xb0+\xb8\x00\x00\u07d4W\x19P\xea,\x90\xc1B}\x93\x9da\xb4\xf2\xdeL\xf1\u03ff\xb0\x89\x01\x15\x8eF\t\x13\xd0\x00\x00\u07d4W\x19\xf4\x9br\r\xa6\x88V\xf4\xb9\xe7\b\xf2VE\xbd\xbcKA\x89\"\xb1\xc8\xc1\"z\x00\x00\x00\u07d4W*\xc1\xab\xa0\xde#\xaeA\xa7\xca\xe1\xdc\bB\u062b\xfc\x10;\x89g\x8a\x93 b\xe4\x18\x00\x00\xe0\x94W-\xd8\xcd?\xe3\x99\xd1\xd0\xec(\x121\xb7\xce\xfc \xb9\u4eca\x023\xc8\xfeBp>\x80\x00\x00\xe0\x94WI!\x83\x8c\xc7}l\x98\xb1}\x90::\xe0\xee\r\xa9[\u040a\vS(\x17\x8a\xd0\xf2\xa0\x00\x00\u07d4WJ\xd95S\x90\u421e\xf4*\xcd\x13\x8b*'\xe7\x8c\x00\xae\x89Tg\xb72\xa9\x134\x00\x00\u07d4WM\xe1\xb3\xf3\x8d\x91XF\xae7\x18VJZ\xda \xc2\xf3\xed\x89\xd8\xd7&\xb7\x17z\x80\x00\x00\xe0\x94W\\\x00\u0081\x82\x10\u0085U\xa0\xff)\x01\x02\x89\xd3\xf8#\t\x8a\x02\x1e\x19\xe0\u027a\xb2@\x00\x00\xe0\x94Ws\xb6\x02g!\xa1\xdd\x04\xb7\x82\x8c\xd6+Y\x1b\xfb4SL\x8a\x05\xb7\xacES\xdez\xe0\x00\x00\xe0\x94WwD\x1c\x83\xe0?\v\xe8\xdd4\v\xdechP\x84|b\v\x8a\x02\x1e\x19\xe0\u027a\xb2@\x00\x00\u07d4Wx\xff\u071b\x94\u0165\x9e\"N\xb9e\xb6\u0790\xf2\"\xd1p\x89\x12-\u007f\xf3f\x03\xfc\x00\x00\u07d4Wz\xee\xe8\u053c\b\xfc\x97\xab\x15n\xd5\u007f\xb9p\x92Sf\xbe\x89\x12\r\xf1\x14rX\xbf\x00\x00\u07d4W{-\a<Y\fP0o[\x11\x95\xa4\xb2\xba\x9e\u0366%\x89\x14@\xbd\u0515\x15\xf0\x00\x00\u07d4W{\xfed\xe3\xa1\xe3\x80\x0e\x94\xdb\x1cl\x18M\x8d\u022a\xfcf\x89Q4\xed\x17A\u007f(\x00\x00\u07d4W\x82Z\xeb\t\al\xaaGx\x87\xfb\u026e7\xe8\xb2|\xc9b\x89\x05k\xc7^-c\x10\x00\x00\u07d4W\x880\x10\xb4\xac\x85\u007f\xed\xac\x03\xea\xb2U\x17#\xa8D\u007f\xfb\x8965\u026d\xc5\u07a0\x00\x00\u07d4W\x89\xd0\x1d\xb1,\x81j\xc2h\xe9\xaf\x19\xdc\r\xd6\u065f\x15\u07c9\n\u05ce\xbcZ\xc6 \x00\x00\u07d4W\x92\x81OY\xa3:\x18C\xfa\xa0\x1b\xaa\b\x9e\xb0/\xfb\\\xf1\x89\x1b\x1a\xb3\x19\xf5\xecu\x00\x00\u07d4W\x93\xab\xe6\xf1S3\x11\xfdQSh\x91x;?\x96%\xef\x1c\x89,\u0626V\xf2?\xda\x00\x00\xe0\x94W\x97\xb6\x0f\u0489J\xb3\xc2\xf4\xae\u0786\xda\xf2\xe7\x88\xd7E\xad\x8a\x01EB\xba\x12\xa37\xc0\x00\x00\u07d4W\xa8R\xfd\xb9\xb1@[\xf5<\u03d5\b\xf82\x99\xd3 lR\x89lk\x93[\x8b\xbd@\x00\x00\u07d4W\xb2=j\x1a\xdc\x06\xc6R\xa7y\u01a7\xfbk\x95\xb9\xfe\xadf\x89\n\u05ce\xbcZ\xc6 \x00\x00\u07d4W\xbc \xe2\xd6+=\x19f<\xdbL0\x9d[O/\xc2\u06cf\x89\x05k\xc7^-c\x10\x00\x00\u07d4W\xbd\xdf\a\x884\x00\x9c\x89\u060eb\x82u\x9d\xc4S5\xb4p\x89tq|\xfbh\x83\x10\x00\x00\u07d4W\xbe\xeaql\xbd\x81p\ns\xd6\u007f\x9f\xf09R\x9c-\x90%\x89\n\u05ce\xbcZ\xc6 \x00\x00\u07d4W\xd02\xa4=\x16Nq\xaa.\xf3\xff\xd8I\x1b\nN\xf1\xea[\x89lk\x93[\x8b\xbd@\x00\x00\u07d4W\xd3\u07c0O+\xee\xe6\xefS\xab\x94\xcb>\xe9\xcfRJ\x18\u04c9\x15Vak\x96\x06g\x00\x00\u07d4W\xd5\xfd\x0e=0I3\x0f\xfc\xdc\xd0 Ei\x17e{\xa2\u0689k\xf2\x01\x95\xf5T\xd4\x00\x00\u07d4W\u0754q\xcb\xfa&'\t\xf5\U00106f37t\xc5\xf5'\xb8\xf8\x89\n\xad\xec\x98?\xcf\xf4\x00\x00\u07d4W\xdf#\xbe\xbd\xc6^\xb7_\ub732\xfa\xd1\xc0si++\xaf\x89\xd8\xd7&\xb7\x17z\x80\x00\x00\u07d4X\x00\u03410\x83\x9e\x94I]-\x84\x15\xa8\xea,\x90\xe0\xc5\u02c9\n\u05ce\xbcZ\xc6 \x00\x00\xe0\x94X\x03\xe6\x8b4\xda\x12\x1a\xef\b\xb6\x02\xba\u06ef\xb4\xd1$\x81\u028a\x03\xcf\xc8.7\xe9\xa7@\x00\x00\xe0\x94X\x16\xc2hww\xb6\xd7\u04a2C-Y\xa4\x1f\xa0Y\xe3\xa4\x06\x8a\x1cO\xe4:\xdb\n^\x90\x00\x00\u07d4X\x1a:\xf2\x97\xef\xa4Cj)\xaf\x00r\x92\x9a\xbf\x98&\xf5\x8b\x89lk\x93[\x8b\xbd@\x00\x00\xe0\x94X\x1b\x9f\xd6\xea\xe3r\xf3P\x1fB\xeb\x96\x19\xee\xc8 \xb7\x8a\x84\x8a\x04+\xe2\xc0\f\xa5;\x8d\x80\x00\u07d4X\x1b\xdf\x1b\xb2v\xdb\u0746\xae\xdc\xdb9z\x01\xef\xc0\xe0\f[\x8965\u026d\xc5\u07a0\x00\x00\u07d4X\x1f4\xb5#\xe5\xb4\x1c\t\xc8|)\x8e)\x9c\xbc\x0e)\xd0f\x89=X3\xaa\xfd9u\x80\x00\xe0\x94X$\xa7\xe2(8'q40\x8c_KP\u06b6^C\xbb1\x8a\x01EB\xba\x12\xa37\xc0\x00\x00\u07d4X+pf\x9c\x97\xaa\xb7\u0581H\xd8\xd4\xe9\x04\x11\xe2\x81\rV\x8965f3\xeb\xd8\xea\x00\x00\u07d4X.|\xc4o\x1d{Nn\x9d\x95\x86\x8b\xfd7\x05s\x17\x8fL\x89lk\x93[\x8b\xbd@\x00\x00\u07d4X>\x83\xbaU\xe6~\x13\xe0\xe7o\x83\x92\xd8s\xcd!\xfb\xf7\x98\x89\x01\x15\x8eF\t\x13\xd0\x00\x00\u07d4Xi\xfb\x86}q\xf18\u007f\x86;i\x8d\t\xfd\xfb\x87\u011b\\\x89\u01bb\xf8X\xb3\x16\b\x00\x00\u07d4X}hI\xb1h\xf6\xc33+z\xba\xe7\xeblB\xc3\u007fH\xbf\x89/\xb4t\t\x8fg\xc0\x00\x00\u07d4X\x87\xdcj3\xdf\xedZ\xc1\xed\xef\xe3^\xf9\x1a!b1\xac\x96\x89\r\x8drkqw\xa8\x00\x00\xe0\x94X\x8e\u0650\xa2\xaf\xf4J\x94\x10]X\xc3\x05%w5\xc8h\xac\x8a\x03h\xc8b:\x8bM\x10\x00\x00\u07d4X\xae-\xdc_L\x8a\u0697\xe0l\x00\x86\x17\x17g\xc4#\xf5\u05c9WG=\x05\u06ba\xe8\x00\x00\u07d4X\xae\xd6gJ\xff\xd9\xf6B3'*W\x8d\xd98k\x99\xc2c\x89\xb8Pz\x82\a( \x00\x00\xe0\x94X\xb8\b\xa6[Q\xe63\x89i\xaf\xb9^\xc7\a5\xe4Q\xd5&\x8a\bxK\xc1\xb9\x83z8\x00\x00\u07d4X\xb8\xae\x8fc\xef5\xed\ab\xf0\xb6#=J\xc1Nd\xb6M\x89lk\x93[\x8b\xbd@\x00\x00\u07d4X\xba\x15ie\x0e[\xbb\xb2\x1d5\xd3\xe1u\xc0\u05b0\xc6Q\xa9\x89\x1b\x1a\xe4\xd6\xe2\xefP\x00\x00\u07d4X\xc5U\xbc)<\xdb\x16\xc66.\xd9z\xe9U\v\x92\xea\x18\x0e\x89\x01\x15\x8eF\t\x13\xd0\x00\x00\u07d4X\xc6P\xce\xd4\v\xb6VA\xb8\xe8\xa9$\xa09\xde\xf4hT\u07c9\x01\x00\xbd3\xfb\x98\xba\x00\x00\u07d4X\xc9\aT\xd2\xf2\n\x1c\xb1\xdd3\x06%\xe0KE\xfaa\x9d\\\x89lk\x93[\x8b\xbd@\x00\x00\xe0\x94X\xe2\xf1\x12#\xfc\x827\xf6\x9d\x99\xc6(\x9c\x14\x8c\x06\x04\xf7B\x8a\x05\x15\n\xe8J\x8c\xdf\x00\x00\x00\u07d4X\xe5T\xaf=\x87b\x96 \xdaa\xd58\xc7\xf5\xb4\xb5LJ\xfe\x89FP\x9diE4r\x80\x00\u07d4X\xe5\xc9\xe3D\xc8\x06e\r\xac\xfc\x90M3\xed\xbaQ\a\xb0\u0789\x01\t\x10\xd4\xcd\xc9\xf6\x00\x00\u07d4X\xe6a\u043as\xd6\xcf$\t\x9aUb\xb8\b\xf7\xb3g;h\x89lk\x93[\x8b\xbd@\x00\x00\xe0\x94X\xf0[&%`P<\xa7a\xc6\x18\x90\xa4\x03_Lsr\x80\x8a\x01\xb1\xaeMn.\xf5\x00\x00\x00\u07d4X\xfb\x94sd\xe7iWe6\x1e\xbb\x1e\x80\x1f\xfb\x8b\x95\xe6\u0409\n\u05ce\xbcZ\xc6 \x00\x00\u07d4Y\x01\x81\xd4E\x00{\u0407Z\xaf\x06\x1c\x8dQ\x159\x00\x83j\x89lk\x93[\x8b\xbd@\x00\x00\u07d4Y\x02\xe4J\xf7i\xa8rF\xa2\x1e\a\x9c\b\xbf6\xb0n\xfe\xb3\x8965\u026d\xc5\u07a0\x00\x00\u07d4Y\n\xcb\xda7)\f\r>\xc8O\xc2\x00\rv\x97\xf9\xa4\xb1]\x89\x1b\x1a\xe4\xd6\xe2\xefP\x00\x00\xe0\x94Y\f\xcbY\x11\xcfx\xf6\xf6\"\xf55\xc4t7_J\x12\xcf\u03ca\x04<3\xc1\x93ud\x80\x00\x00\u07d4Y\x10\x10m\xeb\u0491\xa1\u0340\xb0\xfb\xbb\x8d\x8d\x9e\x93\xa7\xcc\x1e\x89lk\x93[\x8b\xbd@\x00\x00\u07d4Y\x16\x17I\xfe\xdc\xf1\xc7!\xf2 -\x13\xad\xe2\xab\xcfF\v=\x89lk\x93[\x8b\xbd@\x00\x00\xe0\x94Y\x1b\xef1q\xd1\u0155w\x17\xa4\xe9\x8d\x17\xeb\x14,!NV\x8a\x04<3\xc1\x93ud\x80\x00\x00\u07d4Y <\xc3u\x99\xb6H1*|\xc9\xe0m\xac\xb5\x89\xa9\xaej\x89\b\x0fyq\xb6@\x0e\x80\x00\u07d4Y&\x81q\xb83\xe0\xaa\x13\xc5KR\xcc\xc0B.O\xa0:\ub262\xa1]\tQ\x9b\xe0\x00\x00\xe0\x94Y'w&\x1e;\xd8R\u010e\u0295\xb3\xa4L[\u007f-B,\x8a\x04<3\xc1\x93ud\x80\x00\x00\u07d4Y0Dg\x0f\xae\xff\x00\xa5[Z\xe0Q\xeb{\xe8p\xb1\x16\x94\x89\a?u\u0460\x85\xba\x00\x00\xe0\x94Y;E\xa1\x86J\xc5\xc7\xe8\xf0\u02ae\xba\r\x87<\xd5\xd1\x13\xb2\x8a\x01EB\xba\x12\xa37\xc0\x00\x00\u07d4Y<H\x93[\xea\xff\x0f\xde\x19\xb0M0\x9c\xd50\xa2\x8eR\u0389\xd8\xd7&\xb7\x17z\x80\x00\x00\u07d4YG<\xd3\x00\xff\xfa\xe2@\xf5xV&\xc6]\xfe\u01d2\xb9\xaf\x89\x01\x15\x8eF\t\x13\xd0\x00\x00\u07d4YH\xbc6P\xedQ\x9b\xf8\x91\xa5rg\x9f\u0652\xf8x\fW\x89\n\xad\xec\x98?\xcf\xf4\x00\x00\u07d4YJv\xf0i58\x8d\xde^#F\x96\xa0f\x8b\xc2\r-\u0709\x97\xc9\xceL\xf6\xd5\xc0\x00\x00\u07d4YV\x9a!\u048f\xbaK\xda7u4\x05\xa0\x81\xf2\x06=\xa1P\x89\xd8\xd7&\xb7\x17z\x80\x00\x00\u07d4YV\xb2\x8e\u01c9\vv\xfc\x06\x1a\x1f\xebR\xd8*\xe8\x1f\xb65\x89lk\x93[\x8b\xbd@\x00\x00\u07d4Y^#\u05c8\xa2\u053b\x85\xa1]\xf7\x13m&JcU\x11\xb3\x89\u0556{\xe4\xfc?\x10\x00\x00\xe0\x94Yp8\xff\x91\xa0\x90\f\xbb\xabH\x8a\xf4\x83\u01d0\xe6\xec\x00\xa0\x8a\x02\x1e\x19\xe0\u027a\xb2@\x00\x00\xe0\x94Yp\xfb\x1b\x14M\xd7Q\xe4\xce.\xca|\xaa \xe3c\xdcM\xa3\x8a\x02\x1e\x19\xe0\u027a\xb2@\x00\x00\u07d4Yu\xb9R\x8f#\xaf\x1f\x0e.\xc0\x8a\xc8\xeb\xaaxj,\xb8\xe0\x89\x12\xbfPP:\xe3\x03\x80\x00\u07d4Yu\u05cd\x97N\u5edeML\xa2\xaew\xc8K\x9c;K\x82\x89JD\x91\xbdm\xcd(\x00\x00\u07d4Y\x85\u015aD\x9d\xfc]\xa7\x87\xd8$Ntlmp\u02a5_\x89\x05k\xc7^-c\x10\x00\x00\u07d4Y\x8a\xaa\xba\xe9\xed\x83={\xc2\"\xe9\x1f\u02a0d{wX\v\x89a\x94\x04\x9f0\xf7 \x00\x00\u07d4Y\x92bLT\xcd\xec`\xa5\xae\x93\x803\xaf\x8b\xe0\xc5\f\xbb\n\x89\xc4T\xe0\xf8\x87\x0f+\x00\x00\xe0\x94Y\x97(\xa7\x86\x18\u0461{\x9e4\xe0\xfe\xd8\xe8W\xd5\xc4\x06\"\x8a\x02\xf6\xf1\a\x80\xd2,\xc0\x00\x00\u07d4Y\x97\xff\xef\xb3\xc1\xd9\xd1\x0f\x1a\u2b0a\xc3\xc8\xe2\xd2)'\x83\x8965\u026d\xc5\u07a0\x00\x00\u07d4Y\xa0\x87\xb95\x1c\xa4/X\xf3n\x02\x19'\xa2)\x88(O8\x89\x01\x00\xbd3\xfb\x98\xba\x00\x00\u07d4Y\xa1-\xf2\xe3\xef\x85z\xce\xff\x93\x06\xb3\t\xf6\xa5\x00\xf7\x014\x8965\u026d\xc5\u07a0\x00\x00\u07d4Y\xb9m\ub1c4\x88]\x8d;J\x16aC\xccC]%U\xa1\x89Hz\x9a0E9D\x00\x00\u07d4Y\xb9\xe73\u02e4\xbe\x00B\x9bK\xd9\u07e6G2\x05:}U\x89\x01\x15\x8eF\t\x13\xd0\x00\x00\xe0\x94Y\xc5\xd0k\x17\x0e\xe4\xd2n\xb0\xa0\xebF\xcb}\x90\xc1\xc9\x10\x19\x8a\x02\x1e\x19\xe0\u027a\xb2@\x00\x00\u07d4Y\xc7\xf7\x85\xc91`\xe5\x80~\xd3N^SK\xc6\x18\x86G\xa7\x89\"\xb1\xc8\xc1\"z\x00\x00\x00\u07d4Y\xd19\xe2\xe4\f{\x97#\x9d#\u07ec\xa38X\xf6\x02\xd2+\x89lk\x93[\x8b\xbd@\x00\x00\u07d4Y\xf6${\rX*\xaa%\xe5\x11Ge\xe4\xbf<wOC\u0089\x02\xb5\xe3\xaf\x16\xb1\x88\x00\x00\u07d4Y\xfe\x00im\xbd\x87\xb7\x97k)\xd1\x15l\x88B\xa2\xe1y\x14\x89lk\x93[\x8b\xbd@\x00\x00\xe0\x94Z\r`\x9a\xae#2\xb17\xab;/&aZ\x80\x8f7\xe43\x8a!\xe1\x9e\f\x9b\xab$\x00\x00\x00\u07d4Z\x19+\x96J\xfd\x80w>_^\xdajV\xf1N%\xe0\xc6\xf3\x89\x1b\x1a\xe4\xd6\xe2\xefP\x00\x00\u07d4Z\x1a3ib\xd6\xe0\xc601\u0303\u01a5\u01a6\xf4G\x8e\u02c965\u026d\xc5\u07a0\x00\x00\u07d4Z\x1d--\x1dR\x03\x04\xb6 \x88IW\x047\xeb0\x91\xbb\x9f\x89j\xcb=\xf2~\x1f\x88\x00\x00\u07d4Z&s1\xfa\xcb&-\xaa\xec\xd9\xddc\xa9p\f_RY\u07c9\x05k\xc7^-c\x10\x00\x00\xe0\x94Z(WU9\x1e\x91NX\x02_\xaaH\xcch_O\xd4\xf5\xb8\x8a\x05\x81v{\xa6\x18\x9c@\x00\x00\u07d4Z)\x16\xb8\xd2\xe8\xcc\x12\xe2\a\xabFMC>#p\xd8#\u0649lk\x93[\x8b\xbd@\x00\x00\u07d4Z+\x1c\x85:\xeb(\xc4U9\xafv\xa0\n\xc2\u0628$(\x96\x89\x01Z\xf1\u05cbX\xc4\x00\x00\u07d4Z-\xaa\xb2\\1\xa6\x1a\x92\xa4\xc8,\x99%\xa1\xd2\xefXX^\x89\f8\r\xa9\u01d5\f\x00\x00\u07d4Z0\xfe\xac7\xac\x9fr\u05f4\xaf\x0f+\xc79R\xc7O\xd5\u00c9lk\x93[\x8b\xbd@\x00\x00\u07d4ZTh\xfa\\\xa2&\xc7S.\xcf\x06\xe1\xbc\x1cE\"]~\u0249g\x8a\x93 b\xe4\x18\x00\x00\u07d4ZVR\x857JI\xee\xddPL\x95}Q\bt\xd0\x04U\xbc\x89\x05k\xc7^-c\x10\x00\x00\u07d4Z^\xe8\xe9\xbb\x0e\x8a\xb2\xfe\xcbK3\u0494x\xbeP\xbb\xd4K\x89*\x11)\u0413g \x00\x00\xe0\x94Z_\x85\b\xda\x0e\xbe\xbb\x90\xbe\x903\xbdM\x9e'A\x05\xae\x00\x8a\x01je\x02\xf1Z\x1eT\x00\x00\u07d4Z`q\xbc\xeb\xfc\xbaJ\xb5\u007fM\xb9o\u01e6\x8b\xec\xe2\xba[\x89lk\x93[\x8b\xbd@\x00\x00\u07d4Z`\xc9$\x16(s\xfc~\xa4\xda\u007f\x97.5\x01g7`1\x89\x04\x87\xf2w\xa8\x85y\x80\x00\u07d4Zf\x86\xb0\xf1~\a\xed\xfcY\xb7Y\xc7}[\xef\x16M8y\x89P\xc5\xe7a\xa4D\b\x00\x00\u07d4Zp\x10o \xd6?\x87Re\xe4\x8e\r5\xf0\x0e\x17\xd0+\u0249\x01\x15\x8eF\t\x13\xd0\x00\x00\u0794Zt\xbab\xe7\xc8\x1a4t\xe2}\x89O\xed3\xdd$\xad\x95\xfe\x88\xfc\x93c\x92\x80\x1c\x00\x00\xe0\x94Zw5\x00}p\xb0hD\u0699\x01\xcd\xfa\xdb\x11\xa2X,/\x8a\x01EB\xba\x12\xa37\xc0\x00\x00\u07d4Z\x82\xf9l\u0537\xe2\xd9=\x10\xf3\x18]\xc8\xf4=Ku\xaai\x89lc?\xba\xb9\x8c\x04\x00\x00\u07d4Z\x87\xf04\xe6\xf6\x8fNt\xff\xe6\fd\x81\x946\x03l\xf7\u05c9\x01\x15\x8eF\t\x13\xd0\x00\x00\xe0\x94Z\x89\x11U\xf5\x0eB\aCt\xc79\xba\xad\xf7\xdf&Q\x15:\x8a\x01\x02\xdao\xd0\xf7:<\x00\x00\u07d4Z\x9c\x8bi\xfcaMiVI\x99\xb0\r\xcbB\xdbg\xf9~\x90\x89\xb9\xe6\x15\xab\xad:w\x80\x00\xe0\x94Z\xaf\x1c1%Jn\x00_\xba\u007fZ\xb0\xecy\xd7\xfc+c\x0e\x8a\x01@a\xb9\xd7z^\x98\x00\x00\u07d4Z\xb1\xa5aSH\x00\x1c|w]\xc7WHf\x9b\x8b\xe4\xde\x14\x89%jr\xfb)\xe6\x9c\x00\x00\xe1\x94Z\xbf\xec%\xf7L\u06047c\x1aw1\x90i2wcV\xf9\x8b\t\xd8<\xc0\u07e1\x11w\xff\x80\x00\u07d4Z\u0090\x8b\x0f9\x8c\r\xf5\xba\xc2\xcb\x13\xcas\x14\xfb\xa8\xfa=\x89\n\xd4\xc81j\v\f\x00\x00\xe0\x94Z\u025a\u05c1j\xe9\x02\x0f\xf8\xad\xf7\x9f\xa9\x86\x9b|\xeaf\x01\x8a\x04ri\x8bA;C \x00\x00\u07d4Z\xd1,^\xd4\xfa\x82~!P\u03e0\u058c\n\xa3{\x17i\xb8\x89+^:\xf1k\x18\x80\x00\x00\xe0\x94Z\xd5\xe4 uV\x13\x88o5\xaaV\xac@>\xeb\xdf\xe4\xb0\u040a\x10\xf0\xcf\x06M\u0552\x00\x00\x00\u07d4Z\xdew\xfd\x81\xc2\\\n\xf7\x13\xb1\a\x02v\x8c\x1e\xb2\xf9u\xe7\x89\x01\x15\x8eF\t\x13\xd0\x00\x00\u07d4Z\xe6N\x85;\xa0\xa5\x12\x82\u02cd\xb5.Aa^|\x9fs?\x89lk\x93[\x8b\xbd@\x00\x00\u07d4Z\xed\x0el\xfe\x95\xf9\u0580\xc7dr\xa8\x1a+h\n\u007f\x93\xe2\x89\n\xad\xec\x98?\xcf\xf4\x00\x00\u07d4Z\xef\x16\xa2&\xddh\a\x1f$\x83\xe1\xdaBY\x83\x19\xf6\x9b,\x89lk\x93[\x8b\xbd@\x00\x00\u07d4Z\xf4j%\xac\t\xcbsakS\xb1O\xb4/\xf0\xa5\x1c\u0772\x89\xd8\xd7&\xb7\x17z\x80\x00\x00\u07d4Z\xf7\xc0r\xb2\u016c\xd7\x1cv\xad\xdc\xceS\\\xf7\xf8\xf95\x85\x89\x01\x15\x8eF\t\x13\xd0\x00\x00\xe0\x94Z\xfd\xa9@\\\x8e\x976QEt\u0692\x8d\xe6tV\x01\t\x18\x8a\x01E\xb8\xb0#\x9aF\x92\x00\x00\u07d4[\x06\xd1\xe6\x93\f\x10Ti+y\xe3\xdb\xe6\xec\xceS\x96d \x89\v\"\u007fc\xbe\x81<\x00\x00\u07d4[%\xca\xe8m\xca\xfa*`\xe7r61\xfc_\xa4\x9c\x1a\xd8}\x89\x87\fXQ\x0e\x85 \x00\x00\u07d4[(|~sB\x99\xe7'bo\x93\xfb\x11\x87\xa6\rPW\xfe\x89\x05|\xd94\xa9\x14\xcb\x00\x00\u07d4[)\f\x01\x96|\x81.M\xc4\xc9\v\x17L\x1b@\x15\xba\xe7\x1e\x89\b \xeb4\x8dR\xb9\x00\x00\u07d4[+d\xe9\xc0X\u30a8\xb2\x99\"N\xec\xaa\x16\xe0\x9c\x8d\x92\x89\b\xbaR\xe6\xfcE\xe4\x00\x00\xe0\x94[./\x16\x18U.\xab\r\xb9\x8a\xddUc|)Q\xf1\xfb\x19\x8a\x02\x8a\x85t%Fo\x80\x00\x00\u07d4[0`\x8cg\x8e\x1a\xc4d\xa8\x99L;3\xe5\xcd\xf3Iq\x12\x89\x15\xaf\x1dx\xb5\x8c@\x00\x00\u07d4[36\x96\xe0L\xca\x16\x92\xe7\x19\x86W\x9c\x92\rk)\x16\xf9\x89\x1b\x1a\xe4\xd6\xe2\xefP\x00\x00\xe0\x94[C\rw\x96\x96\xa3e?\xc6\x0et\xfb\u02ec\xf6\xb9\u00ba\xf1\x8a\x02\xf6\xf1\a\x80\xd2,\xc0\x00\x00\u07d4[Cse\xae:\x9a/\xf9|h\xe6\xf9\nv \x18\x8c}\x19\x89l\x87T\xc8\xf3\f\b\x00\x00\u07d4[I\xaf\xcduDx8\xf6\xe7\xce\u068d!w}O\xc1\xc3\xc0\x89\xd8\xd7&\xb7\x17z\x80\x00\x00\u07d4[L\f`\xf1\x0e\u0489K\xdbB\xd9\xdd\x1d!\x05\x87\x81\n\r\x89\x1b\x1a\xe4\xd6\xe2\xefP\x00\x00\u07d4[N\xa1m\xb6\x80\x9b\x03R\u0536\xe8\x1c9\x13\xf7jQ\xbb2\x89\x15\xaf\x1dx\xb5\x8c@\x00\x00\u07d4[[\xe0\xd8\xc6rv\xba\xab\xd8\xed\xb3\rH\xeaud\v\x8b)\x89,\xb1\xf5_\xb7\xbe\x10\x00\x00\u07d4[]Qp)2\x15b\x11\x1bC\bm\v\x045\x91\x10\x9ap\x89\x8c\xf2?\x90\x9c\x0f\xa0\x00\x00\xe0\x94[]\x8c\x8e\xedl\x85\xac!Va\xde\x02fv\x82?\xaa\n\f\x8a\x04<3\xc1\x93ud\x80\x00\x00\u07d4[mU\xf6q)g@\\e\x91)\xf4\xb1\xde\t\xac\xf2\xcb{\x89\x0e~\xeb\xa3A\vt\x00\x00\u07d4[p\u011c\u024b=\xf3\xfb\xe2\xb1Y\u007f\\\x1bcG\xa3\x88\xb7\x894\x95tD\xb8@\xe8\x00\x00\u07d4[sn\xb1\x83Sb\x9b\u0796v\xda\xdd\x16P4\xce^\xcch\x89j\xcb=\xf2~\x1f\x88\x00\x00\u07d4[u\x9f\xa1\x10\xa3\x1c\x88F\x9fT\xd4K\xa3\x03\xd5}\xd3\xe1\x0f\x89[F\xdd/\x0e\xa3\xb8\x00\x00\u07d4[w\x84\xca\xea\x01y\x9c\xa3\x02'\x82vg\xce |\\\xbcv\x89lk\x93[\x8b\xbd@\x00\x00\u07d4[x\xec\xa2\u007f\xbd\xeao&\xbe\xfb\xa8\x97+)^x\x146K\x89lk\x93[\x8b\xbd@\x00\x00\xe0\x94[\x80\v\xfd\x1b>\u0525}\x87Z\xed&\xd4/\x1aw\b\xd7*\x8a\x01Z\x82\xd1\u057b\x88\xe0\x00\x00\u07d4[\x85\xe6\x0e*\xf0TO/\x01\xc6N 2\x90\x0e\xbd8\xa3\u01c9lk\x93[\x8b\xbd@\x00\x00\u07d4[\xa2\xc6\xc3]\xfa\xec)h&Y\x19\x04\xd5DFJ\xea\xbd^\x89\x01\x15\x8eF\t\x13\xd0\x00\x00\xe0\x94[\xafmt\x96 \x80>\x83H\xaf7\x10\xe5\xc4\xfb\xf2\x0f\u0214\x8a\x01\x0f@\x02a]\xfe\x90\x00\x00\u07d4[\xc1\xf9U\a\xb1\x01\x86B\xe4\\\xd9\xc0\xe2'3\xb9\xb1\xa3&\x89\x05k\xc7^-c\x10\x00\x00\xe0\x94[\xd25GG\u007fm\t\u05f2\xa0\x05\xc5\xeee\fQ\fV\u05ca\x02\x1e\x19\xe0\u027a\xb2@\x00\x00\u07d4[\xd2J\xac6\x12\xb2\f`\x9e\xb4gy\xbf\x95i\x84\a\xc5|\x89j\xcb=\xf2~\x1f\x88\x00\x00\u07d4[\u0586-Q}M\xe4U\x9dN\xec\n\x06\xca\xd0^/\x94n\x89\n\u05ce\xbcZ\xc6 \x00\x00\u07d4[\xe0EQ*\x02n?\x1c\xeb\xfdZ~\xc0\xcf\xc3o-\xc1k\x89\x06\x81U\xa46v\xe0\x00\x00\xe0\x94[\xf9\xf2\"nZ\xea\xcf\x1d\x80\xae\nY\xc6\xe3\x808\xbc\x8d\xb5\x8a\x01EB\xba\x12\xa37\xc0\x00\x00\u07d4[\xfa\xfe\x97\xb1\xdd\x1dq+\xe8mA\xdfy\x89SE\x87Z\x87\x89\x1b\x1a\xe4\xd6\xe2\xefP\x00\x00\xe0\x94\\\x0f.Q7\x8fk\r{\xabas1X\vn9\xad<\xa5\x8a\x02\bj\xc3Q\x05&\x00\x00\x00\u07d4\\)\xf9\xe9\xa5#\xc1\xf8f\x94H\xb5\\H\xcb\xd4|%\xe6\x10\x894F\xa0\xda\xd0L\xb0\x00\x00\xe0\x94\\0\x8b\xacHW\xd3;\xae\xa0t\xf3\x95m6!\xd9\xfa(\xe1\x8a\x01\x0f\b\xed\xa8\xe5U\t\x80\x00\u07d4\\1*V\u01c4\xb1\"\t\x9bvM\x05\x9c!\xec\xe9^\x84\u0289\x05&c\u032b\x1e\x1c\x00\x00\u07d4\\1\x99m\xca\xc0\x15\xf9\xbe\x98[a\x1fF\x870\xef$M\x90\x89\n\u05ce\xbcZ\xc6 \x00\x00\xe0\x94\\24W\xe1\x87v\x1a\x82v\xe3Y\xb7\xb7\xaf?;n=\xf6\x8a\x02\x1e\x19\xe0\u027a\xb2@\x00\x00\u07d4\\<\x1cd[\x91uC\x11;>l\x1c\x05M\xa1\xfet+\x9a\x89+^:\xf1k\x18\x80\x00\x00\u0794\\=\x19D\x1d\x19l\xb4Cf \xfc\xad\u007f\xbby\xb2\x9ex\x88\xc6s\xce<@\x16\x00\x00\u07d4\\?V\u007f\xaf\xf7\xba\u0475\x12\x00\"\xe8\xcb\u02a8+I\x17\xb3\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\\Ch\x91\x8a\xced\t\u01de\u0280\u036a\xe49\x1d+bN\x89\xd8\xd7&\xb7\x17z\x80\x00\x00\xe0\x94\\FA\x97y\x1c\x8a=\xa3\xc9%Co'z\xb1;\xf2\xfa\xa2\x8a\x01\xb1\xaeMn.\xf5\x00\x00\x00\u07d4\\H\x81\x16\\\xb4+\xb8.\x979l\x8e\xf4J\xdb\xf1s\xfb\x99\x89\x05\xfe\xe2\"\x04\x1e4\x00\x00\xe0\x94\\H\x92\x90z\a \xdfo\xd3A>c\xffv}k9\x80#\x8a\x02\xcb\x00\x9f\u04f5y\x0f\x80\x00\u07d4\\O$\xe9\x94\ud3c5\x0e\xa7\x81\x8fG\x1c\x8f\xac;\xcf\x04R\x89]\x80h\x8d\x9e1\xc0\x00\x00\u07d4\\T\x19V\\:\xadNqN\a92\x8e5!\u024f\x05\u0309\x1c\x9fx\u0489>@\x00\x00\u07d4\\a6\xe2\x18\xde\na\xa17\xb2\xb3\x96-*a\x12\xb8\t\u05c9\x0f\xf3\u06f6_\xf4\x86\x80\x00\xe0\x94\\a\xaby\xb4\b\xdd2)\xf6bY7\x05\xd7/\x1e\x14{\xb8\x8a\x04\xd0$=4\x98\u0344\x00\x00\u07d4\\m\x04\x1d\xa7\xafD\x87\xb9\xdcH\xe8\xe1\xf6\af\u0425m\xbc\x89O\a\n\x00>\x9ct\x00\x00\u07d4\\o6\xaf\x90\xab\x1aeln\xc8\xc7\xd5!Q'b\xbb\xa3\xe1\x89lh\xcc\u041b\x02,\x00\x00\u07d4\\{\x9e\u01e2C\x8d\x1e<v\x98\xb5E\xb9\xc3\xfdw\xb7\xcdU\x8965\u026d\xc5\u07a0\x00\x00\u07d4\\\x93o;\x9d\"\xc4\x03\xdb^s\x0f\xf1w\xd7N\xefB\u06ff\x89\x04\x10\u0546\xa2\nL\x00\x00\u07d4\\\xb71\x16\r.\x89eg\v\u0792]\x9d\xe5Q\t54}\x89\x02+\x1c\x8c\x12'\xa0\x00\x00\u07d4\\\xb9S\xa0\xe4/P0\x81\"&!\u007f\xff\xc3\xce#\x04W\xe4\x89\x05k\xc7^-c\x10\x00\x00\u0794\\\xbd\x8d\xaf'\xdd\xf7\x04\xcd\xd0\xd9\t\xa7\x89\xba6\xedO7\xb2\x88\xb9\xf6]\x00\xf6<\x00\x00\xe0\x94\\\xc4\u02e6!\xf2 cwB\x05\u007f`U\xb8\r\xff\xd7~\x13\x8a\bxG{}%;f\x00\x00\xe0\x94\\\xc7\xd3\x06mE\xd2v!\xf7\x8b\xb4\xb39G>D*\x86\x0f\x8a\x02\x1e\x18\x99\xf07z\xea\x00\x00\u07d4\\\xcc\xf1P\x8b\xfd5\xc2\x050\xaad%\x00\xc1\r\xeee\xea\xed\x89.\x14\x1e\xa0\x81\xca\b\x00\x00\u07d4\\\xcer\xd0h\xc7\xc3\xf5[\x1d(\x19T^w1|\xae\x82@\x89i*\xe8\x89p\x81\xd0\x00\x00\u07d4\\\xd0\xe4u\xb5D!\xbd\xfc\f\x12\xea\x8e\b+\u05e5\xaf\nj\x89\x032\xca\x1bg\x94\f\x00\x00\u07d4\\\u0548\xa1N\xc6H\xcc\xf6G)\xf9\x16z\xa7\xbf\x8b\xe6\xeb=\x8965\u026d\xc5\u07a0\x00\x00\u07d4\\\u062f`\xdee\xf2M\xc3\xceW0\xba\x92e0\"\xdcYc\x89a\t=|,m8\x00\x00\u07d4\\\xdcG\b\xf1O@\xdc\xc1Zy_}\xc8\xcb\v\u007f\xaa\x9en\x89\x1d\x1c_>\xda \xc4\x00\x00\u07d4\\\u0d86,\u0391b\xe8~\bI\xe3\x87\xcb]\xf4\xf9\x11\x8c\x89Z\x87\xe7\xd7\xf5\xf6X\x00\x00\xe0\x94\\\xe2\xe7\u03aa\xa1\x8a\xf0\xf8\xaa\xfa\u007f\xba\xd7L\u021e<\xd46\x8a\x04<3\xc1\x93ud\x80\x00\x00\u07d4\\\xe4@h\xb8\xf4\xa3\xfey\x9ej\x83\x11\xdb\xfd\xed\xa2\x9d\xee\x0e\x89lk\x93[\x8b\xbd@\x00\x00\u0794\\\xeb\xe3\v*\x95\xf4\xae\xfd\xa6ee\x1d\xc0\xcf~\xf5u\x81\x99\x88\xfc\x93c\x92\x80\x1c\x00\x00\u07d4\\\xf1\x8f\xa7\u0227\xc0\xa2\xb3\xd5\xef\u0459\x0fd\xdd\xc5i$,\x8965\u026d\xc5\u07a0\x00\x00\xe0\x94\\\xf4N\x10T\reqd#\xb1\xbc\xb5B\xd2\x1f\xf8:\x94\u034a\x02\x1e\x19\xe0\u027a\xb2@\x00\x00\u07d4\\\xf8\xc0>\xb3\xe8r\xe5\x0f|\xfd\f/\x8d;?,\xb5\x18:\x89\n\u05ce\xbcZ\xc6 \x00\x00\u07d4\\\xfa\x8dV\x85ue\x8c\xa4\xc1\xa5\x93\xacL]\x0eD\xc6\aE\x89\x0f\xc6o\xae7F\xac\x00\x00\u07d4\\\xfa\x98w\xf7\x19\u01dd\x9eIJ\b\xd1\xe4\x1c\xf1\x03\xfc\x87\u0249\n\u05ce\xbcZ\xc6 \x00\x00\u07d4]\x1d\xc38{G\xb8E\x1eU\x10l\f\xc6}m\xc7+\u007f\v\x89lk\x93[\x8b\xbd@\x00\x00\u07d4]#\x1ap\xc1\xdf\xeb6\n\xbd\x97\xf6\x16\xe2\xd1\r9\xf3\u02b5\x89\x15\xaf\x1dx\xb5\x8c@\x00\x00\u07d4]$\xbd\xbc\x1cG\xf0\xeb\x83\xd1(\xca\xe4\x8a\xc3<H\x17\xe9\x1f\x8965\u026d\xc5\u07a0\x00\x00\u07d4](\x19\xe8\xd5x!\x92.\xe4Ee\f\xca\xec}@TJ\x8d\x89\n\u05ce\xbcZ\xc6 \x00\x00\u07d4]/\u007f\v\x04\xbaK\xe1a\u1736\xf1\x12\xcez^}\u007f\xe4\x89\x01\xe8\u007f\x85\x80\x9d\xc0\x00\x00\u07d4]2\xf6\xf8nx\u007f\xf7\x8ec\u05cb\x0e\xf9_\xe6\a\x18R\xb8\x89\x15\xbeat\xe1\x91.\x00\x00\u07d4]9\uf7a6\xbd\xff\xf1]\x11\xfe\x91\xf5a\xa6\xf9\xe3\x1f]\xa5\x89lk\x93[\x8b\xbd@\x00\x00\xe0\x94]?;\x1fq0\xb0\xbb!\xa0\xfd29b9\x17\x9a%e\u007f\x8a\r:\xb8\xea^\x8f\xd9\xe8\x00\x00\u07d4]WQ\x81\x9bO=&\xed\f\x1a\xc5qU'5'\x1d\xbe\xfa\x8965\u026d\xc5\u07a0\x00\x00\u07d4]\\,\x10\x99\xbb\xee\xfb&~t\xb5\x88\x80\xb4D\xd9DI\xe0\x89\r\xbf\v\u0441\xe2\xe7\x00\x00\u07d4]\\\xdb\xe2[*\x04K{\x9b\u30fc\xaaX\a\xb0m<k\x89lk\x93[\x8b\xbd@\x00\x00\u07d4]]n\x82\x1cn\uf581\f\x83\u0111F\x85`\xefp\xbf\xb5\x89lk\x93[\x8b\xbd@\x00\x00\u07d4]h2K\xcbwm?\xfd\v\xf9\xfe\xa9\x1d\x9f\x03\u007f\u05ab\x0f\x89lk\x93[\x8b\xbd@\x00\x00\u07d4]j\xe8\xcb\u05b39<\"\xd1bT\x10\r\x028\xe8\b\x14|\x89'\a\xe5mQ\xa3\f\x00\x00\u07d4]l\\r\rf\xa6\xab\u0283\x97\x14.c\xd2h\x18\xea\xabT\x89\x02+\x1c\x8c\x12'\xa0\x00\x00\u07d4]l\u03c0g8\t\x10B\xad\x97\xa6\xe0\x95\xfe\x8c6\xaay\u0149\n1\x06+\xee\xedp\x00\x00\u07d4]qy\x9c\x8d\xf3\xbc\xcb~\xe4F\xdfP\xb81+\xc4\xebq\u0149\n\u05ce\xbcZ\xc6 \x00\x00\u07d4]\x82-\x9b>\xf4\xb5\x02bt\a\xda'/g\x81Jk\xec\u0509\x01\x15\x8eF\t\x13\xd0\x00\x00\u07d4]\x83\xb2\x1b\xd2q#`Ckg\xa5\x97\xee3x\xdb>z\xe4\x89lk\x93[\x8b\xbd@\x00\x00\xe0\x94]\x87+\x12.\x99N\xf2|q\xd7\u07b4W\xbfeB\x9e\xcal\x8a\x01\xb1\xad\xed\x81\u04d4\x10\x80\x00\xe0\x94]\x8d1\xfa\xa8d\xe2!Y\xcdoQu\xcc\xec\xc5?\xa5Mr\x8a\x05\xb6\x96\xb7\r\xd5g\x10\x00\x00\xe0\x94]\x95\x8a\x9b\u0449\u0098_\x86\u014a\x8ci\xa7\xa7\x88\x06\xe8\u068a\x02(\xf1o\x86\x15x`\x00\x00\u07d4]\xa2\xa9\xa4\xc2\xc0\xa4\xa9$\xcb\xe0\xa5:\xb9\xd0\xc6'\xa1\u03e0\x89'\xbf8\xc6TM\xf5\x00\x00\u07d4]\xa4\u0288\x93\\'\xf5\\1\x10H\x84\x0eX\x9e\x04\xa8\xa0I\x89\x04V9\x18$O@\x00\x00\u07d4]\xa5G\x85\u027d0W\\\x89\u07b5\x9d A\xd2\n9\xe1{\x89j\xa2\t\xf0\xb9\x1de\x80\x00\xe0\x94]\xb6\x9f\xe9>o\xb6\xfb\xd4P\x96k\x97#\x8b\x11\n\xd8'\x9a\x8a\bxg\x83&\xea\xc9\x00\x00\x00\u07d4]\xb7\xbb\xa1\xf9W?$\x11]\x8c\x8cb\xe9\u0388\x95\x06\x8e\x9f\x89\x02\xb5\xaa\xd7,e \x00\x00\xe0\x94]\xb8D\x00W\x00i\xa9W<\xab\x04\xb4\u6d955\xe2\x02\xb8\x8a\x02\r\u058a\xaf2\x89\x10\x00\x00\u07d4]\xc3m\xe55\x94P\xa1\xec\t\xcb\fD\xcf+\xb4+:\xe45\x89<\x94m\x89;3\x06\x00\x00\u07d4]\xc6\xf4_\xef&\xb0n3\x021?\x88M\xafH\xe2to\xb9\x89\x1b\x1a\xe4\xd6\xe2\xefP\x00\x00\xe0\x94]\u0376\xb8zP<m\x8a<e\xc2\u03da\x9a\xa8\x83G\x9a\x1e\x8a\x01\xf2\xbb\xa5\xd8O\x99\xc0\x00\x00\u07d4]\xd1\x12\xf3h\xc0\xe6\xce\xffw\xa9\xdf\x02\xa5H\x16Q\xa0/\xb7\x89\t4r\xc8\\mT\x00\x00\xe0\x94]\xd5:\xe8\x97Rk\x16}9\xf1tN\xf7\xc3\xda[7\xa2\x93\x8a\x01\xb1\xaeMn.\xf5\x00\x00\x00\u07d4]\xde\xd0I\xa6\xe1\xf3)\xdcK\x97\x1er,\x9c\x1f*\u0783\xf0\x8965\u026d\xc5\u07a0\x00\x00\u07d4]\u562b\xa3D7\x8c\xabD1U[Oy\x99-\u0090\u0189Hz\x9a0E9D\x00\x00\u07d4]\xe9\xe7\xd5\u0476g\u0415\xdd4\t\x9c\x85\xb0B\x1a\v\u0181\x89\x01\x15\x8eF\t\x13\xd0\x00\x00\u07d4]\xf3'|\xa8Y6\u01e0\xd2\xc0yV\x05\xad%\t^qY\x89lk\x93[\x8b\xbd@\x00\x00\u07d4]\xff\x81\x1d\xad\x81\x9e\xce;\xa6\x02\u00c3\xfb]\xc6L\n:H\x89\n\x15D\xbe\x87\x9e\xa8\x00\x00\u0794^\x03\x1b\nrDq\xd4v\xf3\xbc\xd2\xeb\a\x838\xbfg\xfb\xef\x88\xfc\x93c\x92\x80\x1c\x00\x00\xe0\x94^\a\x85S,w#\xe4\xc0\xaf\x93W\xd5'Ks\xbd\xdd\xdd\u078a\x05KA\xea\x9b\xdba\xdc\x00\x00\u07d4^\x11\xec\xf6\x9dU\x1d\u007fO\x84\xdf\x12\x80F\xb3\xa12@\xa3(\x89\x01\x15\x8eF\t\x13\xd0\x00\x00\xe0\x94^\x1f\xbdNX\xe21+<x\u05ea\xaa\xfa\x10\xbf\x9c1\x89\xe3\x8a\bxg\x83&\xea\xc9\x00\x00\x00\xe0\x94^2\xc7!\x91\xb89,U\xf5\x10\xd8\xe32n:`P\x1db\x8a\tQ>\xa9\xde\x02C\x80\x00\x00\u07d4^Q\xb8\xa3\xbb\t\xd3\x03\xea|\x86\x05\x15\x82\xfd`\x0f\xb3\xdc\x1a\x89\x01\x15\x8eF\t\x13\xd0\x00\x00\u0794^X\xe2U\xfc\x19\x87\n\x040_\xf2\xa0F1\xf2\xff)K\xb1\x88\xf4?\xc2\xc0N\xe0\x00\x00\u07d4^ZD\x19t\xa8=t\u0187\xeb\xdcc?\xb1\xa4\x9e{\x1a\u05c9\xa2\xa1]\tQ\x9b\xe0\x00\x00\u07d4^eE\x8b\xe9d\xaeD\x9fqw7\x04\x97\x97f\xf8\x89\x87a\x89\x1c\xa7\xccs[o|\x00\x00\u07d4^g\u07c9i\x10\x1a\u06bd\x91\xac\xcdk\xb1\x99\x12t\xaf\x8d\xf2\x89\x1b\x1a\xe4\xd6\xe2\xefP\x00\x00\u07d4^n\x97G\xe1b\xf8\xb4\\en\x0fl\xaez\x84\xba\xc8\x0eN\x89lk\x93[\x8b\xbd@\x00\x00\u07d4^s\x1bU\xce\xd4R\xbb??\xe8q\xdd\xc3\xed~\xe6Q\n\x8f\x89\xa2\xa1]\tQ\x9b\xe0\x00\x00\u07d4^t\xed\x80\xe9eW\x88\xe1\xbb&\x97R1\x96g\xfeuNZ\x89\x03\t'\xf7L\x9d\xe0\x00\x00\u07d4^w.'\xf2\x88\x00\xc5\r\u0697;\xb3>\x10v.n\xea \x89a\t=|,m8\x00\x00\u07d4^{\x8cT\xdcW\xb0@ bq\x9d\xee~\xf5\xe3~\xa3]b\x89\x9b\xf9\x81\x0f\xd0\\\x84\x00\x00\u07d4^\u007fp7\x87uX\x9f\xc6j\x81\xd3\xf6S\xe9T\xf5U`\ub243\xf2\x89\x18\x1d\x84\xc8\x00\x00\xe0\x94^\x80n\x84W0\xf8\a>l\xc9\x01\x8e\xe9\x0f\\\x05\xf9\t\xa3\x8a\x02\x01\xe9m\xac\u03af \x00\x00\u07d4^\x8eM\xf1\x8c\xf0\xafw\tx\xa8\u07cd\xac\x90\x93\x15\x10\xa6y\x89lk\x93[\x8b\xbd@\x00\x00\u07d4^\x90\xc8Xw\x19\x87V\xb06l\x0e\x17\xb2\x8eR\xb4FPZ\x89\x14JJ\x18\xef\xebh\x00\x00\u07d4^\x95\xfe_\xfc\xf9\x98\xf9\xf9\xac\x0e\x9a\x81\u06b8>\xadw\x00=\x89\x1dB\xc2\r2y\u007f\x00\x00\u07d4^\xad)\x03z\x12\x89dx\xb1)j\xb7\x14\xe9\u02d5B\x8c\x81\x89\x03\xe0C\a-@n\x00\x00\u07d4^\xb3q\xc4\a@lB{;}\xe2q\xad<\x1e\x04&\x95y\x89\xa2\xa1]\tQ\x9b\xe0\x00\x00\u07d4^\u037a\xea\xb9\x10o\xfe]{Q\x96\x96`\x9a\x05\xba\ub16d\x89\x01\x15\x8eF\t\x13\xd0\x00\x00\u07d4^\xd0\xd63\x85Y\xefD\xdcza\xed\xeb\x89?\xa5\xd8?\xa1\xb5\x89\v\xed\x1d\x02c\xd9\xf0\x00\x00\xe0\x94^\u04fb\xc0R@\xe0\u04d9\xebm\xdf\xe6\x0fb\xdeM\x95\t\xaf\x8a)\x14\xc0$u\xf9\xd6\xd3\x00\x00\u0594^\xd3\xf1\xeb\xe2\xaegV\xb5\xd8\xdc\x19\xca\xd0,A\x9a\xa5w\x8b\x80\u07d4^\xd5a\x15\xbde\x05\xa8\x82s\xdf\\V\x83\x94p\xd2J-\xb7\x89\x03\x8ee\x91\xeeVf\x80\x00\xe0\x94^\xf8\xc9a\x86\xb3y\x84\xcb\xfe\x04\u0158@n;\n\xc3\x17\x1f\x8a\x01\xfd\x934\x94\xaa_\xe0\x00\x00\u07d4^\xfb\xdf\xe58\x99\x99c<&`Z[\xfc,\x1b\xb5\x95\x93\x93\x89\x03\xc0W\xc9\\\xd9\b\x00\x00\xe0\x94_\x13\x15F1Fm\xcb\x13S\u0210\x93*|\x97\xe0\x87\x8e\x90\x8a\x01EB\xba\x12\xa37\xc0\x00\x00\u07d4_\x16z\xa2B\xbcL\x18\x9a\xde\xcb:\u0127\xc4R\xcf\x19/\u03c9lkLM\xa6\u077e\x00\x00\xe0\x94_\x1c\x8a\x04\xc9\rs[\x8a\x15)\t\xae\xaeco\xb0\xce\x16e\x8a\x01{x'a\x8cZ7\x00\x00\u07d4_#\xba\x1f7\xa9lE\xbcI\x02YS\x8aT\u008b\xa3\xb0\u0549A\rXj \xa4\xc0\x00\x00\u07d4_&\xcf4Y\x9b\xc3n\xa6{\x9ez\x9f\x9bC0\xc9\xd5B\xa3\x8965\u026d\xc5\u07a0\x00\x00\u07d4_)\xc9\xdev]\xde%\x85*\xf0}3\xf2\xceF\x8f\xd2\t\x82\x89lk\x93[\x8b\xbd@\x00\x00\u07d4_/\a\xd2\u0597\xe8\xc5g\xfc\xfd\xfe\x02\x0fI\xf3`\xbe!9\x89lk\x93[\x8b\xbd@\x00\x00\u07d4_2\x1b=\xaa\xa2\x96\xca\xdf)C\x9f\x9d\xab\x06*K\xff\xed\u0589\x04p%\x90>\xa7\xae\x00\x00\u07d4_3:;#\x10vZ\r\x182\xb9\xbeL\n\x03pL\x1c\t\x8965\u026d\xc5\u07a0\x00\x00\u07d4_4K\x01\xc7\x19\x1a2\xd0v*\xc1\x88\xf0\xec-\xd4`\x91\x1d\x8965\u026d\xc5\u07a0\x00\x00\xe0\x94_6>\n\xb7G\xe0-\x1b;f\xab\xb6\x9e\xa5<{\xafR:\x8a\x02w\x01s8\xa3\n\xe0\x00\x00\u07d4_7[\x86`\f@\u0328\xb2gkz\x1a\x1d\x16D\xc5\xf5,\x89\x04F\x18\xd7Lb?\x00\x00\u07d4_>\x1eg9\xb0\xc6\"\x00\xe0\n\x006\x91\xd9\xef\xb28\u061f\x89\xa2\xa1]\tQ\x9b\xe0\x00\x00\u07d4_H?\xfb\x8fh\n\xed\xf2\xa3\x8fx3\xaf\xdc\xdeY\xb6\x1eK\x89lk\x93[\x8b\xbd@\x00\x00\xe0\x94_J\xceL\x1c\xc13\x91\xe0\x1f\x00\xb1\x98\xe1\xf2\v_\x91\xcb\xf5\x8a\x01\x0f\x0f\xa8\xb9\u04c1\x1a\x00\x00\xe0\x94_R\x12\x82\xe9\xb2x\u070c\x03Lr\xafS\xee)\xe5D=x\x8a\x01as-/\x8f:\xe0\x00\x00\u07d4_h\xa2L~\xb4\x11vgs{39?\xb3\xc2\x14\x8aS\xb6\x89\x02\xce\u0791\x8dE<\x00\x00\u07d4_p\x8e\xaf9\xd8#\x94lQ\xb3\xa3\u9df3\xc0\x03\xe2cA\x89b\xa9\x92\xe5:\n\xf0\x00\x00\u07d4_t.H~:\xb8\x1a\xf2\xf9J\xfd\xbe\x1b\x9b\x8f\\\u0301\xbc\x89u\xc4E\xd4\x11c\xe6\x00\x00\u07d4_t\xed\x0e$\xff\x80\u0672\u0124K\xaa\x99uB\x8c\u05b95\x89\xa1\x8b\xce\xc3H\x88\x10\x00\x00\u07d4_v\xf0\xa3\x06&\x9cx0k=e\r\xc3\xe9\xc3p\x84\xdba\x89\x82\x1a\xb0\xd4AI\x80\x00\x00\u07d4_w\xa1\a\xab\x12&\xb3\xf9_\x10\ue0ee\xfcl]\xff>\u0709\x1b\x1a\xe4\xd6\xe2\xefP\x00\x00\u07d4_{;\xba\xc1m\xab\x83\x1aJ\x0f\xc5;\fT\x9d\xc3l1\u0289i*\xe8\x89p\x81\xd0\x00\x00\xe0\x94_\x93\xff\x83't\xdbQ\x14\xc5[\xb4\xbfD\xcc\U000f53d0?\x8a(\xa9\xc9\x1a&4X)\x00\x00\u07d4_\x96\x16\xc4{Jg\xf4\x06\xb9Z\x14\xfeo\xc2h9o\x17!\x89\n\u05ce\xbcZ\xc6 \x00\x00\u07d4_\x98\x109\xfc\xf5\x02%\xe2\xad\xf7bu!\x12\xd1\xcc&\xb6\xe3\x89\x1b\x1aAj!S\xa5\x00\x00\u07d4_\x99\u070eI\xe6\x1dW\xda\xef`j\xcd\xd9\x1bMp\a2j\x89\xa2\xa1]\tQ\x9b\xe0\x00\x00\u07d4_\xa6\x1f\x15-\xe6\x125\x16\xc7Q$)y(_yj\u01d1\x89\v\x0f\x11\x97)c\xb0\x00\x00\u07d4_\xa7\xbf\xe0C\x88a'\xd4\x01\x1d\x83V\xa4~\x94yc\xac\xa8\x89b\xa9\x92\xe5:\n\xf0\x00\x00\xe0\x94_\xa8\xa5Nh\x17lO\xe2\xc0\x1c\xf6q\xc5\x15\xbf\xbd\xd5(\xa8\x8aE\xe1U\xfa\x01\x10\xfa@\x00\x00\u07d4_\xad\x96\x0fk,\x84V\x9c\x9fMG\xbf\x19\x85\xfc\xb2\xc6]\xa6\x8965f3\xeb\xd8\xea\x00\x00\u07d4_\xc6\xc1\x14&\xb4\xa1\xea\xe7\xe5\x1d\xd5\x12\xad\x10\x90\xc6\xf1\xa8[\x89\x93\xfe\\W\xd7\x10h\x00\x00\u07d4_\u0344Th\x96\xdd\b\x1d\xb1\xa3 \xbdM\x8c\x1d\xd1R\x8cL\x89\x01\x15\x8eF\t\x13\xd0\x00\x00\u07d4_\u0368G\xaa\xf8\xd7\xfa\x8b\xca\b\x02\x9c\xa2\x84\x91f\xaa\x15\xa3\x89!\u02b8\x12Y\xa3\xbf\x00\x00\u07d4_\xd1\xc3\xe3\x17x'l\xb4.\xa7@\xf5\xea\xe9\xc6A\xdb\xc7\x01\x89\n\x84Jt$\xd9\xc8\x00\x00\u07d4_\xd3\xd6w~\xc2b\n\xe8:\x05R\x8e\xd4%\a-<\xa8\xfd\x89lk\x93[\x8b\xbd@\x00\x00\u07d4_\xd9s\xaf6j\xa5\x15|Te\x9b\u03f2|\xbf\xa5\xac\x15\u0589\xd8\xd7&\xb7\x17z\x80\x00\x00\u07d4_\xe7w\x03\x80\x8f\x82>l9\x93R\x10\x8b\xdb,R|\xb8|\x89j@v\xcfy\x95\xa0\x00\x00\xe0\x94_\xecI\xc6e\xe6N\xe8\x9d\xd4A\xeet\x05n\x1f\x01\xe9(p\x8a\x01V\x9b\x9es4t\xc0\x00\x00\u07d4_\xf3&\xcd`\xfd\x13k$^)\xe9\bzj\u04e6R\u007f\r\x89e\xea=\xb7UF`\x00\x00\u07d4_\xf9=\xe6\xee\x05L\xadE\x9b-^\xb0\xf6\x87\x03\x89\xdf\xcbt\x89\v\xed\x1d\x02c\xd9\xf0\x00\x00\u07d4`\x06\xe3m\x92\x9b\xf4]\x8f\x16#\x1b\x12j\x01\x1a\xe2\x83\xd9%\x89\t\x8a}\x9b\x83\x14\xc0\x00\x00\u07d4`!\xe8Z\x88\x14\xfc\xe1\xe8*A\xab\xd1\u04f2\xda\xd2\xfa\xef\xe0\x89lk\x93[\x8b\xbd@\x00\x00\u07d4`8t\n\xe2\x8df\xba\x93\xb0\xbe\bH+2\x05\xa0\xf7\xa0{\x89\x11!a\x85\u009fp\x00\x00\u07d4`?/\xabz\xfbn\x01{\x94v`i\xa4\xb4;8\x96I#\x89Y\xd2\xdb$\x14\u0699\x00\x00\u07d4`B'm\xf2\x98?\xe2\xbcGY\xdc\x19C\xe1\x8f\xdb\xc3Ow\x89j\xcb=\xf2~\x1f\x88\x00\x00\u07d4`B\xc6D\xba\xe2\xb9o%\xf9M1\xf6x\xc9\r\xc9f\x90\u06c9lk\x93[\x8b\xbd@\x00\x00\u07d4`L\xdf\x18b\x8d\xbf\xa82\x91\x94\xd4x\xddR\x01\xee\xccK\xe7\x89\x01?0j$\t\xfc\x00\x00\u07d4`N\x94w\xeb\xf4r|t[\u02bb\xed\xcbl\xcf)\x99@\"\x8966\x9e\xd7t}&\x00\x00\u07d4`gm\x1f\xa2\x1f\xca\x05\"\x97\xe2K\xf9c\x89\u0171*p\u05c9\r\x17|Zzh\xd6\x00\x00\u07d4`gn\x92\u044b\x00\x05\t\xc6\x1d\xe5@\xe6\xc5\u0776v\xd5\t\x89A\rXj \xa4\xc0\x00\x00\u07d4`o\x17q!\xf7\x85\\!\xa5\x06#0\xc8v\"d\xa9{1\x89\xd8\xd7&\xb7\x17z\x80\x00\x00\u07d4`\x86B6\x93\r\x04\xd8@+]\xcb\xeb\x80\u007f<\xafa\x1e\xa2\x89\xd8\xd7&\xb7\x17z\x80\x00\x00\u07d4`\xabq\xcd&\xeamnY\xa7\xa0\xf6'\xee\a\x9c\x88^\xbb\xf6\x89\x01s\x17\x90SM\xf2\x00\x00\u07d4`\xaf\x0e\xe1\x18D<\x9b7\xd2\xfe\xadw\xf5\xe5!\u07be\x15s\x89g\x8a\x93 b\xe4\x18\x00\x00\u07d4`\xb3X\xcb=\xbe\xfa7\xf4}\xf2\xd76X@\u068e;\u024c\x89\x01\x15\x8eF\t\x13\xd0\x00\x00\u07d4`\xb8\u05b7;ySO\xb0\x8b\xb8\xcb\xce\xfa\xc7\xf3\x93\xc5{\xfe\x89_h\xe8\x13\x1e\u03c0\x00\x00\u07d4`\xbeo\x95?*M%\xb6%o\xfd$#\xac\x148%.N\x89\b!\xab\rD\x14\x98\x00\x00\u0794`\xc3qO\xdd\xdbcFY\u48b1\xeaB\xc4r\x8c\u01f8\xba\x88\xb9\x8b\xc8)\xa6\xf9\x00\x00\u07d4`\xcc=D^\xbd\xf7j}z\xe5q\u0197\x1d\xffh\u0305\x85\x8965\u026d\xc5\u07a0\x00\x00\xe0\x94`\xd5fq@\xd1&\x14\xb2\x1c\x8e^\x8a3\b.2\xdf\xcf#\x8a\x04<3\xc1\x93ud\x80\x00\x00\u07d4`\xde\"\xa1Pt2\xa4{\x01\xcch\xc5*\v\xf8\xa2\xe0\u0418\x89\x01\t\x10\xd4\xcd\xc9\xf6\x00\x00\u07d4`\xe0\xbd\u0422Y\xbb\x9c\xb0\x9d?7\xe5\u034b\x9d\xac\uafca\x89JD\x91\xbdm\xcd(\x00\x00\u07d4`\xe3\xccC\xbc\xdb\x02j\xadu\x9cpf\xf5U\xbb\xf2\xacf\xf5\x89lk\x93[\x8b\xbd@\x00\x00\u07d4a\x04+\x80\xfd`\x95\u0478{\xe2\xf0\x0f\x10\x9f\xab\xaf\xd1W\xa6\x89\x05k\xc7^-c\x10\x00\x00\u07d4a\a\xd7\x1d\xd6\xd0\xee\xfb\x11\xd4\xc9\x16@L\xb9\x8cu>\x11}\x89lk\x93[\x8b\xbd@\x00\x00\u07d4a\x0f\xd6\xeeN\xeb\xab\x10\xa8\xc5]\vK\xd2\xe7\xd6\xef\x81qV\x89\x01\x15\x95a\x06]]\x00\x00\u07d4a\x14\xb0\xea\xe5Wi\x03\xf8\v\xfb\x98\x84-$\xed\x92#\u007f\x1e\x89\x05k\xc7^-c\x10\x00\x00\u07d4a!\xaf9\x8a[-\xa6\x9fe\xc68\x1a\xec\x88\u039c\xc6D\x1f\x89\"\xb1\xc8\xc1\"z\x00\x00\x00\u07d4a&g\xf1r\x13[\x95\v,\xd1\xde\x10\xaf\xde\xcehW\xb8s\x8965\u026d\xc5\u07a0\x00\x00\u07d4a,\xed\x8d\xc0\u071e\x89\x9e\xe4oyb33\x15\xf3\xf5^D\x89\x12^5\xf9\xcd=\x9b\x00\x00\u07d4a4\xd9B\xf07\xf2\xcc=BJ#\f`=g\xab\xd3\xed\xf7\x89lk\x93[\x8b\xbd@\x00\x00\u07d4a:\xc5;\xe5e\xd4e6\xb8 q[\x9b\x8d:\xe6\x8aK\x95\x89\xcb\xd4{n\xaa\x8c\xc0\x00\x00\u07d4a?\xabD\xb1k\xbeUMD\xaf\xd1x\xab\x1d\x02\xf3z\ua949lk\x93[\x8b\xbd@\x00\x00\u07d4aN\x8b\xef=\xd2\u015bY\xa4\x14Vt@\x10\x185\x18\x84\xea\x89\x01\x15\x8eF\t\x13\xd0\x00\x00\u07d4aQ\x84d\xfd\u0637<\x1b\xb6\xacm\xb6\x00eI8\xdb\xf1z\x89\n\u05ce\xbcZ\xc6 \x00\x00\u07d4aT}7nSi\xbc\xf9x\xfc\x16,<V\xaeE5G\xe8\x89\n\u05ce\xbcZ\xc6 \x00\x00\u07d4aX\xe1\a\xc5\xebT\xcbv\x04\xe0\u034d\xc1\xe0u\x00\xd9\x1c<\x89\x02\xb5\xe3\xaf\x16\xb1\x88\x00\x00\xe0\x94aZo6w\u007f@\xd6a~\xb5\x81\x98\x96\x18i\x83\xfd71\x8a\x01@a\xb9\xd7z^\x98\x00\x00\u07d4a_\x826\\Q\x01\xf0q\xe7\xd2\xcbj\xf1Oz\xad,\x16\u0189\x01\x15\x8eF\t\x13\xd0\x00\x00\u07d4ap\xdd\x06\x87\xbdU\u0288\xb8z\xde\xf5\x1c\xfd\xc5\\M\xd4X\x89l\xb3/\\4\xfeD\x00\x00\u07d4as9G\xfa\xb8 \xdb\xd3Q\xef\xd6xU\xea\x0e\x88\x13s\xa0\x89\x01\x15\x8eF\t\x13\xd0\x00\x00\u07d4ay\x97\x99\a\xfe\u007f\x03~L8\x02\x9d`\xbc\xba\xb82\xb3\u0589WG=\x05\u06ba\xe8\x00\x00\xe0\x94a\u007f \x89O\xa7\x0e\x94\xa8jI\xcdt\xe028\xf6M<\u064a\x01\x0f\r\xba\xe6\x10\tR\x80\x00\u07d4a\u007f\xf2\u0300>1\xc9\b\"3\xb8%\xd0%\xbe?{\x10V\x89j\xcb=\xf2~\x1f\x88\x00\x00\u07d4a\x91\xdd\u0276J\x8e\b\x90\xb427\t\u05e0|H\xb9*d\x89*\x03I\x19\u07ff\xbc\x00\x00\u07d4a\x96\xc3\xd3\xc0\x90\x8d%Cf\xb7\xbc\xa5WE\"-\x9dM\xb1\x89\xd8\xd7&\xb7\x17z\x80\x00\x00\u07d4a\x9f\x17\x14E\xd4+\x02\xe2\xe0p\x04\xad\x8a\xfeiO\xa5=j\x89\x01\x15\x8eF\t\x13\xd0\x00\x00\u07d4a\xad\xf5\x92\x9a^)\x81hN\xa2C\xba\xa0\x1f}\x1f^\x14\x8a\x89\x05\xfa\xbfl\x98O#\x00\x00\u07d4a\xb1\xb8\xc0\x12\xcdLx\xf6\x98\xe4p\xf9\x02V\xe6\xa3\x0fH\u0749\n\u05ce\xbcZ\xc6 \x00\x00\u07d4a\xb3\xdf.\x9e\x9f\xd9h\x13\x1f\x1e\x88\xf0\xa0\xeb[\xd7eFM\x89\xd8\xd7&\xb7\x17z\x80\x00\x00\u07d4a\xb9\x02\u0166s\x88X&\x82\r\x1f\xe1EI\xe4\x86_\xbd\u0089\x12$\xef\xed*\u1440\x00\u07d4a\xb9\x05\xdef?\xc1s\x86R;:(\xe2\xf7\xd07\xa6U\u0349\x1b\x1a\xe4\xd6\xe2\xefP\x00\x00\u07d4a\xba\x87\xc7~\x9bYm\xe7\xba\x0e2o\xdd\xfe\xec!c\xeff\x89\n\u05ce\xbcZ\xc6 \x00\x00\u07d4a\xbf\x84\u056b\x02oX\xc8s\xf8o\xf0\xdf\u0282\xb5W3\xae\x89lk\x93[\x8b\xbd@\x00\x00\u07d4a\xc4\xee|\x86LMk^7\xea\x131\xc2\x03s\x9e\x82k/\x89\x01\xa15;8*\x91\x80\x00\u07d4a\xc80\xf1eG\x18\xf0u\u032b\xa3\x16\xfa\xac\xb8[}\x12\v\x89\x15\xaf\x1dx\xb5\x8c@\x00\x00\u07d4a\xc8\xf1\xfaC\xbf\x84i\x99\xec\xf4{+2M\xfbkc\xfe:\x89+^:\xf1k\x18\x80\x00\x00\u07d4a\xc9\xdc\u8c98\x1c\xb4\x0e\x98\xb0@+\xc3\xeb(4\x8f\x03\xac\x89\n\xac\xac\u0679\xe2+\x00\x00\u07d4a\u03a7\x1f\xa4d\xd6*\a\x06?\x92\v\f\xc9\x17S\x973\u0609Z\x87\xe7\xd7\xf5\xf6X\x00\x00\u07d4a\xd1\x01\xa03\xee\x0e.\xbb1\x00\xed\xe7f\xdf\x1a\xd0$IT\x89\x1b\x1a\xe4\xd6\xe2\xefP\x00\x00\u07d4a\xedU\x96\u0197 \u007f=U\xb2\xa5\x1a\xa7\xd5\x0f\a\xfa\t\xe8\x89lk\x93[\x8b\xbd@\x00\x00\u07d4a\xff\x8eg\xb3M\x9e\xe6\xf7\x8e\xb3o\xfe\xa1\xb9\xf7\xc1W\x87\xaf\x89X\xe7\x92n\xe8X\xa0\x00\x00\u07d4b\x05\xc2\xd5dtp\x84\x8a8@\xf3\x88~\x9b\x01]4u\\\x89a\x94\x04\x9f0\xf7 \x00\x00\u07d4b(\xad\xe9^\x8b\xb1}\x1a\xe2;\xfb\x05\x18AMI~\x0e\xb8\x89\x15\xaf\x1dx\xb5\x8c@\x00\x00\xe0\x94b)\xdc\xc2\x03\xb1\xed\xcc\xfd\xf0n\x87\x91\fE*\x1fMzr\x8a\x06\xe1\xd4\x1a\x8f\x9e\xc3P\x00\x00\u0794b+\xe4\xb4T\x95\xfc\xd91C\xef\xc4\x12\u0599\xd6\xcd\xc2=\u0148\xf0\x15\xf2W6B\x00\x00\u07d4b3\x1d\xf2\xa3\xcb\xee5 \xe9\x11\u07a9\xf7>\x90_\x89%\x05\x89lk\x93[\x8b\xbd@\x00\x00\u07d4bVD\xc9Z\x87>\xf8\xc0l\u06de\x9fm\x8dv\x80\x04=b\x89a\x94\x04\x9f0\xf7 \x00\x00\u07d4be\xb2\xe7s\x0f6\xb7v\xb5-\f\x9d\x02\xad\xa5]\x8e<\xb6\x8965\u026d\xc5\u07a0\x00\x00\u07d4bh\n\x15\xf8\u0338\xbd\xc0/s`\xc2Z\xd8\u03f5{\x8c\u034965\u026d\xc5\u07a0\x00\x00\u07d4b\x94\xea\xe6\xe4 \xa3\xd5`\n9\xc4\x14\x1f\x83\x8f\xf8\xe7\xccH\x89\xa00\xdc\xeb\xbd/L\x00\x00\u07d4b\x97\x1b\xf2cL\xee\v\xe3\u0249\x0fQ\xa5`\x99\u06f9Q\x9b\x89#\x8f\xd4,\\\xf0@\x00\x00\u07d4b\x9b\xe7\xab\x12jS\x98\xed\xd6\u069f\x18D~x\u0192\xa4\xfd\x89lk\x93[\x8b\xbd@\x00\x00\u07d4b\xb4\xa9\"nah<r\xc1\x83%F\x90\xda\xf5\x11\xb4\x11z\x89\x0e\x189\x8ev\x01\x90\x00\x00\u07d4b\xb9\b\x1ew\x104^8\xe0.\x16D\x9a\xce\x1b\x85\xbc\xfcN\x891T\xc9r\x9d\x05x\x00\x00\u07d4b\xc3|R\xb9\u007fK\x04\v\x1a\xa3\x91\xd6\xde\xc1R\x89<G\a\x8965\u026d\xc5\u07a0\x00\x00\u07d4b\u0272q\xff\u0577p\xa5\xee\xe4\xed\xc9x{\\\xdcp\x97\x14\x89lk\x93[\x8b\xbd@\x00\x00\u07d4b\xd5\xccq\x17\xe1\x85\x00\xac/\x9e<&\xc8k\n\x94\xb0\xde\x15\x89\x05\xb1*\ufbe8\x04\x00\x00\u07d4b\xdcrr\x90$7_\xc3|\xbb\x9c|#\x93\xd1\x0233\x0f\x89lk\x93[\x8b\xbd@\x00\x00\u07d4b\xe6\xb2\xf5\xeb\x94\xfazC\x83\x1f\xc8~%J?\u3fcf\x89\x89\r\x8drkqw\xa8\x00\x00\u07d4b\xf2\xe5\xcc\xec\xd5,\u0139^\x05\x97\xdf'\xcc\a\x97\x15`\x8c\x89\a\xc0\x86\x0eZ\x80\xdc\x00\x00\xe0\x94b\xfb\x8b\xd1\xf0\xe6k\x90S>\a\x1el\xbea\x11\xfe\xf0\xbcc\x8a\x03\xba\x19\x10\xbf4\x1b\x00\x00\x00\xe0\x94c\n\x91:\x901\xc9I*\xbdLA\u06f1PT\xcf\xecD\x16\x8a\x014X\xdbg\xaf5\xe0\x00\x00\xe0\x94c\fRs\x12mQ|\xe6q\x01\x81\x1c\xab\x16\xb8SL\xf9\xa8\x8a\x01\xfe\xcc\xc6%s\xbb\u04c0\x00\u07d4c\x100\xa5\xb2{\a(\x8aEio\x18\x9e\x11\x14\xf1*\x81\xc0\x89\x1b\x1azB\v\xa0\r\x00\x00\u07d4c\x10\xb0 \xfd\x98\x04IW\x99P\x92\t\x0f\x17\xf0NR\xcd\xfd\x89U\xa6\xe7\x9c\xcd\x1d0\x00\x00\u07d4c+\x91I\xd7\x01x\xa7364'^\x82\u0555?'\x96{\x89%\xf2s\x93=\xb5p\x00\x00\u07d4c,\xec\xb1\f\xfc\xf3\x8e\u0246\xb4;\x87p\xad\xec\xe9 \x02!\x89\x01\x15\x8eF\t\x13\xd0\x00\x00\u07d4c1\x02\x8c\xbbZ!H[\xc5\x1bVQB\x99;\xdb%\x82\xa9\x89\x1c\xfd\xd7F\x82\x16\xe8\x00\x00\u07d4c3O\xcf\x17E\x84\x0eK\tJ;\xb4\v\xb7o\x96\x04\xc0L\x89\u05e5\xd7\x03\xa7\x17\xe8\x00\x00\u07d4c4\nWqk\xfac\xebl\xd13r\x12\x02W[\xf7\x96\xf0\x89\va\xe0\xa2\f\x12q\x80\x00\u07d4cN\xfc$7\x11\a\xb4\xcb\xf0?y\xa9=\xfd\x93\xe41\xd5\xfd\x89B5\x82\xe0\x8e\xdc\\\x80\x00\xe0\x94c\\\x00\xfd\xf05\xbc\xa1_\xa3a\r\xf38N\x0f\xb7\x90h\xb1\x8a\x01\xe7\xe4\x17\x1b\xf4\u04e0\x00\x00\u07d4ca.xb\xc2{X|\xfbm\xaf\x99\x12\xcb\x05\x1f\x03\n\x9f\x89\x02[\x19\u053f\xe8\xed\x00\x00\u07d4cfgU\xbdA\xb5\x98i\x97x<\x13\x040\b$+<\xb5\x89\x1b\x1a\xe4\xd6\xe2\xefP\x00\x00\u07d4c{\xe7\x1b:\xa8\x15\xffE=VB\xf70tE\vd\xc8*\x89lk\x93[\x8b\xbd@\x00\x00\xe0\x94c}g\xd8\u007fXo\nZG\x9e \xee\x13\xea1\n\x10\xb6G\x8a\n:Y&\xaf\xa1\xe70\x00\x00\u07d4c\u007fXi\xd6\xe4i_\x0e\xb9\xe2s\x11\u0107\x8a\xff33\x80\x89j\xc0Nh\xaa\xec\x86\x00\x00\u07d4c\x97|\xad}\r\xcd\xc5+\x9a\xc9\xf2\xff\xa16\xe8d(\x82\xb8\x89\x04\x10\u0546\xa2\nL\x00\x00\u07d4c\xa6\x1d\xc3\n\x8e;0\xa7c\xc4!<\x80\x1c\xbf\x98s\x81x\x8965\u026d\xc5\u07a0\x00\x00\u07d4c\xacT\\\x99\x12C\xfa\x18\xae\xc4\x1dOoY\x8eUP\x15\u0709 \x86\xac5\x10R`\x00\x00\u07d4c\xb9uMu\xd1-8@9\xeci\x06<\v\xe2\x10\xd5\xe0\u3252\v\x86\f\xc8\xec\xfd\x80\x00\u07d4c\xbbfO\x91\x17\x03v(YM\xa7\xe3\xc5\b\x9f\xd6\x18\xb5\xb5\x89\x01\x15\x8eF\t\x13\xd0\x00\x00\u07d4c\u00a3\xd25\xe5\xee\xab\xd0\u0526\xaf\u06c9\xd9F'9d\x95\x89CN\xf0[\x9d\x84\x82\x00\x00\u07d4c\xc8\xdf\xde\v\x8e\x01\xda\xdc.t\x8c\x82L\xc06\x9d\U00010cc9\xd2U\xd1\x12\xe1\x03\xa0\x00\x00\u07d4c\xd5Z\u065b\x917\xfd\x1b \xcc+O\x03\xd4,\xba\xdd\xf34\x89\x15\xaf\x1dx\xb5\x8c@\x00\x00\u07d4c\xd8\x00H\x87u\x96\xe0\u0084\x89\xe6P\xcdJ\xc1\x80\tjI\x89\x0f-\xc7\xd4\u007f\x15`\x00\x00\xe0\x94c\xe4\x14`>\x80\xd4\xe5\xa0\xf5\xc1\x87t FB%\x82\b\xe4\x8a\x01\x0f\f\xf0d\xddY \x00\x00\xe0\x94c\xe8\x8e.S\x9f\xfbE\x03\x86\xb4\xe4g\x89\xb2#\xf5GlE\x8a\x01U\x17\nw\x8e%\xd0\x00\x00\u07d4c\xef/\xbc=\xaf^\xda\xf4\xa2\x95b\x9c\xcf1\xbc\xdf@8\xe5\x89O%\x91\xf8\x96\xa6P\x00\x00\u07d4c\xf0\xe5\xa7R\xf7\x9fg\x12N\xedc:\xd3\xfd'\x05\xa3\x97\u0509\u0556{\xe4\xfc?\x10\x00\x00\xe0\x94c\xf5\xb5=y\xbf.A\x14\x89Re0\"8E\xfa\xc6\xf6\x01\x8a\x06ZM\xa2]0\x16\xc0\x00\x00\u07d4c\xfc\x93\x00\x13\x05\xad\xfb\u0278])\xd9)\x1a\x05\xf8\xf1A\v\x8965\u026d\xc5\u07a0\x00\x00\u0794c\xfek\xccK\x8a\x98P\xab\xbeu\x8070\xc92%\x1f\x14[\x88\xfc\x93c\x92\x80\x1c\x00\x00\u07d4d\x03\xd0bT\x96\x90\xc8\xe8\xb6>\xaeA\xd6\xc1\tGn%\x88\x89lk\x93[\x8b\xbd@\x00\x00\u07d4d\x04+\xa6\x8b\x12\xd4\xc1Qe\x1c\xa2\x81;sR\xbdV\xf0\x8e\x89 \x86\xac5\x10R`\x00\x00\u0794d\x05\xdd\x13\xe9:\xbc\xff7~p\x0e<\x1a\x00\x86\xec\xa2})\x88\xfc\x93c\x92\x80\x1c\x00\x00\xe0\x94d\n\xbam\xe9\x84\xd9E\x177x\x03p^\xae\xa7\t_J\x11\x8a\x02\x1e\x19\xe0\u027a\xb2@\x00\x00\u07d4d\v\xf8t\x15\xe0\xcf@s\x01\xe5Y\x9ah6m\xa0\x9b\xba\u0209\x1a\xbc\x9fA`\x98\x15\x80\x00\u07d4d \xf8\xbc\xc8\x16JaR\xa9\x9dk\x99i0\x05\xcc\xf7\xe0S\x8965f3\xeb\xd8\xea\x00\x00\u07d4d$\x1axD)\x0e\n\xb8U\xf1\u052au\xb5SE\x03\"$\x89V\xbcu\xe2\xd61\x00\x00\x00\u07d4d&J\xed\xd5-\xca\xe9\x18\xa0\x12\xfb\xcd\f\x03\x0e\xe6\xf7\x18!\x8965\u026d\xc5\u07a0\x00\x00\u07d4d7\x0e\x87 &E\x12Z5\xb2\a\xaf\x121\xfb`r\xf9\xa7\x89\n\u05ce\xbcZ\xc6 \x00\x00\u07d4d=\x9a\xee\u0531\x80\x94~\u04b9 |\xceL=\xdcU\xe1\xf7\x89\n\u05ce\xbcZ\xc6 \x00\x00\u07d4dC\xb8\xaec\x9d\xe9\x1c\xf7<Z\xe7c\xee\xee\xd3\u077b\x92S\x89lk\x93[\x8b\xbd@\x00\x00\u07d4dE\u007f\xa3;\b2PlO}\x11\x80\xdc\xe4\x8fF\xf3\xe0\xff\x89lk\x93[\x8b\xbd@\x00\x00\u07d4dFJh\x05\xb4bA*\x90\x1d-\xb8\x17K\x06\xc2-\ue989\x19\xc8F\xa0)\xc7\xc8\x00\x00\u07d4dK\xa6\xc6\x10\x82\xe9\x89\x10\x9f\\\x11\u0534\x0e\x99\x16`\xd4\x03\x89\xd8\xd7&\xb7\x17z\x80\x00\x00\u07d4db\x8co\xb8\xect:\xdb\xd8|\xe5\xe0\x18\xd51\xd9!\x047\x89\x01s\x17\x90SM\xf2\x00\x00\u07d4dc\xf7\x15\u0554\xa1\xa4\xac\u4edc;(\x8at\xde\xcf)M\x89j\xcb=\xf2~\x1f\x88\x00\x00\u07d4df(\xa5<,A\x93\u06885\x9c\xe7\x18\xda\u0752\xb7\xa4\x8d\x89\n\xd8\x00l/^\xf0\x00\x00\u07d4dg-\xa3\xab\x05(!\xa0$=\x1c\xe4\xb6\xe0\xa3e\x17\xb8\xeb\x89\n\u05ce\xbcZ\xc6 \x00\x00\u07d4dj\xfb\xa7\x1d\x84\x9e\x80\xc0\xedY\xca\xc5\x19\xb2x\xe7\xf7\xab\xe4\x8965\u026d\xc5\u07a0\x00\x00\u07d4dn\x04=\x05\x97\xa6d\x94\x8f\xbb\r\xc1Tu\xa3\xa4\xf3\xa6\xed\x89\x01\x15\x8eF\t\x13\xd0\x00\x00\u07d4dp\xa4\xf9.\u01b0\xfc\xcd\x01#O\xa5\x90#\xe9\xff\x1f:\xac\x89\xa2\xa1]\tQ\x9b\xe0\x00\x00\u07d4d{\x85\x04M\xf2\xcf\vN\u0508.\x88\x81\x9f\xe2*\xe5\xf7\x93\x8966;]\x9awp\x00\x00\u07d4d\x85G\x0ea\xdb\x11\n\xeb\u06ef\xd56v\x9e<Y\x9c\xc9\b\x89 \x86\xac5\x10R`\x00\x00\xe0\x94d\x8f[\u04a2\xae\x89\x02\xdb7\x84}\x1c\xb0\u06d3\x90\xb0bH\x8a\x01\xa55\xec\xf0v\n\x04\x80\x00\xe0\x94d\x9a+\x98y\u034f\xb76\xe6p;\fwG\x84\x97\x96\xf1\x0f\x8a\x01\x8e\xe2-\xa0\x1a\xd3O\x00\x00\u07d4d\x9a\x85\xb96S\a_\xa6V,@\x9aV]\b{\xa3\u1e89lk\x93[\x8b\xbd@\x00\x00\u07d4d\xad\xcc\xee\xc5=\xd9\xd9\xdd\x15\xc8\xcc\x1a\x9esm\xe4$\x1d,\x89\x03\t'\xf7L\x9d\xe0\x00\x00\u07d4d\xcf\t5\xbf\x19\xd2\u03bb\xec\xd8x\r'\xd2\xe2\xb2\xc3Af\x89j\xcb=\xf2~\x1f\x88\x00\x00\u07d4d\xd8\f;\x8b\xa6\x82\x82)\vu\xe6]\x89x\xa1Z\x87x,\x89j\xcb=\xf2~\x1f\x88\x00\x00\xe0\x94d\u06e2\xd6a[\x8b\xd7W\x186\xdcu\xbcy\xd3\x14\xf5\xec\xee\x8a\x02\x1e\x19\xe0\u027a\xb2@\x00\x00\u07d4d\xe0!z[8\xaa@X6%\x96\u007f\xa9\x886\x908\x8bo\x89\n\u05ce\xbcZ\xc6 \x00\x00\u07d4d\xe0*\xbb\x01l\xc2:)4\xf6\xbc\u0776\x81\x90P!\xd5c\x8965\u026d\xc5\u07a0\x00\x00\u07d4d\xe0>\xf0p\xa5G\x03\xb7\x18NH'l\\\x00w\xefK4\x89\x11X\xe4`\x91=\x00\x00\x00\xe0\x94d\xe2\xde! \v\x18\x99\u00e0\xc0e;P@\x13m\r\xc8B\x8a\x04<3\xc1\x93ud\x80\x00\x00\u07d4d\xec\x8a[t?4y\xe7\a\xda\xe9\xee \u076aO@\xf1\u0649\n\u05ce\xbcZ\xc6 \x00\x00\u07d4e\x03\x86\v\x19\x10\b\xc1U\x83\xbf\u0201X\t\x93\x01v((\x8965\u026d\xc5\u07a0\x00\x00\u07d4e\x051\x911\x9e\x06z%\xe66\x1dG\xf3\u007fc\x18\xf84\x19\x89\x15[\xd90\u007f\x9f\xe8\x00\x00\u07d4e\t;#\x9b\xbf\xba#\xc7w\\\xa7\xdaZ\x86H\xa9\xf5L\xf7\x89\x15\xaf\x1dx\xb5\x8c@\x00\x00\u07d4e\t\xee\xb14~\x84/\xfbA>7\x15^,\xbcs\x82s\xfd\x89lk\x93[\x8b\xbd@\x00\x00\xe0\x94e\vBUU\xe4\xe4\xc5\x17\x18\x14h6\xa2\xc1\xeew\xa5\xb4!\x8a\x04<3\xc1\x93ud\x80\x00\x00\u07d4e\f\xf6}\xb0`\xcc\xe1uh\xd5\xf2\xa4#h|Idv\t\x89\x05k\xc7^-c\x10\x00\x00\u07d4e\x10\xdfB\xa5\x99\xbc\xb0\xa5\x19\u0329a\xb4\x88u\x9aogw\x89lk\x93[\x8b\xbd@\x00\x00\u07d4e6u\xb8B\xd7\u0634a\xf7\"\xb4\x11|\xb8\x1d\xac\x8ec\x9d\x89\x01\xae6\x1f\xc1E\x1c\x00\x00\u07d4eK~\x80\x87\x99\xa8=r\x87\xc6w\x06\xf2\xab\xf4\x9aId\x04\x89j\xcb=\xf2~\x1f\x88\x00\x00\xe0\x94eORHG\xb3\xa6\xac\xc0\xd3\xd5\xf1\xf3b\xb6\x03\xed\xf6_\x96\x8a\x01\xb1\xaeMn.\xf5\x00\x00\x00\u07d4eY4\u068etN\xaa=\xe3M\xbb\xc0\x89LN\xda\va\xf2\x89\n\u05ce\xbcZ\xc6 \x00\x00\u07d4e]\\\xd7H\x96)\xe2A<!\x05\xb5\xa1r\xd93\xc2z\xf8\x89\xdb\x03\x18l\xd8@\xa6\x00\x00\u07d4e`\x18XA0\u06c3\xab\x05\x91\xa8\x12\x8d\x93\x81fj\x8d\x0e\x89\x03w\x9f\x91 \x19\xfc\x00\x00\u07d4e`\x94\x13(\xffX|\xbcV\u00ccx#\x8a{\xb5\xf4B\xf6\x89(a\x90kY\xc4z\x00\x00\u07d4eey\xda\xed\u0493p\u06777\xee?\\\xd9\xd8K\u00b3B\x89M\x85<\x8f\x89\b\x98\x00\x00\u07d4etswOc\xac=by\xfd\aC\xd5y\fO\x16\x15\x03\x89\n\u05ce\xbcZ\xc6 \x00\x00\u07d4e\x80\xb1\xbc\x949\x0f\x04\xb3\x97\xbds\xe9]\x96\xef\x11\xea\xf3\xa8\x89\x01\x15\x8eF\t\x13\xd0\x00\x00\u07d4e\x84\x9b\xe1\xaf \x10\x0e\xb8\xa3\xbaZ[\xe4\u04ee\x8d\xb5\xa7\x0e\x89\x15\xaf\x1dx\xb5\x8c@\x00\x00\u07d4e\x9c\nr\xc7g\xa3\xa6\\\xed\x0e\x1c\xa8\x85\xa4\xc5\x1f\u0677y\x89lk\x93[\x8b\xbd@\x00\x00\u07d4e\xa5!A\xf5k\uf619\x17$\xc6\xe7\x053\x81\u068bY%\x89\x03B\x9c3]W\xfe\x00\x00\u07d4e\xa9\xda\xd4.\x162\xba>NIb?\xabb\xa1~M6\x11\x89\x05\fL\xb2\xa1\f`\x00\x00\u07d4e\xaf\x8d\x8b[\x1d\x1e\xed\xfaw\xbc\xbc\x96\xc1\xb13\xf83\x06\u07c9\x05P\x05\xf0\xc6\x14H\x00\x00\u07d4e\xaf\x90\x87\xe0QgqT\x97\u0265\xa7I\x18\x94\x89\x00M\xef\x89-C\xf3\xeb\xfa\xfb,\x00\x00\u0794e\xb4/\xae\xcc\x1e\u07f1B\x83\u0297\x9a\xf5E\xf6;0\xe6\f\x88\xfc\x93c\x92\x80\x1c\x00\x00\u0794e\xd3>\xb3\x9c\xdadS\xb1\x9ea\xc1\xfeM\xb91p\xef\x9d4\x88\xb9\x8b\xc8)\xa6\xf9\x00\x00\u07d4e\xd8\xddN%\x1c\xbc\x02\x1f\x05\xb0\x10\xf2\xd5\xdcR\f8r\xe0\x89-CW\x9a6\xa9\x0e\x00\x00\u07d4e\xea&\xea\xbb\xe2\xf6L\xcc\xcf\xe0h)\xc2]F7R\x02%\x89%\xf2s\x93=\xb5p\x00\x00\u07d4e\xeag\xad?\xb5j\xd5\xfb\x948}\u04ce\xb3\x83\x00\x1d|h\x89\x05k\xc7^-c\x10\x00\x00\xe0\x94e\xeb\xae\xd2~\u06dd\xcc\x19W\xae\xe5\xf4R\xac!\x05\xa6\\\x0e\x8a\t7\u07ed\xae%\u26c0\x00\u07d4e\xee \xb0m\x9a\u0549\xa7\xe7\xce\x04\xb9\xf5\xf7\x95\xf4\x02\xae\u0389lk\x93[\x8b\xbd@\x00\x00\u07d4e\xf544m/\xfbx\u007f\xa9\xcf\x18]t[\xa4)\x86\xbdn\x89\x1b\x1a\xe4\xd6\xe2\xefP\x00\x00\xe0\x94e\xf5\x87\x0f&\xbc\xe0\x89g}\xfc#\xb5\x00\x1e\xe4\x92H4(\x8a\x01\x12\xb1\xf1U\xaa2\xa3\x00\x00\u07d4e\xfd\x02\xd7\x04\xa1*M\xac\xe9G\x1b\x06E\xf9b\xa8\x96q\u0209\x01\x8d\x1c\xe6\xe4'\u0340\x00\u07d4e\xff\x87O\xaf\xceM\xa3\x18\xd6\xc9=W\xe2\u00ca\rs\xe8 \x8968\x02\x1c\xec\u06b0\x00\x00\xe0\x94f\x05W\xbbC\xf4\xbe:\x1b\x8b\x85\xe7\xdf{<[\xcdT\x80W\x8a\x01EB\xba\x12\xa37\xc0\x00\x00\u07d4f\b,u\xa8\xde1\xa59\x13\xbb\xd4M\xe3\xa07O\u007f\xaaA\x89O%\x91\xf8\x96\xa6P\x00\x00\u07d4f\x11\xceY\xa9\x8b\a*\xe9Y\xdcI\xadQ\x1d\xaa\xaa\xa1\x9dk\x89\n\u05ce\xbcZ\xc6 \x00\x00\u07d4f \x1b\xd2'\xaem\u01bd\xfe\xd5\xfb\u0781\x1f\xec\xfe^\x9d\u0649 >\x9e\x84\x92x\x8c\x00\x00\u07d4f#4\x81G$\x93[y1\xdd\xcaa\x00\xe0\rFw'\u0349\"\x88&\x9d\a\x83\xd4\x00\x00\u07d4f'O\xea\x82\xcd0\xb6\u009b#5\x0eOO=1\nX\x99\x89p7\x05P\xab\x82\x98\x00\x00\u07d4f,\xfa\x03\x8f\xab7\xa0\x17E\xa3d\u1e41'\xc5\x03tm\x89\u0556{\xe4\xfc?\x10\x00\x00\u07d4f5\xb4oq\x1d-\xa6\xf0\xe1cp\u034e\xe4>\xfb,-R\x89lk\x93[\x8b\xbd@\x00\x00\u07d4f6\x04\xb0P0F\xe6$\xcd&\xa8\xb6\xfbGB\xdc\xe0*o\x89\x03\x8b\x9by~\xf6\x8c\x00\x00\u07d4f6\u05ecczH\xf6\x1d8\xb1L\xfdHe\xd3m\x14(\x05\x89\x1b\x1a\xe4\xd6\xe2\xefP\x00\x00\u07d4f@\xcc\xf0SU\\\x13\n\xe2\xb6Vd~\xa6\xe3\x167\xb9\xab\x89j\xcb=\xf2~\x1f\x88\x00\x00\u07d4fBK\xd8x[\x8c\xb4a\x10*\x90\x02\x83\xc3]\xfa\a\xefj\x89\x02.-\xb2ff\xfc\x80\x00\u07d4fL\xd6}\xcc\u026c\x82(\xb4\\U\u06cdvU\ve\x9c\u0709\x15[\xd90\u007f\x9f\xe8\x00\x00\u07d4fNC\x11\x98p\xaf\x10zD\x8d\xb1'\x8b\x04H8\xff\u036f\x89\x15\xaf\x1dx\xb5\x8c@\x00\x00\u07d4fQso\xb5\x9b\x91\xfe\xe9\xc9:\xa0\xbdn\xa2\xf7\xb2Pa\x80\x89\x1b\x1a\xe4\xd6\xe2\xefP\x00\x00\u07d4f[\x00\x0f\vw'P\xcc<!z^\xf4)\xa9+\xf1\u033b\x89\xd8\xd7&\xb7\x17z\x80\x00\x00\u07d4ff \x06\x01\\\x1f\x8e<\xcf\xca\xeb\xc8\xeeh\a\xee\x19c\x03\x89\x1b\x1b:\x1a\xc2a\xec\x00\x00\u07d4fgF\xfb\x93\u0453\\Z<hNrP\x10\xc4\xfa\u0431\u0609\x01\x15\x8eF\t\x13\xd0\x00\x00\u07d4fkO7\xd5]c\xb7\xd0V\xb6\x15\xbbt\xc9k;\x01\x99\x1a\x89\xd8\xd7&\xb7\x17z\x80\x00\x00\u07d4fq\x9c\x06\x82\xb2\xac\u007f\x9e'\xab\xeb\xec~\u07cd\xec\xf0\xae\r\x89\x01\x15\x8eF\t\x13\xd0\x00\x00\u07d4fq\xb1\x82\xc9\xf7A\xa0\xcd<5ls\xc21&\xd4\xf9\xe6\xf4\x89\n\u05ce\xbcZ\xc6 \x00\x00\u07d4fy\xae\xec\xd8zW\xa7?3V\x81\x1d,\xf4\x9d\fM\x96\u0709 \x86\xac5\x10R`\x00\x00\u07d4f{a\xc0;\xb97\xa9\xf5\xd0\xfcZ\t\xf1\xea3c\xc7p5\x89\xe6d\x99\"\x88\xf2(\x00\x00\u07d4f\x85\xfd.%Dp,6\v\x8b\xb9\xeex\xf10\xda\xd1m\xa5\x89lk\x93[\x8b\xbd@\x00\x00\xe0\x94f\x8bk\xa8\xab\b\xea\xce9\xc5\x02\xefg+\xd5\u0336\xa6z \x8a\x06\x97\xd9]B\x013<\x00\x00\u07d4f\x92]\xe3\xe4?KA\xbf\x9d\xad\xde'\xd5H\x8e\xf5i\xea\r\x89\x02\"\xc8\xeb?\xf6d\x00\x00\u07d4f\xb0\xc1\x00\u0111I\x93]\x14\xc0\xdc ,\u0390|\xea\x1a=\x89j\xcb=\xf2~\x1f\x88\x00\x00\u07d4f\xb1\xa6=\xa4\xdc\xd9\xf8\x1f\xe5O^?\xcb@U\xef~\xc5O\x89\n\xeb'*\u07dc\xfa\x00\x00\u07d4f\xb3\x987\xcb<\xac\x8a\x80*\xfe?\x12\xa2X\xbb\xcab\xda\u0349\x15\xaf\x1dx\xb5\x8c@\x00\x00\xe0\x94f\xc83\x1e\xfeq\x98\xe9\x8b-2\xb98h\x8e2A\xd0\xe2O\x8a\x02\t\x80Q\x97\x0e9\xd0\x00\x00\u07d4f\u030a\xb2<\x00\u0478*\xcd}s\xf3\x8c\x99\xe0\xd0ZO\xa6\x89\x05k\xc7^-c\x10\x00\x00\u07d4f\xdc\xc5\xfbN\xe7\xfe\xe0F\xe1A\x81\x9a\xa9hy\x9ddD\x91\x89Hz\x9a0E9D\x00\x00\u07d4f\xe0\x94'\xc1\xe6=\xee\xd7\xe1+\x8cU\xa6\xa1\x93 \xefKj\x89\t79SM(h\x00\x00\u07d4f\xec\x16\ue72a\xb4\x11\xc5Zf)\xe3\x18\xden\xe2\x16I\x1d\x89.\xe4IU\b\x98\xe4\x00\x00\u07d4f\xf5\x04\x06\xeb\x1b\x11\xa9F\u02b4Y'\u0323tp\xe5\xa2\b\x89lk\x93[\x8b\xbd@\x00\x00\xe0\x94f\xfd\xc9\xfe\xe3Q\xfa\x158\xeb\r\x87\xd8\x19\xfc\xf0\x9e|\x10j\x8a\x01F'\xb5\xd97\x81\xb2\x00\x00\u07d4g\x04\x8f:\x12\xa4\xdd\x1fbld&L\xb1\u05d7\x1d\xe2\xca8\x89\t\xc2\x00vQ\xb2P\x00\x00\u07d4g\x04\xf1i\xe0\u0433kW\xbb\u00df<EC{^\xe3\u048d\x89\x15[\xd90\u007f\x9f\xe8\x00\x00\u07d4g\x10\x15\xb9vp\xb1\r^X?=b\xa6\x1c\x1cy\xc5\x14?\x89\x15\xaf\x1dx\xb5\x8c@\x00\x00\xe0\x94g\x10\xc2\xc0<e\x99+.wK\xe5-:\xb4\xa6\xba!~\xf7\x8a\x02t\xd6V\xac\x90\xe3@\x00\x00\u07d4g\x11\x10\xd9j\xaf\xf1\x15#\xccTk\xf9\x94\x0e\xed\xff\xb2\xfa\xf7\x89\xd8\xd7&\xb7\x17z\x80\x00\x00\u07d4g\x15\xc1@5\xfbW\xbb=f\u007f{pt\x98\xc4\x10t\xb8U\x89%\xf2s\x93=\xb5p\x00\x00\u07d4g\x1b\xbc\xa0\x99\xff\x89\x9b\xab\a\xea\x1c\xf8ie\xc3\x05L\x89`\x89\x02\xb5\xe3\xaf\x16\xb1\x88\x00\x00\u07d4g'\xda\xf5\xb9\u058e\xfc\xabH\x9f\xed\xec\x96\xd7\xf72]\xd4#\x89lk\x93[\x8b\xbd@\x00\x00\u07d4g,\xbc\xa8D\n\x85w\t{\x19\xaf\xf5\x93\xa2\xad\x9d(\xa7V\x89\x04V9\x18$O@\x00\x00\xe0\x94g.\xc4/\xaa\x8c\u059a\xaaq\xb3,\u01f4\x04\x88\x1dR\xff\x91\x8a\x02\x1e\x19\xe0\u027a\xb2@\x00\x00\xe0\x94g/\xa0\xa0\x19\b\x8d\xb3\x16oa\x19C\x8d\a\xa9\x9f\x8b\xa2$\x8a\x02\xd4\xca\x05\xe2\xb4<\xa8\x00\x00\u07d4g1D\xf0\xec\x14.w\x0fH4\xfe\xe0\xee1\x182\xf3\b{\x89\x1b\x1bk\u05efd\xc7\x00\x00\u07d4g5\vS1\x92o^(\xf3\xc1\xe9\x86\xf9dC\x80\x9c\x8b\x8c\x89\x13\x14\xfb7\x06)\x80\x00\x00\xe0\x94g7\x06\xb1\xb0\xe4\xdcz\x94\x9azybX\xa5\xb8;\xb5\xaa\x83\x8a\x03h\xc8b:\x8bM\x10\x00\x00\u07d4gB\xa2\xcf\u038dy\xa2\u0125\x1bwtt\x98\x91\"E\xcdj\x89\r\xfd[\x80\xb7\xe4h\x00\x00\u07d4gJ\xdb!\xdfL\x98\u01e3G\xacL<$&gW\xddp9\x89lk\x93[\x8b\xbd@\x00\x00\u07d4gQ\x8e]\x02\xb2\x05\x18\x0f\x04c\xa3 \x04G\x1fu<R>\x89k\x91\x8a\xacIK\x16\x80\x00\xe0\x94g]\\\xaa`\x9b\xf7\n\x18\xac\xa5\x80F]\x8f\xb71\r\x1b\xbb\x8a\x04<3\xc1\x93ud\x80\x00\x00\u07d4gc F\u0732ZT\x93i(\xa9oB?3 \xcb\ud489lk\x93[\x8b\xbd@\x00\x00\u07d4ge\xdf%(\x0e\x8eO8\u0531\xcfDo\xc5\xd7\xebe\x9e4\x89\x05k\xc7^-c\x10\x00\x00\u07d4gv\xe13\xd9\xdc5L\x12\xa9Q\b{c\x96P\xf59\xa43\x89\x06\x81U\xa46v\xe0\x00\x00\u07d4g\x85Q<\xf72\xe4~\x87g\ap\xb5A\x9b\xe1\f\xd1\xfct\x89lk\x93[\x8b\xbd@\x00\x00\u07d4g\x947\xea\xcfCxx\xdc)=H\xa3\x9c\x87\xb7B\x1a!l\x89\x03\u007f\x81\x82\x1d\xb2h\x00\x00\u07d4g\x9b\x9a\x10\x990Q~\x89\x99\t\x9c\xcf*\x91LL\x8d\xd94\x89\x03@\xaa\xd2\x1b;p\x00\x00\u07d4g\xa8\x0e\x01\x90r\x1f\x949\rh\x02r\x9d\xd1,1\xa8\x95\xad\x89lk\x13u\xbc\x91V\x00\x00\u07d4g\xb8\xa6\xe9\x0f\xdf\n\x1c\xacD\x17\x930\x1e\x87P\xa9\xfayW\x890\x84\x9e\xbe\x166\x9c\x00\x00\u07d4g\xbc\x85\xe8}\xc3LN\x80\xaa\xfa\x06k\xa8\u049d\xbb\x8eC\x8e\x89\x15\xd1\xcfAv\xae\xba\x00\x00\u07d4g\xc9&\t>\x9b\x89'\x938\x10\u0642\"\xd6.+\x82\x06\xbb\x89g\x8a\x93 b\xe4\x18\x00\x00\u07d4g\xcf\xdanp\xbfvW\u04d0Y\xb5\x97\x90\xe5\x14Z\xfd\xbea\x89#\x05\r\tXfX\x00\x00\u07d4g\u0582\xa2\x82\xefs\xfb\x8dn\x90q\xe2aOG\xab\x1d\x0f^\x8965\u026d\xc5\u07a0\x00\x00\u07d4g\u05a8\xaa\x1b\xf8\xd6\xea\xf78N\x99=\xfd\xf1\x0f\n\xf6\x8aa\x89\n\xbc\xbbW\x18\x97K\x80\x00\u07d4g\u0692.\xff\xa4r\xa6\xb1$\xe8N\xa8\xf8k$\xe0\xf5\x15\xaa\x89\x01\x15\x8eF\t\x13\xd0\x00\x00\u07d4g\xdf$-$\r\u0538\a\x1dr\xf8\xfc\xf3[\xb3\x80\x9dq\xe8\x89\xd8\xd7&\xb7\x17z\x80\x00\x00\u07d4g\xee@n\xa4\xa7\xaej:8\x1e\xb4\xed\xd2\xf0\x9f\x17KI(\x898)c_\th\xb0\x00\x00\u07d4g\xf2\xbbx\xb8\xd3\xe1\x1f|E\x8a\x10\xb5\xc8\xe0\xa1\xd3tF}\x89a\t=|,m8\x00\x00\u07d4g\xfcR}\xce\x17\x85\xf0\xfb\x8b\xc7\xe5\x18\xb1\xc6i\xf7\xec\u07f5\x89\r\x02\xabHl\xed\xc0\x00\x00\u07d4h\x02}\x19U\x8e\xd73\x9a\b\xae\xe8\xde5Y\xbe\x06>\xc2\xea\x89lk\x93[\x8b\xbd@\x00\x00\u07d4h\x06@\x83\x8b\xd0zD{\x16\x8dm\x92;\x90\xcflC\xcd\u0289]\u0212\xaa\x111\xc8\x00\x00\u07d4h\a\xdd\u020d\xb4\x89\xb03\xe6\xb2\xf9\xa8\x15SW\x1a\xb3\xc8\x05\x89\x01\x9f\x8euY\x92L\x00\x00\xe0\x94h\rY\x11\xed\x8d\xd9\xee\xc4\\\x06\f\"?\x89\xa7\xf6 \xbb\u054a\x04<3\xc1\x93ud\x80\x00\x00\u07d4h\x11\xb5L\u0456c\xb1\x1b\x94\xda\x1d\xe2D\x82\x85\u035fh\u0649;\xa1\x91\v\xf3A\xb0\x00\x00\u07d4h\x19\f\xa8\x85\xdaB1\x87L\x1c\xfbB\xb1X\n!s\u007f8\x89\xcf\x15&@\xc5\xc80\x00\x00\xe0\x94h(\x97\xbcO\x8e\x89\x02\x91 \xfc\xff\xb7\x87\xc0\x1a\x93\xe6A\x84\x8a\x02\x1e\x19\xe0\u027a\xb2@\x00\x00\u07d4h)^\x8e\xa5\xaf\xd9\t?\xc0\xa4e\xd1W\x92+]*\xe24\x89\x01\x15NS!}\xdb\x00\x00\u07d4h.\x96'oQ\x8d1\xd7\xe5n0\u07f0\t\xc1!\x82\x01\xbd\x89\x01\x15\x8eF\t\x13\xd0\x00\x00\u07d4h5\xc8\xe8\xb7J,\xa2\xae?J\x8d\x0fk\x95J>*\x83\x92\x89\x03B\x9c3]W\xfe\x00\x00\u07d4h63\x01\n\x88hk\xeaZ\x98\xeaS\xe8y\x97\xcb\xf7>i\x89\x05k9Bc\xa4\f\x00\x00\u07d4h=\xba6\xf7\xe9O@\xeaj\xea\ry\xb8\xf5!\xdeU\an\x89\a\x96\xe3\xea?\x8a\xb0\x00\x00\u07d4hA\x9cm\xd2\xd3\xceo\u02f3\xc7>/\xa0y\xf0`Q\xbd\xe6\x89j\xcb=\xf2~\x1f\x88\x00\x00\u07d4hG;z}\x96Y\x04\xbe\u06e5V\u07fc\x17\x13l\xd5\xd44\x89\x05k\xc7^-c\x10\x00\x00\u07d4hG\x82[\xde\xe8$\x0e(\x04,\x83\xca\xd6B\U000868fd\u0709QP\xae\x84\xa8\xcd\xf0\x00\x00\xe0\x94hJD\xc0i3\x9d\b\xe1\x9auf\x8b\u06e3\x03\xbe\x85S2\x8a\x0e\u04b5%\x84\x1a\xdf\xc0\x00\x00\u07d4hS\x1fM\u0680\x8fS vz\x03\x114(\xca\f\xe2\xf3\x89\x89\x01\r:\xa56\xe2\x94\x00\x00\u07d4hy'\xe3\x04\x8b\xb5\x16*\xe7\xc1\\\xf7k\xd1$\xf9I{\x9e\x89lk\x93[\x8b\xbd@\x00\x00\xe0\x94h\x80\x9a\xf5\xd52\xa1\x1c\x1aMn2\xaa\xc7\\LR\xb0\x8e\xad\x8a\x02\x1e\x19\xe0\u027a\xb2@\x00\x00\u07d4h\x86\xad\xa7\xbb\xb0a{\u0684!\x91\u018c\x92.\xa3\xa8\xac\x82\x89>\xe2;\xde\x0e} \x00\x00\xe0\x94h\x88>\x15.V`\xfe\xe5\x96&\xe7\xe3\xb4\xf0Q\x10\xe6\"/\x8a\v\x94c;\xe9u\xa6*\x00\x00\u07d4h\x8aV\x9e\x96U$\xeb\x1d\n\xc3\xd3s>\xab\x90\x9f\xb3\xd6\x1e\x89G\x8e\xae\x0eW\x1b\xa0\x00\x00\xe0\x94h\x8e\xb3\x85;\xbc\xc5\x0e\xcf\xee\x0f\xa8\u007f\n\xb6\x93\u02bd\xef\x02\x8a\x06\xb1\n\x18@\x06G\xc0\x00\x00\u07d4h\xa7B_\xe0\x9e\xb2\x8c\xf8n\xb1y>A\xb2\x11\xe5{\u058d\x89$=M\x18\"\x9c\xa2\x00\x00\u07d4h\xa8l@#\x88\xfd\xdcY\x02\x8f\xecp!\u933f\x83\x0e\xac\x89\x01\t\x10\xd4\xcd\xc9\xf6\x00\x00\xe0\x94h\xac\u06a9\xfb\x17\xd3\xc3\t\x91\x1aw\xb0_S\x91\xfa\x03N\xe9\x8a\x01\xe5.3l\xde\"\x18\x00\x00\u07d4h\xad\xdf\x01\x9dk\x9c\xabp\xac\xb1?\v1\x17\x99\x9f\x06.\x12\x89\x02\xb5\x12\x12\xe6\xb7\u0200\x00\u07d4h\xb3\x186\xa3\n\x01j\xda\x15{c\x8a\xc1]\xa7?\x18\xcf\u0789\x01h\u048e?\x00(\x00\x00\xe0\x94h\xb6\x85G\x88\xa7\xc6Il\xdb\xf5\xf8K\x9e\xc5\xef9+x\xbb\x8a\x04+\xf0kx\xed;P\x00\x00\u07d4h\xc0\x84\x90\u021b\xf0\u05b6\xf3 \xb1\xac\xa9\\\x83\x12\xc0\x06\b\x89\xd8\xd7&\xb7\x17z\x80\x00\x00\u07d4h\xc7\xd1q\x1b\x01\x1a3\xf1o\x1fU\xb5\xc9\x02\xcc\xe9p\xbd\u05c9\b=lz\xabc`\x00\x00\u07d4h\xc8y\x1d\xc3B\xc3sv\x9e\xa6\x1f\xb7\xb5\x10\xf2Q\xd3 \x88\x8965\u026d\xc5\u07a0\x00\x00\u07d4h\u07d4|I[\ubbb8\u8273\xf9S\xd53\x87K\xf1\x06\x89\x1d\x99E\xab+\x03H\x00\x00\u07d4h\xe8\x02'@\xf4\xaf)\xebH\xdb2\xbc\xec\xdd\xfd\x14\x8d=\xe3\x8965\u026d\xc5\u07a0\x00\x00\u07d4h\xecy\u057eqUql@\x94\x1cy\u05cd\x17\u079e\xf8\x03\x89\x1b#8w\xb5 \x8c\x00\x00\u07d4h\xee\xc1\u222c1\xb6\xea\xba~\x1f\xbdO\x04\xadW\x9ak]\x89lk\x93[\x8b\xbd@\x00\x00\u07d4h\xf5%\x92\x1d\xc1\x1c2\x9buO\xbf>R\x9f\xc7#\xc84\u0349WG=\x05\u06ba\xe8\x00\x00\u07d4h\xf7\x19\xae4+\xd7\xfe\xf1\x8a\x05\u02f0/pZ\u04ce\u0572\x898\xeb\xad\\\u0710(\x00\x00\xe0\x94h\xf7W<\xd4W\xe1L\x03\xfe\xa4>0-04|\x10p\\\x8a\x01\x0f\f\xf0d\xddY \x00\x00\u07d4h\xf8\xf4QU\xe9\x8cP)\xa4\xeb\u0175'\xa9.\x9f\xa81 \x89\xf0{D\xb4\a\x93 \x80\x00\u07d4h\xfe\x13W!\x8d\tXI\xcdW\x98B\u012a\x02\xff\x88\x8d\x93\x89lk\x93[\x8b\xbd@\x00\x00\u07d4i\x02(\xe4\xbb\x12\xa8\u0535\u09d7\xb0\xc5\xcf*u\t\x13\x1e\x89e\xea=\xb7UF`\x00\x00\u07d4i\x05\x94\xd3\x06a<\xd3\xe2\xfd$\xbc\xa9\x99J\u064a=s\xf8\x89lk\x93[\x8b\xbd@\x00\x00\xe0\x94i\a2ir\x9ed\x14\xb2n\xc8\xdc\x0f\xd95\xc7;W\x9f\x1e\x8a\x06ZM\xa2]0\x16\xc0\x00\x00\xe0\x94i\x19\xdd^]\xfb\x1a\xfa@G\x03\xb9\xfa\xea\x8c\xee5\xd0\rp\x8a\x01@a\xb9\xd7z^\x98\x00\x00\u07d4i4\x92\xa5\xc5\x13\x96\xa4\x82\x88\x16i\xcc\xf6\xd8\xd7y\xf0\tQ\x89\x12\xbfPP:\xe3\x03\x80\x00\u07d4i=\x83\xbe\tE\x9e\xf89\v.0\xd7\xf7\u008d\xe4\xb4(N\x89lk\x93[\x8b\xbd@\x00\x00\u07d4iQp\x83\xe3\x03\xd4\xfb\xb6\xc2\x11E\x14!]i\xbcF\xa2\x99\x89\x05k\xc7^-c\x10\x00\x00\u07d4iUPel\xbf\x90\xb7]\x92\xad\x91\"\xd9\r#\xcah\xcaM\x8965\u026d\xc5\u07a0\x00\x00\xe0\x94iX\xf8;\xb2\xfd\xfb'\xce\x04\t\xcd\x03\xf9\xc5\xed\xbfL\xbe\u074a\x04<3\xc1\x93ud\x80\x00\x00\u0794i[\x0fRBu7\x01\xb2d\xa6pq\xa2\u0708\b6\xb8\u06c8\u3601\x1b\xech\x00\x00\xe0\x94i[L\xce\bXV\xd9\xe1\xf9\xff>y\x94 #5\x9e_\xbc\x8a\x01\x0f\f\xf0d\xddY \x00\x00\xe0\x94if\x06:\xa5\xde\x1d\xb5\xc6q\xf3\xddi\x9dZ\xbe!>\xe9\x02\x8a\x01\xb1\xaeMn.\xf5\x00\x00\x00\u07d4it\u0224\x14\u03ae\xfd<.M\xfd\xbe\xf40V\x8d\x9a\x96\v\x89\x12\x1e\xa6\x8c\x11NQ\x00\x00\xe0\x94iximQP\xa9\xa2cQ?\x8ft\u0196\xf8\xb19|\xab\x8a\x01g\xf4\x82\xd3\u0171\xc0\x00\x00\xe0\x94iy{\xfb\x12\u027e\u0582\xb9\x1f\xbcY5\x91\xd5\xe4\x027(\x8a\x02\x1e\x19\xe0\u027a\xb2@\x00\x00\xe0\x94i\u007fUSk\xf8Z\xdaQ\x84\x1f\x02\x87b:\x9f\x0e\u041a\x17\x8a\x02\x1e\x19\xe0\u027a\xb2@\x00\x00\u07d4i\x82\xfe\x8a\x86~\x93\xebJ\v\xd0QX\x93\x99\xf2\xec\x9aR\x92\x89lk\x93[\x8b\xbd@\x00\x00\u07d4i\x8a\x8ao\x01\xf9\xabh/c|yi\xbe\x88_lS\x02\xbf\x89\x01\r:\xa56\xe2\x94\x00\x00\u07d4i\x8a\xb9\xa2\xf33\x81\xe0|\fGC=\r!\xd6\xf36\xb1'\x89\x01\x15\x8eF\t\x13\xd0\x00\x00\u07d4i\x94\xfb21\xd7\xe4\x1dI\x1a\x9dh\xd1\xfaL\xae,\xc1Y`\x89\xd8\xd7&\xb7\x17z\x80\x00\x00\u07d4i\x9c\x9e\xe4q\x95Q\x1f5\xf8b\xcaL\"\xfd5\xae\x8f\xfb\xf4\x89\x04V9\x18$O@\x00\x00\u07d4i\x9f\xc6\u058aGuW<\x1d\u036e\xc80\xfe\xfdP9|N\x89\x03@\xaa\xd2\x1b;p\x00\x00\u07d4i\xaf(\xb0tl\xac\r\xa1p\x84\xb99\x8c^6\xbb:\r\xf2\x896w\x03n\xdf\n\xf6\x00\x00\u07d4i\xb8\x0e\xd9\x0f\x84\x83J\xfa?\xf8.\xb9dp;V\tw\u0589\x01s\x17\x90SM\xf2\x00\x00\xe0\x94i\xb8\x1dY\x81\x14\x1e\u01e7\x14\x10`\xdf\u03cf5\x99\xff\xc6>\x8a\x01\x0f\f\xf0d\xddY \x00\x00\u07d4i\xbc\xfc\x1dC\xb4\xba\x19\xde{'K\xdf\xfb5\x13\x94\x12\xd3\u05c95e\x9e\xf9?\x0f\xc4\x00\x00\u07d4i\xbd%\xad\xe1\xa34lY\xc4\xe90\xdb*\x9dq^\xf0\xa2z\x89\xd8\xd7&\xb7\x17z\x80\x00\x00\u07d4i\xc0\x8dtGT\xdep\x9c\xe9n\x15\xae\r\x1d9[:\"c\x8965\u026d\xc5\u07a0\x00\x00\u07d4i\xc2\xd85\xf1>\xe9\x05\x80@\x8ej2\x83\xc8\u0326\xa44\xa2\x89#\x8f\xd4,\\\xf0@\x00\x00\u07d4i\xc9N\a\u0129\xbe3\x84\xd9]\xfa<\xb9)\x00Q\x87;{\x89\x03\xcbq\xf5\x1f\xc5X\x00\x00\u07d4i\xcb>!S\x99\x8d\x86\xe5\xee \xc1\xfc\u0466\xba\uec86?\x89\xd8\xd7&\xb7\x17z\x80\x00\x00\u07d4i\u04ddQ\b\x89\xe5R\xa3\x96\x13[\xfc\xdb\x06\xe3~8v3\x89\xd8\xd7&\xb7\x17z\x80\x00\x00\xe0\x94i\u064f8\xa3\xba=\xbc\x01\xfa\\,\x14'\xd8b\x83//p\x8a\x15-\x02\xc7\xe1J\xf6\x80\x00\x00\xe0\x94i\xe2\xe2\xe7\x040|\xcc[\\\xa3\xf1d\xfe\xce.\xa7\xb2\xe5\x12\x8a\x01{x\x83\xc0i\x16`\x00\x00\u07d4i\xffB\x90t\u02dblc\xbc\x91B\x84\xbc\xe5\xf0\xc8\xfb\xf7\u0409\x1b\x1a\xe4\xd6\xe2\xefP\x00\x00\u07d4i\xff\x89\x01\xb5Av?\x81|_)\x98\xf0-\xcf\xc1\xdf)\x97\x89\x02+\x1c\x8c\x12'\xa0\x00\x00\u07d4j\x02:\xf5}XM\x84^i\x876\xf10\u06dd\xb4\r\xfa\x9a\x89\x05[ \x1c\x89\x00\x98\x00\x00\u07d4j\x04\xf5\xd5?\xc0\xf5\x15\xbe\x94+\x8f\x12\xa9\xcbz\xb0\xf3\x97x\x89\xa9\xaa\xb3E\x9b\xe1\x94\x00\x00\u07d4j\x05\xb2\x1cO\x17\xf9\xd7?_\xb2\xb0\u02c9\xffSV\xa6\xcc~\x89QP\xae\x84\xa8\xcd\xf0\x00\x00\xe0\x94j\x0f\x05`f\xc2\xd5f(\x85\x02s\xd7\xec\xb7\xf8\xe6\xe9\x12\x9e\x8a\x01\x0f\r)<\u01e5\x88\x00\x00\u07d4j\x13\xd5\xe3,\x1f\xd2m~\x91\xffn\x051`\xa8\x9b,\x8a\xad\x89\x02\xe6/ \xa6\x9b\xe4\x00\x00\u07d4j.\x86F\x9a[\xf3|\xee\x82\xe8\x8bL8c\x89](\xfc\xaf\x89\x1c\"\x92f8[\xbc\x00\x00\u07d4j6\x94BL|\u01b8\xbc\u067c\u02baT\f\xc1\xf5\xdf\x18\u05c9lk\x93[\x8b\xbd@\x00\x00\xe0\x94jB\u0297\x1cex\u056d\xe2\x95\xc3\xe7\xf4\xad3\x1d\xd3BN\x8a\x01EB\xba\x12\xa37\xc0\x00\x00\u07d4jD\xaf\x96\xb3\xf02\xaed\x1b\xebg\xf4\xb6\xc83B\xd3|]\x89\x01\x92t\xb2Y\xf6T\x00\x00\u07d4jL\x89\a\xb6\x00$\x80W\xb1\xe4cT\xb1\x9b\u0705\x9c\x99\x1a\x89\x01\x15\x8eF\t\x13\xd0\x00\x00\u07d4jQNbB\xf6\xb6\x8c\x13~\x97\xfe\xa1\u73b5U\xa7\xe5\xf7\x89\x01\x15\x8eF\t\x13\xd0\x00\x00\u07d4jS\xd4\x1a\xe4\xa7R\xb2\x1a\xbe\xd57FI\x95:Q=\xe5\xe5\x89lk\x93[\x8b\xbd@\x00\x00\u07d4jaY\aJ\xb5s\xe0\xeeX\x1f\x0f=\xf2\u05a5\x94b\x9bt\x89\x10\xce\x1d=\x8c\xb3\x18\x00\x00\u07d4jc7\x83?\x8fjk\xf1\f\xa7\xec!\xaa\x81\x0e\xd4D\xf4\u02c97\xbd$4\\\xe8\xa4\x00\x00\u07d4jcS\xb9qX\x9f\x18\xf2\x95\\\xba(\xab\xe8\xac\xcejWa\x89\xa2\xa1]\tQ\x9b\xe0\x00\x00\u07d4jc\xfc\x89\xab\xc7\xf3n(-\x80x{{\x04\xaf\xd6U>q\x89\b\xacr0H\x9e\x80\x00\x00\u07d4jg\x9e7\x8f\xdc\xe6\xbf\xd9\u007f\xe6/\x04<od\x05\u05de\x99\x89\xd8\xd7&\xb7\x17z\x80\x00\x00\u07d4jhk\xf2 \xb5\x93\u07b9\xb72F\x15\xfb\x91D\xde\xd3\xf3\x9d\x89O%\x91\xf8\x96\xa6P\x00\x00\xe0\x94jk\x18\xa4ZvF~.]Z.\xf9\x11\xc3\xe1))\x85{\x8a\x11]:\x99\xa9aO@\x00\x00\u07d4jt\x84M\x8e\x9c\xb5X\x1cE\a\x9a.\x94F*l\xee\x88!\x89:\xb5:U-\xd4\xc9\x00\x00\xe0\x94j{.\r\x88\x86\u007f\xf1] |\"+\xeb\xf9O\xa6\u0383\x97\x8a\f\xb4\x9bD\xba`-\x80\x00\x00\u07d4j|% B\xe7F\x8a?\xf7s\xd6E\v\xba\x85\xef\xa2c\x91\x89\x1b\x1a\xe4\xd6\xe2\xefP\x00\x00\u07d4j\x8aC\x17\xc4_\xaa\x05T\xcc\xdbH%H\x18>)Z$\xb9\x8965\u026d\xc5\u07a0\x00\x00\u07d4j\x8c\xea-\xe8J\x8d\xf9\x97\xfd?\x84\xe3\b=\x93\xdeW\u0369\x89\x05k\xe0<\xa3\xe4}\x80\x00\xe0\x94j\x97Xt;`>\xea:\xa0RKB\x88\x97#\xc4\x159H\x8a\x02#\x85\xa8'\xe8\x15P\x00\x00\u07d4j\xa5s/;\x86\xfb\x8c\x81\xef\xbek[G\xb5cs\v\x06\u020965\u026d\xc5\u07a0\x00\x00\u07d4j\xb3#\xaePV\xed\nE0r\u016b\xe2\xe4/\xcf]q9\x89/\xb4t\t\x8fg\xc0\x00\x00\u07d4j\xb5\xb4\xc4\x1c\u0778)i\f/\xda\u007f \xc8^b\x9d\xd5\u0549d\u052fqL2\x90\x00\x00\u07d4j\xc4\x0fS-\xfe\xe5\x11\x81\x17\u04ad5-\xa7}Om\xa2\u0209\x15\xaf\x1dx\xb5\x8c@\x00\x00\u07d4j\xc4\u053e-\xb0\u065d\xa3\xfa\xaa\xf7RZ\xf2\x82\x05\x1dj\x90\x89\x04X\xcaX\xa9b\xb2\x80\x00\u07d4j\xcd\u0723\xcd+I\x90\xe2\\\xd6\\$\x14\x9d\t\x12\t\x9ey\x89\xa2\xa1\xe0|\x9fl\x90\x80\x00\u07d4j\xd9\v\xe2R\xd9\xcdFM\x99\x81%\xfa\xb6\x93\x06\v\xa8\xe4)\x89\xd8\xd7&\xb7\x17z\x80\x00\x00\u07d4j\u0753!\x93\xcd8IJ\xa3\xf0:\xec\xccKz\xb7\xfa\xbc\xa2\x89\x04\xdbs%Gc\x00\x00\x00\xe0\x94j\xe5\u007f'\x91|V*\x13*M\x1b\xf7\xec\n\u01c5\x83)&\x8a\x01EB\xba\x12\xa37\xc0\x00\x00\u07d4j\xeb\x9ftt.\xa4\x91\x81=\xbb\xf0\xd6\xfc\xde\x1a\x13\x1dM\xb3\x89\x17\xe5T0\x8a\xa00\x00\x00\u07d4j\xf25\u04bb\xe0P\xe6)\x16\x15\xb7\x1c\xa5\x82\x96X\x81\x01B\x89\xa2\xa1]\tQ\x9b\xe0\x00\x00\u07d4j\xf6\xc7\xee\x99\xdf'\x1b\xa1[\xf3\x84\xc0\xb7d\xad\xcbM\xa1\x82\x8965f3\xeb\xd8\xea\x00\x00\u07d4j\xf8\xe5Yih,q_H\xadO\xc0\xfb\xb6~\xb5\x97\x95\xa3\x89lk\x93[\x8b\xbd@\x00\x00\u07d4j\xf9@\xf6>\u0278\xd8v'*\u0296\xfe\xf6\\\xda\xce\xcd\ua262\xa1]\tQ\x9b\xe0\x00\x00\u07d4j\xf9\xf0\xdf\uebbb_d\xbf\x91\xabw\x16i\xbf\x05)US\x89\x15\xaf\x1dx\xb5\x8c@\x00\x00\u07d4j\xff\x14f\xc2b6u\xe3\xcb\x0eu\xe4#\xd3z%\xe4B\xeb\x89]\u0212\xaa\x111\xc8\x00\x00\xe0\x94k\r\xa2Z\xf2g\u05c3l\"k\xca\xe8\xd8r\xd2\xceR\xc9A\x8a\x01EB\xba\x12\xa37\xc0\x00\x00\u07d4k\x10\xf8\xf8\xb3\xe3\xb6\r\xe9\n\xa1-\x15_\x9f\xf5\xff\xb2,P\x89lk\x93[\x8b\xbd@\x00\x00\u07d4k\x17Y\x8a\x8e\xf5Oyz\xe5\x15\u0336Q}\x18Y\xbf\x80\x11\x89\x05k\xc7^-c\x10\x00\x00\u07d4k \xc0\x80`jy\xc7;\xd8\xe7[\x11qzN\x8d\xb3\xf1\u00c9\x10?sX\x03\xf0\x14\x00\x00\u07d4k\"\x84D\x02!\xce\x16\xa88-\xe5\xff\x02)G\"i\xde\xec\x8965\u026d\xc5\u07a0\x00\x00\u07d4k0\xf1\x829\x10\xb8m:\xcbZj\xfc\x9d\xef\xb6\xf3\xa3\v\xf8\x89\u3bb5sr@\xa0\x00\x00\u07d4k8\u0784\x1f\xad\u007fS\xfe\x02\xda\x11[\xd8j\xaff$f\xbd\x89]\u0212\xaa\x111\xc8\x00\x00\u07d4kK\x99\xcb?\xa9\xf7\xb7L\u3903\x17\xb1\xcd\x13\t\n\x1az\x89\x03\x1b2~i]\xe2\x00\x00\u07d4kZ\xe7\xbfx\xecu\xe9\f\xb5\x03\xc7x\xcc\u04f2KO\x1a\xaf\x89+^:\xf1k\x18\x80\x00\x00\u07d4kc\xa2\u07f2\xbc\xd0\xca\xec\x00\"\xb8\x8b\xe3\f\x14Q\xeaV\xaa\x89+\xdbk\xf9\x1f\u007fL\x80\x00\u07d4kew\xf3\x90\x9aMm\xe0\xf4\x11R-Ep8d\x004\\\x89e\xea=\xb7UF`\x00\x00\u07d4kr\xa8\xf0a\xcf\xe6\x99j\xd4G\xd3\xc7,(\xc0\xc0\x8a\xb3\xa7\x89\xe7\x8cj\u01d9\x12b\x00\x00\u07d4kv\rHw\xe6\xa6'\xc1\xc9g\xbe\xe4Q\xa8P}\xdd\u06eb\x891T\xc9r\x9d\x05x\x00\x00\u07d4k\x83\xba\xe7\xb5e$EXU[\xcfK\xa8\xda \x11\x89\x1c\x17\x89lk\x93[\x8b\xbd@\x00\x00\u07d4k\x92]\xd5\xd8\xeda2\xabm\b`\xb8,D\xe1\xa5\x1f\x1f\xee\x89P; >\x9f\xba \x00\x00\xe0\x94k\x94a]\xb7Pej\u00cc~\x1c\xf2\x9a\x9d\x13g\u007fN\x15\x8a\x02\x8a\x85t%Fo\x80\x00\x00\u07d4k\x95\x1aC'N\xea\xfc\x8a\t\x03\xb0\xaf.\xc9+\xf1\xef\xc89\x89\x05k\xc7^-c\x10\x00\x00\u07d4k\x99%!\xec\x85#p\x84\x8a\u0597\xcc-\xf6Nc\xcc\x06\xff\x8965\u026d\xc5\u07a0\x00\x00\u07d4k\xa8\xf7\xe2_\xc2\xd8qa\x8e$\xe4\x01\x84\x19\x917\xf9\xf6\xaa\x89\x15\xafd\x86\x9ak\xc2\x00\x00\u07d4k\xa9\xb2\x1b5\x10k\xe1Y\xd1\xc1\xc2ez\xc5l\u049f\xfdD\x89\xf2\xdc}G\xf1V\x00\x00\x00\u07d4k\xafz*\x02\xaex\x80\x1e\x89\x04\xadz\xc0Q\b\xfcV\xcf\xf6\x8965\u026d\xc5\u07a0\x00\x00\xe0\x94k\xb2\xac\xa2?\xa1bm\x18\xef\xd6w\u007f\xb9}\xb0-\x8e\n\xe4\x8a\bxg\x83&\xea\xc9\x00\x00\x00\u07d4k\xb4\xa6a\xa3:q\xd4$\u051b\xb5\xdf(b.\xd4\xdf\xfc\xf4\x89\",\x8e\xb3\xfff@\x00\x00\u07d4k\xb5\b\x13\x14j\x9a\xddB\xee\"\x03\x8c\x9f\x1fti\xd4\u007fG\x89\n\xdaUGK\x814\x00\x00\u07d4k\xbc?5\x8af\x8d\u0461\x1f\x03\x80\xf3\xf71\bBj\xbdJ\x89\xd8\xd7&\xb7\x17z\x80\x00\x00\u07d4k\xbd\x1eq\x93\x90\xe6\xb9\x10C\xf8\xb6\xb9\u07c9\x8e\xa8\x00\x1b4\x89llO\xa6\xc3\xdaX\x80\x00\u07d4k\xc8Z\xcdY(r.\xf5\tS1\xee\x88\xf4\x84\xb8\u03c3W\x89\t\xc2\x00vQ\xb2P\x00\x00\u07d4k\xd3\xe5\x9f#\x9f\xaf\xe4wk\xb9\xbd\xddk\ue0fa]\x9d\x9f\x8965\u026d\xc5\u07a0\x00\x00\u07d4k\xd4W\xad\xe0Qy]\xf3\xf2F\\89\xae\xd3\xc5\xde\xe9x\x8964\xbf9\xab\x98x\x80\x00\u07d4k\xe1c\x13d>\xbc\x91\xff\x9b\xb1\xa2\xe1\x16\xb8T\xea\x93:E\x89\x1b\x1a\xe4\xd6\xe2\xefP\x00\x00\u07d4k\xe7Y^\xa0\xf0hH\x9a'\x01\xecFI\x15\x8d\xdcC\xe1x\x89lk\x93[\x8b\xbd@\x00\x00\u07d4k\xe9\x03\x0e\xe6\xe2\xfb\u0111\xac\xa3\xde@\"\xd3\x01w+{}\x89\x01s\x17\x90SM\xf2\x00\x00\xe0\x94k\xec1\x1a\xd0P\b\xb4\xaf5<\x95\x8c@\xbd\x06s\x9a?\xf3\x8a\x03w\xf6*\x0f\nbp\x00\x00\u07d4k\xf7\xb3\xc0e\xf2\xc1\xe7\xc6\xeb\t+\xa0\xd1Pf\xf3\x93\u0478\x89\x15\xaf\x1dx\xb5\x8c@\x00\x00\u07d4k\xf8o\x1e/+\x802\xa9\\Mw8\xa1\t\xd3\xd0\xed\x81\x04\x89b\xa9\x92\xe5:\n\xf0\x00\x00\u07d4l\x05\xe3N^\xf2\xf4.\u041d\xef\xf1\x02l\xd6k\xcbi`\xbb\x89lk\x93[\x8b\xbd@\x00\x00\u07d4l\b\xa6\xdc\x01s\xc74)U\xd1\xd3\xf2\xc0e\xd6/\x83\xae\u01c9\x01\x15\x8eF\t\x13\xd0\x00\x00\u07d4l\n\xe9\xf0C\xc84\xd4Bq\xf14\x06Y=\xfe\tO8\x9f\x89RD*\xe13\xb6*\x80\x00\u07d4l\f\xc9\x17\xcb\xee}|\t\x97c\xf1Nd\xdf}4\xe2\xbf\t\x89\r\x8drkqw\xa8\x00\x00\xe0\x94l\x0eq/@\\Yr_\xe8)\xe9wK\xf4\xdf\u007fM\xd9e\x8a\f(h\x88\x9c\xa6\x8aD\x00\x00\xe0\x94l\x10\x12\x05\xb3#\xd7uD\xd6\xdcR\xaf7\xac\xa3\xce\xc6\xf7\xf1\x8a\x02\x1e\x19\xe0\u027a\xb2@\x00\x00\u07d4l\x15\xec5 \xbf\x8e\xbb\xc8 \xbd\x0f\xf1\x97x7T\x94\u03dd\x89l\xb7\xe7Hg\xd5\xe6\x00\x00\xe0\x94l\x1d\xdd3\xc8\x19f\u0706!w`q\xa4\x12\x94\x82\xf2\xc6_\x8a\bxg\x83&\xea\xc9\x00\x00\x00\u07d4l%2\u007f\x8d\u02f2\xf4^V\x1e\x86\xe3]\x88P\xe5:\xb0Y\x89;\xcd\xf9\xba\xfe\xf2\xf0\x00\x00\u07d4l.\x9b\xe6\u052bE\x0f\xd1%1\xf3?\x02\x8caFt\xf1\x97\x89\xc2\x12z\xf8X\xdap\x00\x00\u07d4l5\x9eX\xa1=Ex\xa93\x8e3\\g\xe7c\x9f_\xb4\u05c9\v\xd1[\x94\xfc\x8b(\x00\x00\u07d4l=\x18pA&\xaa\x99\xee3B\xce`\xf5\xd4\xc8_\x18g\u0349\x02\xb5\xe3\xaf\x16\xb1\x88\x00\x00\u07d4lGK\xc6jTx\x00f\xaaOQ.\xef\xa7s\xab\xf9\x19\u01c9\x05\x18\x83\x15\xf7v\xb8\x00\x00\u07d4lNBn\x8d\xc0\x05\u07e3Ql\xb8\xa6\x80\xb0.\ua56e\x8e\x89Hz\x9a0E9D\x00\x00\u07d4lR\xcf\b\x95\xbb5\xe6V\x16\x1eM\xc4j\xe0\xe9m\xd3\xe6,\x89\xd8\xd8X?\xa2\xd5/\x00\x00\u07d4lT\"\xfbK\x14\xe6\u064b`\x91\xfd\xecq\xf1\xf0\x86@A\x9d\x89\x15\xaf\x1dx\xb5\x8c@\x00\x00\u07d4l\\:T\u0367\xc2\xf1\x18\xed\xbaCN\xd8\x1en\xbb\x11\xddz\x89\n\u05ce\xbcZ\xc6 \x00\x00\u07d4lc\xf8EV\u0490\xbf\u0359\xe44\ue657\xbf\xd7yWz\x89lk\x93[\x8b\xbd@\x00\x00\u07d4lc\xfc\x85\x02\x9a&T\u05db+\xeaM\xe3I\xe4REw\u0149#\xc7W\a+\x8d\xd0\x00\x00\u07d4led\xe5\xc9\xc2N\xaa\xa7D\xc9\xc7\xc9h\xc9\xe2\xc9\xf1\xfb\xae\x89I\x9bB\xa2\x119d\x00\x00\xe0\x94lg\xd6\xdb\x1d\x03Ql\x12\x8b\x8f\xf24\xbf=I\xb2m)A\x8a\x15-\x02\xc7\xe1J\xf6\x80\x00\x00\u07d4lg\xe0\u05f6.*\bPiE\xa5\xdf\xe3\x82c3\x9f\x1f\"\x89j\xcb=\xf2~\x1f\x88\x00\x00\u07d4lj\xa0\xd3\vdr\x19\x90\xb9PJ\x86?\xa0\xbf\xb5\xe5}\xa7\x89\x92^\x06\xee\xc9r\xb0\x00\x00\u07d4lqJX\xff\xf6\xe9}\x14\xb8\xa5\xe3\x05\xeb$@eh\x8b\xbd\x89\xd8\xd7&\xb7\x17z\x80\x00\x00\u07d4l\x80\rKI\xba\a%\x04`\xf9\x93\xb8\xcb\xe0\v&j%S\x89\x1a\xb2\xcf|\x9f\x87\xe2\x00\x00\u07d4l\x80\x8c\xab\xb8\xff_\xbbc\x12\xd9\xc8\xe8J\xf8\xcf\x12\xef\bu\x89\xd8\xd8X?\xa2\xd5/\x00\x00\xe0\x94l\x82 )!\x8a\xc8\xe9\x8a&\f\x1e\x06@)4\x889\x87[\x8a\x01\x0f\x97\xb7\x87\xe1\xe3\b\x00\x00\u07d4l\x84\u02e7|m\xb4\xf7\xf9\x0e\xf1=^\xe2\x1e\x8c\xfc\u007f\x83\x14\x89lk\x93[\x8b\xbd@\x00\x00\xe0\x94l\x86\x87\xe3Aw\x10\xbb\x8a\x93U\x90!\xa1F\x9ej\x86\xbcw\x8a\x02[-\xa2x\xd9k{\x80\x00\xe0\x94l\x88,'s,\xef\\|\x13\xa6\x86\xf0\xa2\xeawUZ\u0089\x8a\x15-\x02\xc7\xe1J\xf6\x80\x00\x00\u07d4l\xa5\xde\x00\x81}\xe0\xce\xdc\xe5\xfd\x00\x01(\xde\xde\x12d\x8b<\x89\x01\x15\x8eF\t\x13\xd0\x00\x00\u07d4l\xa6\xa12\xce\x1c\u0488\xbe\xe3\x0e\xc7\xcf\xef\xfb\x85\xc1\xf5\nT\x89lk\x93[\x8b\xbd@\x00\x00\xe0\x94l\xb1\x1e\xcb2\xd3\u0382\x96\x011\x066\xf5\xa1\f\xf7\u03db_\x8a\x04?\u851c8\x01\xf5\x00\x00\u07d4l\xc1\xc8x\xfal\u078a\x9a\v\x83\x11$~t\x1eFB\xfem\x895e\x9e\xf9?\x0f\xc4\x00\x00\xe0\x94l\xcb\x03\xac\xf7\xf5<\xe8z\xad\xcc!\xa9\x93-\xe9\x15\xf8\x98\x04\x8a\x01\xb1\xaeMn.\xf5\x00\x00\x00\u07d4l\xd2\x12\xae\xe0N\x01?=*\xba\u04a0#`k\xfb\\j\u01c9lj\xccg\u05f1\xd4\x00\x00\u07d4l\xd2(\xdcq!i0\u007f\xe2|\xebtw\xb4\x8c\xfc\x82r\xe5\x89\x044\xea\x94\u06caP\x00\x00\u07d4l\xe1\xb0\xf6\xad\xc4pQ\xe8\xab8\xb3\x9e\xdbA\x86\xb0;\xab\u0309Ay\x97\x94\xcd$\xcc\x00\x00\u07d4l\xea\xe3s=\x8f\xa4=l\xd8\f\x1a\x96\xe8\xeb\x93\x10\x9c\x83\xb7\x89\x10'\x94\xad \xdah\x00\x00\u07d4m\x05i\xe5U\x8f\xc7\xdf'f\xf2\xba\x15\u070a\xef\xfc[\xebu\x89\xd8\xe6\x00\x1el0+\x00\x00\u07d4m\x12\x0f\f\xaa\xe4O\xd9K\xca\xfeU\xe2\xe2y\uf5ba\\z\x89\xd8\xd7&\xb7\x17z\x80\x00\x00\u07d4m\x14V\xff\xf0\x10N\xe8D\xa31G7\x8438\xd2L\xd6l\x89\a\xb0l\xe8\u007f\xddh\x00\x00\u07d4m \xef\x97\x04g\nP\v\xb2i\xb5\x83.\x85\x98\x02\x04\x9f\x01\x89\a\f\x1c\xc7;\x00\xc8\x00\x00\xe0\x94m/\x97g4\xb9\xd0\a\r\x18\x83\xcfz\u02b8\xb3\xe4\x92\x0f\xc1\x8a\x02\x1e\x19\xe0\u027a\xb2@\x00\x00\u07d4m9\xa9\u93c1\xf7i\xd7:\xad,\xea\xd2v\xac\x13\x87\xba\xbe\x89\x15[\xd90\u007f\x9f\xe8\x00\x00\u07d4m;x6\xa2\xb9\u0619r\x1aM#{R#\x85\xdc\xe8\xdf\u034966\xc2^f\xec\xe7\x00\x00\u07d4m?+\xa8V\u033b\x027\xfava\x15k\x14\xb0\x13\xf2\x12@\x8965\u026d\xc5\u07a0\x00\x00\xe0\x94m@\b\xb4\xa8\x88\xa8&\xf2H\xeej\v\r\xfd\xe9\xf92\x10\xb9\x8a\x01'\xfc\xb8\xaf\xae \xd0\x00\x00\u07d4m@\xca'\x82m\x97s\x1b>\x86\xef\xfc\u05f9*Aa\xfe\x89\x89lk\x93[\x8b\xbd@\x00\x00\u07d4mD\x97J1\u0447\xed\xa1m\xddG\xb9\xc7\xecP\x02\xd6\x1f\xbe\x892\xf5\x1e\u06ea\xa30\x00\x00\xe0\x94mK\\\x05\xd0j \x95~\x17H\xabm\xf2\x06\xf3C\xf9/\x01\x8a\x02\x1f6\x06\x99\xbf\x82_\x80\x00\xe0\x94mL\xbf=\x82\x84\x83:\xe9\x93D0>\b\xb4\xd6\x14\xbf\xda;\x8a\x02\x8a\x85t%Fo\x80\x00\x00\u07d4mY\xb2\x1c\xd0\xe2t\x88\x04\u066b\xe0d\xea\u00be\xf0\xc9_'\x89lk\x93[\x8b\xbd@\x00\x00\u07d4mc\u04ce\xe8\xb9\x0e\x0en\xd8\xf1\x92\xed\xa0Q\xb2\u05a5\x8b\xfd\x89\x01\xa0Ui\r\x9d\xb8\x00\x00\u07d4mf4\xb5\xb8\xa4\x01\x95\xd9I\x02z\xf4\x82\x88\x02\t,\ued89\xa2\xa1]\tQ\x9b\xe0\x00\x00\xe0\x94m}\x1c\x94\x95\x11\xf8\x83\x03\x80\x8c`\xc5\xea\x06@\xfc\xc0&\x83\x8a\x02\x1e\x19\xe0\u027a\xb2@\x00\x00\u07d4m\x84m\xc1&W\xe9\x1a\xf2P\bQ\x9c>\x85\u007fQp}\u0589\xf8\xd3\v\xc9#B\xf8\x00\x00\u07d4m\x91\x93\x99k\x19F\x17!\x11\x06\xd1c^\xb2l\u0136ll\x89\x15\xaa\x1e~\x9d\xd5\x1c\x00\x00\u07d4m\x99\x97P\x98\x82\x02~\xa9G#\x14$\xbe\xde\xde)e\u043a\x89l\x81\u01f3\x11\x95\xe0\x00\x00\u07d4m\xa0\xed\x8f\x1di3\x9f\x05\x9f*\x0e\x02G\x1c\xb4O\xb8\u00fb\x892\xbc8\xbbc\xa8\x16\x00\x00\u07d4m\xb7+\xfdC\xfe\xf4e\xcaV2\xb4Z\xabra@N\x13\xbf\x89lk\x93[\x8b\xbd@\x00\x00\xe0\x94m\xbe\x8a\xbf\xa1t(\x06&9\x817\x1b\xf3\xd3U\x90\x80kn\x8a\x04<3\xc1\x93ud\x80\x00\x00\u07d4m\xc3\xf9+\xaa\x1d!\u06b78+\x892a\xa05o\xa7\xc1\x87\x89]\u0212\xaa\x111\xc8\x00\x00\u07d4m\xc7\x05:q\x86\x16\xcf\u01cb\xeec\x82\xeeQ\xad\xd0\xc7\x030\x89lk\x93[\x8b\xbd@\x00\x00\xe0\x94m\xcc~d\xfc\xaf\xcb\xc2\xdcl\x0e^f,\xb3G\xbf\xfc\xd7\x02\x8a\x04<3\xc1\x93ud\x80\x00\x00\u07d4m\xda_x\x8alh\x8d\u07d2\x1f\xa3\x85.\xb6\xd6\xc6\xc6)f\x89\x02+\x1c\x8c\x12'\xa0\x00\x00\u07d4m\xdb`\x92w\x9dXB\xea\xd3x\xe2\x1e\x81 \xfdLk\xc12\x89lk\x93[\x8b\xbd@\x00\x00\u07d4m\xdf\xefc\x91U\u06ab\n\\\xb4\x95:\xa8\u016f\xaa\x88\x04S\x89b\xa9\x92\xe5:\n\xf0\x00\x00\u07d4m\xe0/-\xd6~\xfd\xb794\x02\xfa\x9e\xaa\xcb\xcfX\x9d.V\x89@\x13\x8b\x91~\u07f8\x00\x00\u07d4m\u4d418\\\xf7\xfc\x9f\xe8\xc7}\x13\x1f\xe2\xeew$\xc7j\x89})\x97s=\xcc\xe4\x00\x00\u07d4m\xe4\xd1R\x19\x18/\xaf:\xa2\xc5\xd4\xd2Y_\xf20\x91\xa7'\x89U\xa6\xe7\x9c\xcd\x1d0\x00\x00\u07d4m\xed\xf6.t?M,*K\x87\xa7\x87\xf5BJz\xeb9<\x89\t\xc2\x00vQ\xb2P\x00\x00\u07d4m\xf2Of\x85\xa6/y\x1b\xa37\xbf?\xf6~\x91\xf3\u053c:\x89ukI\xd4\nH\x18\x00\x00\u07d4m\xf5\xc8O{\x90\x9a\xab>a\xfe\x0e\xcb\x1b;\xf2`\"*\u0489\xd8\xd7&\xb7\x17z\x80\x00\x00\u07d4m\xff\x90\xe6\xdc5\x9d%\x90\x88+\x14\x83\xed\xbc\xf8\x87\xc0\xe4#\x8965\u026d\xc5\u07a0\x00\x00\u07d4n\x01\xe4\xadV\x9c\x95\xd0\a\xad\xa3\r^-\xb1(\x88I\"\x94\x89\xd8\xd7&\xb7\x17z\x80\x00\x00\u07d4n\a;f\u0478\xc6gD\u0600\x96\xa8\u0759\xec~\x02(\u0689\xd8\xd7&\xb7\x17z\x80\x00\x00\u07d4n\x0e\xe7\x06\x12\xc9v(}I\x9d\u07e6\xc0\xdc\xc1,\x06\xde\xea\x89\a\v\u0579V!F\x00\x00\xe0\x94n\x12\xb5\x1e\"[JCr\xe5\x9a\u05e2\xa1\xa1>\xa3\u04e17\x8a\x03\x00F\xc8\xccw_\x04\x00\x00\u07d4n\x1a\x04l\xaf[JW\xf4\xfdK\xc1sb!&\xb4\xe2\xfd\x86\x89a\t=|,m8\x00\x00\u07d4n\x1e\xa4\xb1\x83\xe2R\u027bwg\xa0\x06\u05346\x96\u02ca\xe9\x89\x0f\xf3x<\x85\xee\u0400\x00\u07d4n%[p\n\xe7\x13\x8aK\xac\xf2(\x88\xa9\xe2\xc0\n(^\xec\x89\xd8\xd7&\xb7\x17z\x80\x00\x00\u07d4n'\n\xd5)\xf1\xf0\xb8\xd9\xcbm$'\xec\x1b~-\xc6Jt\x89\n\u05ce\xbcZ\xc6 \x00\x00\u07d4n.\xab\x85\u0709\xfe)\xdc\n\xa1\x852G\u06b4:R=V\x89\x04V9\x18$O@\x00\x00\u07d4n:Q\xdbt=3M/\xe8\x82$\xb5\xfe|\x00\x8e\x80\xe6$\x89\x05\xbf\v\xa6cOh\x00\x00\u07d4nL*\xb7\xdb\x02i9\xdb\u04fch8J\xf6`\xa6\x18\x16\xb2\x89\t\r\x97/22<\x00\x00\u07d4nM.9\u0203f)\u5d07\xb1\x91\x8af\x9a\xeb\u07556\x8965\u026d\xc5\u07a0\x00\x00\u07d4n\\-\x9b\x1cTj\x86\xee\xfd]\nQ \xc9\xe4\xe70\x19\x0e\x89\n\xd2\x01\xa6yO\xf8\x00\x00\u07d4n`\xae\u19cf\x8e\u068bBLs\xe3S5J\xe6|0B\x89\xbd5\xa4\x8d\x99\x19\xe6\x00\x00\u07d4nd\xe6\x12\x9f\"N7\x8c\x0ensj~z\x06\xc2\x11\xe9\xec\x8965\u026d\xc5\u07a0\x00\x00\u07d4nm[\xbb\xb9\x05;\x89\xd7D\xa2s\x16\u00a7\xb8\xc0\x9bT}\x891Rq\n\x02>m\x80\x00\u07d4nr\xb2\xa1\x18j\x8e)\x16T;\x1c\xb3jh\x87\x0e\xa5\u0457\x89\n\x15D\xbe\x87\x9e\xa8\x00\x00\u07d4nv\x1e\xaa\x0f4_w{TA\xb7:\x0f\xa5\xb5k\x85\xf2-\x89lk\x93[\x8b\xbd@\x00\x00\u07d4ny\xed\u0504[\anL\u060d\x18\x8bnC-\xd9?5\xaa\x893\xc5I\x901r\f\x00\x00\u07d4n\x82\x12\xb7\"\xaf\xd4\b\xa7\xa7>\xd3\xe29^\xe6EJ\x030\x89\b\x9e\x91y\x94\xf7\x1c\x00\x00\u07d4n\x84\x87m\xbb\x95\xc4\vfV\xe4+\xa9\xae\xa0\x8a\x99;T\u0709;\xbc`\xe3\xb6\u02fe\x00\x00\u07d4n\x84\xc2\xfd\x18\xd8\tW\x14\xa9h\x17\x18\x9c\xa2\x1c\xcab\xba\xb1\x89\x12{lp&!\u0340\x00\u07d4n\x86m\x03-@Z\xbd\xd6\\\xf6QA\x1d\x807\x96\xc2#\x11\x89lk\x93[\x8b\xbd@\x00\x00\xe0\x94n\x89\x9eY\xa9\xb4\x1a\xb7\xeaA\xdfu\x17\x86\x0f*\xcbY\xf4\xfd\x8a\x04<3\xc1\x93ud\x80\x00\x00\u07d4n\x89\xc5\x1e\xa6\xde\x13\xe0l\xdct\x8bg\xc4A\x0f\u9f2b\x03\x89\xd8\xd7&\xb7\x17z\x80\x00\x00\u07d4n\x8a&h\x9fz/\xde\xfd\x00\x9c\xba\xaaS\x10%4P\u06ba\x89o!7\x17\xba\xd8\xd3\x00\x00\u07d4n\x96\xfa\xed\xa3\x05C\x02\xc4_X\xf1a2L\x99\xa3\xee\xbbb\x89\x01\x15\x8eF\t\x13\xd0\x00\x00\u07d4n\xb0\xa5\xa9\xae\x96\xd2,\xf0\x1d\x8f\xd6H;\x9f8\xf0\x8c,\x8b\x89\xd8\xd7&\xb7\x17z\x80\x00\x00\u07d4n\xb3\x81\x96\x17@@X&\x8f\f<\xff5\x96\xbf\xe9\x14\x8c\x1c\x89Z\x87\xe7\xd7\xf5\xf6X\x00\x00\xe0\x94n\xb5W\x8ak\xb7\xc3!S\x19[\r\x80 \xa6\x91HR\xc0Y\x8a\x8b\u00ab\xf4\x02!\xf4\x80\x00\x00\u07d4n\xbb^iW\xaa\x82\x1e\xf6Y\xb6\x01\x8a9:PL\xaeDP\x89lk\x93[\x8b\xbd@\x00\x00\u07d4n\xbc\xf9\x95\u007f_\xc5\u916d\xd4u\";\x04\xb8\xc1Jz\xed\x89]\u0212\xaa\x111\xc8\x00\x00\u07d4n\xc3e\x95q\xb1\x1f\x88\x9d\xd49\xbc\xd4\xd6u\x10\xa2[\xe5~\x89\x06\xaa\xf7\xc8Qm\f\x00\x00\u07d4n\u021b9\xf9\xf5'jU>\x8d\xa3\x0en\xc1z\xa4~\xef\u01c9\x18BO_\v\x1bN\x00\x00\u07d4n\xc9m\x13\xbd\xb2M\u01e5W)?\x02\x9e\x02\xddt\xb9zU\x89\xd8\xd7&\xb7\x17z\x80\x00\x00\u07d4n\xca\xef\xa6\xfc>\xe54bm\xb0,o\x85\xa0\u00d5W\x1ew\x89 \x86\xac5\x10R`\x00\x00\u07d4n\u04a1+\x02\xf8\u0188\u01f5\u04e6\xea\x14\xd66\x87\u06b3\xb6\x89lk\x93[\x8b\xbd@\x00\x00\u07d4n\u0604E\x9f\x80\x9d\xfa\x10\x16\xe7p\xed\xaf>\x9f\xefF\xfa0\x89\xb8R\xd6x \x93\xf1\x00\x00\xe0\x94n\xdf\u007fR\x83r\\\x95>\xe6C\x17\xf6a\x88\xaf\x11\x84\xb03\x8a\x01\xb4d1\x1dE\xa6\x88\x00\x00\u07d4n\xe8\xaa\xd7\xe0\xa0e\u0605-|;\x9an_\xdcK\xf5\f\x00\x89\x01\x15\x8eF\t\x13\xd0\x00\x00\u07d4n\xef\u0705\x0e\x87\xb7\x15\xc7'\x91w<\x03\x16\xc3U\x9bX\xa4\x89\xd8\xd7&\xb7\x17z\x80\x00\x00\u07d4n\xf9\xe8\u0276!}Vv\x9a\xf9}\xbb\x1c\x8e\x1b\x8b\xe7\x99\u0489\t\xdd\xc1\xe3\xb9\x01\x18\x00\x00\u07d4n\xfb\xa8\xfb*\u0176s\a)\xa9r\xec\"D&\xa2\x87\u00ed\x89\x0fY\x85\xfb\xcb\xe1h\x00\x00\xe0\x94n\xfd\x90\xb55\xe0\v\xbd\x88\x9f\xda~\x9c1\x84\xf8y\xa1Q\u06ca\x02#\x85\xa8'\xe8\x15P\x00\x00\u07d4o\x05\x16f\xcbO{\u04b1\x90r!\xb8)\xb5U\u05e3\xdbt\x89_h\xe8\x13\x1e\u03c0\x00\x00\u07d4o\x0e\xdd#\xbc\xd8_`\x15\xf9(\x9c(\x84\x1f\xe0L\x83\xef\xeb\x89\x01\t\x10\xd4\xcd\xc9\xf6\x00\x00\u07d4o\x13zq\xa6\xf1\x97\xdf,\xbb\xf0\x10\u073d<DN\xf5\xc9%\x89lk\x93[\x8b\xbd@\x00\x00\u07d4o\x17`e\xe8\x8e<o\xe6&&}\x18\xa0\x88\xaa\xa4\u06c0\xbc\x89\xbe\xd1\xd0&=\x9f\x00\x00\x00\u07d4o\x18\xecv~2\x05\b\x19_\x13tP\x0e?.\x12V\x89\xff\x8965\u026d\xc5\u07a0\x00\x00\u07d4o\x1fI\a\xb8\xf6\x1f\fQV\x8di(\x06\xb3\x82\xf5\x03$\xf5\x89lk\x93[\x8b\xbd@\x00\x00\u07d4o$\u026f+v4\x80Q]\x1b\tQ\xbbw\xa5@\xf1\xe3\xf9\x89j\xcb=\xf2~\x1f\x88\x00\x00\u07d4o%v\xdaM\u20fb\xe8\xe3\xeei\xdd\xd6n^q\x1d\xb3\xf5\x89DY\x1dg\xfe\u0300\x00\x00\u07d4o)\xbb7[\xe5\xed4\ud65b\xb80\xee)W\xdd\xe7m\x16\x89lk\x93[\x8b\xbd@\x00\x00\u07d4o*1\x90\x0e$\x03\x95\xb1\x9f\x15\x9c\x1d\x00\xdf\xe4\u0618\xeb\u07c9lf\x06E\xaaG\x18\x00\x00\u07d4o*B\xe6\xe03\xd0\x10a\x13\x19)\xf7\xa6\xee\x158\x02\x1eR\x89lk\x93[\x8b\xbd@\x00\x00\u07d4o9\xcc7\u02aa-\u071ba\x0fa1\xe0a\x9f\xaew*<\x89\x1b\x1a\xe4\xd6\xe2\xefP\x00\x00\u07d4oD\xca\t\xf0\u01a8)L\xbdQ\x9c\xdcYJ\xd4,gW\x9f\x89\x02\xb5\xe3\xaf\x16\xb1\x88\x00\x00\u07d4oP\x92\x97w\x82L)\x1aI\xc4m\xc8T\xf3y\xa6\xbe\xa0\x80\x89\x13\x84\x00\xec\xa3d\xa0\x00\x00\xe0\x94ol\xf2\x06I\xa9\xe9s\x17z\xc6}\xba\xde\xe4\xeb\xe5\u01fd\u068a\x01\x13c)}\x01\xa8`\x00\x00\u07d4oy\x1d5\x9b\xc3Sj1]c\x82\xb8\x83\x11\xaf\x8e\xd6\xdaG\x89\x04\xfc\xc1\xa8\x90'\xf0\x00\x00\u07d4oyM\xbd\xf6#\u06a6\xe0\xd0\at\xadibs|\x92\x1e\xa4\x89lk\x93[\x8b\xbd@\x00\x00\u07d4oz\u0181\xd4^A\x8f\u038b:\x1d\xb5\xbc;\xe6\xf0l\x98I\x89lk\x93[\x8b\xbd@\x00\x00\u07d4o\x81\xf3\xab\xb1\xf93\xb1\xdf9k\x8e\x9c\xc7#\xa8\x9b|\x98\x06\x89\x0f-\xc7\xd4\u007f\x15`\x00\x00\u07d4o\x8f\r\x15\u0316\xfb\u007f\xe9O\x10e\xbci@\xf8\xd1)W\xb2\x8965\u026d\xc5\u07a0\x00\x00\u07d4o\x92\xd6\xe4T\x8cx\x99e\t\xeehK.\u26e3\xc52\xb4\x8965\u026d\xc5\u07a0\x00\x00\xe0\x94o\xa6\r\xf8\x18\xa5Dd\x18\xb1\xbb\xd6(&\u0e42^\x13\x18\x8a\x02\u02d2\u030fg\x14@\x00\x00\u07d4o\xa68\x8d@+0\xaf\xe5\x994\u00f9\xe1=\x11\x86G`\x18\x89$R\x1e*0\x17\xb8\x00\x00\u07d4o\xa7 \x15\xfaxin\xfd\x9a\x86\x17O\u007f\x1f!\x01\x92\x86\xb1\x89Hz\x9a0E9D\x00\x00\u07d4o\xc2^~\x00\xcaO`\xa9\xfeo(\xd1\xfd\xe3T.-\x10y\x89*\xef5;\xcd\xdd`\x00\x00\u07d4o\xc56b7\x1d\xcaX{Y\x85\r\xe7\x86\x06\xe25\x9d\xf3\x83\x89\t\xc2\x00vQ\xb2P\x00\x00\xe0\x94o\xcc,s+\u0753J\xf6\xcc\xd1hF\xfb&\uf272\xaa\x9b\x8a\x02\x1e+\x1dB&\x1dI\x00\x00\u07d4o\xd4\xe0\xf3\xf3+\xeem7g\xfd\xbc\x9d5:m:\xabx\x99\x89%\xb0d\xa8u\xea\x94\x00\x00\xe0\x94o\xd9G\u0567;\x17P\b\xaen\xe8\"\x81c\xda(\x9b\x16}\x8a\x06ZM\xa2]0\x16\xc0\x00\x00\u07d4o\u064eV=\x12\xce\x0f\xd6\x0fO\x1f\x85\n\u35a9\x82<\x02\x89D[\xe3\xf2\uf1d4\x00\x00\xe0\x94o\u077d\x9b\xcaf\xe2\x87e\xc2\x16,\x843T\x8c\x10R\xed\x11\x8a\x11\x84B\x9b\x82\xa8\x18\x80\x00\x00\u07d4o\xf5\xd3a\xb5*\u0436\x8b\x15\x88`~\xc3\x04\xaeVe\xfc\x98\x89i*\xe8\x89p\x81\xd0\x00\x00\u07d4o\xf6\u0310\xd6I\xdeN\x96\xcf\xfe\xe1\az[0*\x84\x8d\u02c9\x01\x8c\xe7\x9cx\x80,\x00\x00\u07d4o\xfe\\\xf8,\xc9\xea^6\xca\xd7\u0097L\xe7$\x9f7I\xe6\x89i*\xe8\x89p\x81\xd0\x00\x00\xe0\x94p\x05\xa7r(+\x1fb\xaf\xdac\xf8\x9b]\u01abd\xc8L\xb9\x8a\x03\xcf\xc8.7\xe9\xa7@\x00\x00\u07d4p\a\x11\xe3\x11\xbb\x94sU\xf7U\xb5y%\f\xa7\xfdvZ>\x89a\t=|,m8\x00\x00\u07d4p\x10\xbe-\xf5{\u042b\x9a\xe8\x19l\xd5\n\xb0\xc5!\xab\xa9\xf9\x89j\xcb=\xf2~\x1f\x88\x00\x00\u07d4p#\xc7\tV\xe0J\x92\xd7\x00%\xaa\u0497\xb59\xaf5Xi\x89lk\x93[\x8b\xbd@\x00\x00\u07d4p%\x96]+\x88\xda\x19}DY\xbe=\xc98cD\xcc\x1f1\x89l\xb7\xe7Hg\xd5\xe6\x00\x00\u07d4p(\x02\xf3m\x00%\x0f\xabS\xad\xbc\u0596\xf0\x17oc\x8aI\x89lk\x93[\x8b\xbd@\x00\x00\u07d4pH\x19\xd2\xe4Mn\xd1\xda%\xbf\u0384\u011f\u0322V\x13\xe5\x89\x15\xaf\x1dx\xb5\x8c@\x00\x00\u07d4pJn\xb4\x1b\xa3O\x13\xad\xdd\xe7\xd2\xdb}\xf0I\x15\u01e2!\x89b\xa9\x92\xe5:\n\xf0\x00\x00\u07d4pJ\xb1\x15\r^\x10\xf5\xe3I\x95\b\xf0\xbfpe\x0f\x02\x8dK\x89\xd8\xd7&\xb7\x17z\x80\x00\x00\u07d4pJ\xe2\x1dv-n\x1d\xde(\xc25\xd11\x04Yr6\xdb\x1a\x89lk\x93[\x8b\xbd@\x00\x00\u07d4pM$<)x\xe4l,\x86\xad\xbe\xcd$n;)_\xf63\x89m\x12\x1b\xeb\xf7\x95\xf0\x00\x00\u07d4pM]\xe4\x84m9\xb5<\xd2\x1d\x1cI\xf0\x96\xdb\\\x19\xba)\x89\b=lz\xabc`\x00\x00\u07d4p]\xdd85T\x82\xb8\xc7\u04f5\x15\xbd\xa1P\r\xd7\u05e8\x17\x89\x15\xaf\x1dx\xb5\x8c@\x00\x00\xe0\x94pan(\x92\xfa&\x97\x05\xb2\x04k\x8f\xe3\xe7/\xa5X\x16\u04ca\x04<3\xc1\x93ud\x80\x00\x00\u07d4pg\x0f\xbb\x05\xd30\x14DK\x8d\x1e\x8ew\x00%\x8b\x8c\xaam\x89lk\x93[\x8b\xbd@\x00\x00\u07d4p\x81\xfak\xaa\xd6\u03f7\xf5\x1b,\xca\x16\xfb\x89p\x99\x1ad\xba\x89\f\xae\xc0\x05\xf6\xc0\xf6\x80\x00\xe0\x94p\x85\xae~~M\x93!\x97\xb5\u01c5\x8c\x00\xa3gF&\xb7\xa5\x8a\x01EB\xba\x12\xa37\xc0\x00\x00\u07d4p\x86\xb4\xbd\xe3\xe3]J\xeb$\xb8%\xf1\xa2\x15\xf9\x9d\x85\xf7E\x89lh\xcc\u041b\x02,\x00\x00\u07d4p\x8a*\xf4%\u03b0\x1e\x87\xff\xc1\xbeT\xc0\xf52\xb2\x0e\xac\u0589\aE\u0503\xb1\xf5\xa1\x80\x00\u07d4p\x8e\xa7\a\xba\xe45\u007f\x1e\xbe\xa9Y\u00e2P\xac\u05aa!\xb3\x89\x1b\x1a\xe4\xd6\xe2\xefP\x00\x00\u0794p\x8f\xa1\x1f\xe3=\x85\xad\x1b\xef\u02ee8\x18\xac\xb7\x1fj}~\x88\xfc\x93c\x92\x80\x1c\x00\x00\u07d4p\x9101\x16\xd5\xf28\x9b##\x8bMej\x85\x96\u0644\u04c9;N~\x80\xaaX3\x00\x00\u07d4p\x99\xd1/n\xc6V\x89\x9b\x04\x9avW\x06]b\x99h\x92\u0209\x15\xaf\x1dx\xb5\x8c@\x00\x00\u07d4p\x9f\xe9\xd2\xc1\xf1\xceB |\x95\x85\x04J`\x89\x9f5\x94/\x89lk\x93[\x8b\xbd@\x00\x00\u07d4p\xa05I\xaaah\xe9~\x88\xa5\b3\nZ\v\xeatq\x1a\x89Hz\x9a0E9D\x00\x00\u07d4p\xa4\x06}D\x8c\xc2]\xc8\xe7\x0ee\x1c\xea|\xf8N\x92\x10\x9e\x89\t\x8a}\x9b\x83\x14\xc0\x00\x00\u07d4p\xab4\xbc\x17\xb6o\x9c;c\xf1Q'O*r|S\x92c\x89lk\x93[\x8b\xbd@\x00\x00\u07d4p\xc2\x13H\x8a\x02\f<\xfb9\x01N\xf5\xbad\x04rK\u02a3\x89i*\xe8\x89p\x81\xd0\x00\x00\u07d4p\xd2^\xd2\u022d\xa5\x9c\b\x8c\xf7\r\xd2+\xf2\u06d3\xac\xc1\x8a\x899GEE\u4b7c\x00\x00\u07d4p\xe5\xe9\xdas_\xf0w$\x9d\u02da\xaf=\xb2\xa4\x8d\x94\x98\xc0\x8965\u026d\xc5\u07a0\x00\x00\u07d4p\xfe\xe0\x8b\x00\xc6\xc2\xc0J<b\\\x1f\xf7|\xaf\x1c2\xdf\x01\x89\n\u05ce\xbcZ\xc6 \x00\x00\u07d4q\x01\xbdy\x9eA\x1c\xde\x14\xbd\xfa\xc2[\x06z\u0210\xea\xb8\xe8\x89N\x9b\x8a\xaeH\xdeG\x00\x00\u07d4q\t\xdd\x01\x1d\x15\xf3\x12-\x9d:'X\x8c\x10\xd7wDP\x8b\x89lk\x93[\x8b\xbd@\x00\x00\xe0\x94q\v\x02t\xd7\x12\xc7~\b\xa5p}o>p\xc0\xce=\x92\u03ca\x01Z\xf1\u05cbX\xc4\x00\x00\x00\u0794q\v\xe8\xfd^)\x18F\x8b\u2abe\xa8\r\x82\x845\u05d6\x12\x88\xf4?\xc2\xc0N\xe0\x00\x00\u07d4q\x13]\x8f\x05\x96<\x90ZJ\a\x92)\t#Z\x89jR\ua262\xa1]\tQ\x9b\xe0\x00\x00\u07d4q\x1e\xcfw\xd7\x1b=\x0e\xa9\\\xe4u\x8a\xfe\u0379\xc11\a\x9d\x89)3\x1eeX\xf0\xe0\x00\x00\u07d4q!?\xca14\x04 N\u02e8q\x97t\x1a\xa9\xdf\xe9c8\x89\x03@\xaa\xd2\x1b;p\x00\x00\xe0\x94q+vQ\x02\x14\xdcb\x0fl:\x1d\u049a\xa2+\xf6\xd2\x14\xfb\x8a\x01EB\xba\x12\xa37\xc0\x00\x00\u07d4q/\xf77\n\x13\xed6\ts\xfe\u071f\xf5\xd2\xc9:P^\x9e\x89\u0556{\xe4\xfc?\x10\x00\x00\u07d4q3\x84:x\xd99\u019dD\x86\xe1\x0e\xbc{`*4\x9f\xf7\x89\x11\xd5\xca\xcc\xe2\x1f\x84\x00\x00\u07d4qH\xae\xf32a\xd8\x03\x1f\xac?q\x82\xff5\x92\x8d\xafT\u0649\xdeB\xee\x15D\u0750\x00\x00\u07d4qcu\x8c\xbblLR^\x04\x14\xa4\n\x04\x9d\xcc\xcc\xe9\x19\xbb\x89\n\u05ce\xbcZ\xc6 \x00\x00\u07d4qh\xb3\xbb\x8c\x16s!\u067d\xb0#\xa6\xe9\xfd\x11\xaf\u026f\u0649a\t=|,m8\x00\x00\u07d4qirN\xe7\"q\xc54\xca\xd6B\x0f\xb0N\xe6D\u02c6\xfe\x89\x16<+@\u06e5R\x00\x00\u07d4qj\xd3\xc3:\x9b\x9a\n\x18\x96sW\x96\x9b\x94\xee}*\xbc\x10\x89\x1a!\x17\xfeA*H\x00\x00\xe0\x94qk\xa0\x1e\xad*\x91'\x065\xf9_%\xbf\xaf-\xd6\x10\xca#\x8a\ty\xe7\x01 V\xaax\x00\x00\u07d4qmP\u0320\x1e\x93\x85\x00\xe6B\x1c\xc0p\xc3P|g\u04c7\x89lk\x93[\x8b\xbd@\x00\x00\u07d4qv,cg\x8c\x18\xd1\xc67\x8c\xe0h\xe6f8\x13\x15\x14~\x89lk\x93[\x8b\xbd@\x00\x00\u07d4qxL\x10Q\x17\xc1\xf6\x895y\u007f\xe1Y\xab\xc7NC\xd1j\x89l\x81\u01f3\x11\x95\xe0\x00\x00\xe0\x94qyro\\q\xae\x1bm\x16\xa6\x84(\x17Nk4\xb26F\x8a\x01\x8e\xa2P\t|\xba\xf6\x00\x00\xe0\x94q|\xf9\xbe\xab680\x8d\xed~\x19^\f\x86\x13-\x16?\xed\x8a\x032n\xe6\xf8e\xf4\"\x00\x00\u07d4q\x80\xb8>\xe5WC\x17\xf2\x1c\x80r\xb1\x91\u0615\xd4aS\u00c9\x18\xef\xc8J\xd0\u01f0\x00\x00\u07d4q\x94kq\x17\xfc\x91^\xd1\a8_B\u065d\xda\xc62I\u0089lk\x93[\x8b\xbd@\x00\x00\xe0\x94q\x9e\x89\x1f\xbc\xc0\xa3>\x19\xc1-\xc0\xf0 9\xca\x05\xb8\x01\u07ca\x01OU8F:\x1bT\x00\x00\u07d4q\xc7#\n\x1d5\xbd\u0581\x9e\u0539\xa8\x8e\x94\xa0\xeb\a\x86\u0749\uc80b5=$\x14\x00\x00\u07d4q\xd2\xccm\x02W\x8ce\xf7<W^v\u038f\xbc\xfa\xdc\xf3V\x89\x03\xec\xc0xh\x8aH\x00\x00\u07d4q\xd9INP\xc5\xddY\u0159\u06e3\x81\v\xa1u^e7\xf0\x89\xd8\xd7&\xb7\x17z\x80\x00\x00\u07d4q\xe3\x8f\xf5E\xf3\x0f\xe1L\xa8c\xd4\xf5)\u007f\u050cs\xa5\u0389\xc2\x12z\xf8X\xdap\x00\x00\u07d4q\xea[\x11\xad\x8d)\xb1\xa4\xcbg\xbfX\xcal\x9f\x9c3\x8c\x16\x89V\xbcu\xe2\xd61\x00\x00\x00\u07d4q\xec:\xec?\x8f\x92!\xf9\x14\x9f\xed\xe0i\x03\xa0\xf9\xa22\xf2\x89\n\u05ce\xbcZ\xc6 \x00\x00\u07d4q\xf2\xcd\u0470F\xe2\xda/\xbbZ&r4\"\xb82^%\xa3\x89\x05k9Bc\xa4\f\x00\x00\u07d4q\xfa\"\xccm3 k}p\x1a\x16:\r\xab1\xaeM1\u0589WG=\x05\u06ba\xe8\x00\x00\u07d4r\x01\xd1\xc0i \xcd9z\u8b46\x9b\u0366\xe4\u007f\xfb\x1bZ\x89\x01\x15\x8eF\t\x13\xd0\x00\x00\u07d4r\a*\x0e\xf1\xcf\xf3\xd5g\xcd\xd2`\xe7\b\xdd\xc1\x1c\xbc\x9a1\x89\x05k\xc7^-c\x10\x00\x00\xe0\x94r\tO9Q\xff\xc9w\x1d\xce\xd2:\xda\b\v\xca\xf9\xc7\u0327\x8a\x01EB\xba\x12\xa37\xc0\x00\x00\xe0\x94r\t\x94\xdb\xe5j:\x95\x92\x97t\xe2\x0e\x1f\xe5%\xcf7\x04\xe4\x8a\x01\xb1\xaeMn.\xf5\x00\x00\x00\u07d4r\x0ek\"\xbfC\tf\xfa2\xb6\xac\xb9\xa5\x06\xee\xbff,a\x89\b=lz\xabc`\x00\x00\xe0\x94r\x11X\xbeWb\xb1\x19\u031b 5\xe8\x8e\xe4\xeex\U0009b08a\x02\x1e\x19\xe0\u027a\xb2@\x00\x00\u07d4r\x1f\x9d\x17\xe5\xa0\xe7B\x05\x94z\xeb\x9b\u01a7\x93\x89a\x03\x8f\x89\x02\xd0A\xd7\x05\xa2\xc6\x00\x00\u07d4r\"\xfe\xc7q\x17\x81\xd2n\xaaN\x84\x85\xf7\xaa?\xacD$\x83\x89\x18\xb8Ep\x02* \x00\x00\u07d4r9=7\xb4Q\xef\xfb\x9e\x1f\xf3\xb8U'\x12\xe2\xa9p\xd8\u00895e\x9e\xf9?\x0f\xc4\x00\x00\u07d4r=\x8b\xaa%Q\u04ad\xdcC\xc2\x1bE\xe8\xafL\xa2\xbf\xb2\u0089_h\xe8\x13\x1e\u03c0\x00\x00\xe0\x94r@#\x00\xe8\x1d\x14l.dN+\xbd\xa1\xda\x16<\xa3\xfbV\x8a\x01{x\x83\xc0i\x16`\x00\x00\xe0\x94rH\v\xed\xe8\x1a\xd9d#\xf2\"\x8b\\a\xbeD\xfbR1\x00\x8a\x01Z\xf1\u05cbX\xc4\x00\x00\x00\u07d4rL\xe8X\x85~\xc5H\x1c\x86\xbd\x90n\x83\xa0H\x82\xe5\x82\x1d\x89\xa2\xa1]\tQ\x9b\xe0\x00\x00\xe0\x94rj\x14\xc9\x0e?\x84\x14Lv\\\xff\xac\xba>\r\xf1\x1bH\xbe\x8a\x02\x1e\x19\xe0\u027a\xb2@\x00\x00\u07d4r\x83\xcdFu\xdaX\u0116UaQ\xda\xfd\x80\xc7\xf9\x95\xd3\x18\x89)3\x1eeX\xf0\xe0\x00\x00\u07d4r\x86\xe8\x9c\xd9\u078fz\x8a\x00\xc8o\xfd\xb59\x92\u0752Q\u0449i*\xe8\x89p\x81\xd0\x00\x00\u07d4r\x8f\x9a\xb0\x80\x15}\xb3\a1V\xdb\xca\x1a\x16\x9e\xf3\x17\x94\a\x89\x1b\x1a\xe4\xd6\xe2\xefP\x00\x00\u07d4r\x94\xc9\x18\xb1\xae\xfbM%\x92~\xf9\u05d9\xe7\x1f\x93\xa2\x8e\x85\x89\n\xad\xec\x98?\xcf\xf4\x00\x00\xe0\x94r\x94\uc763\x10\xbckK\xbd\xf5C\xb0\xefE\xab\xfc>\x1bM\x8a\x04\xa8\x9fT\xef\x01!\xc0\x00\x00\u07d4r\x9a\xadF'tNS\xf5\xd6c\t\xaatD\x8b:\xcd\xf4o\x89lk\x93[\x8b\xbd@\x00\x00\u07d4r\xa2\xfc\x86u\xfe\xb9r\xfaA\xb5\r\xff\u06fa\xe7\xfa*\u07f7\x89\x9a\xb4\xfcg\xb5(\xc8\x00\x00\u07d4r\xa8&\b&)G&\xa7[\xf3\x9c\u066a\x9e\a\xa3\xea\x14\u0349lk\x93[\x8b\xbd@\x00\x00\u07d4r\xb0Yb\xfb*\u0549\xd6Z\xd1j\"U\x9e\xba\x14X\xf3\x87\x89\a?u\u0460\x85\xba\x00\x00\u07d4r\xb5c?\xe4w\xfeT.t/\xac\xfdi\f\x13xT\xf2\x16\x89Z\x87\xe7\xd7\xf5\xf6X\x00\x00\u07d4r\xb7\xa0=\xda\x14\u029cf\x1a\x1dF\x9f\xd376\xf6s\xc8\xe8\x89lk\x93[\x8b\xbd@\x00\x00\u07d4r\xb9\x04D\x0e\x90\xe7 \u05ac\x1c*\u05dc2\x1d\xcc\x1c\x1a\x86\x89T\x06\x923\xbf\u007fx\x00\x00\xe0\x94r\xb9\nM\xc0\x97#\x94\x92\u0179w}\xcd\x1eR\xba+\xe2\u008a\x01EB\xba\x12\xa37\xc0\x00\x00\u07d4r\xbb'\u02d9\xf3\xe2\xc2\u03d0\xa9\x8fp}0\xe4\xa2\x01\xa0q\x89X\xe7\x92n\xe8X\xa0\x00\x00\xe0\x94r\xc0\x83\xbe\xad\xbd\xc2'\xc5\xfbC\x88\x15\x97\xe3.\x83\xc2`V\x8a\x04<3\xc1\x93ud\x80\x00\x00\u07d4r\xcd\x04\x8a\x11\x05tH)\x83I-\xfb\x1b\xd2yB\xa6\x96\xba\x89lk\x93[\x8b\xbd@\x00\x00\u07d4r\xd0=M\xfa\xb3P\f\xf8\x9b\x86\x86o\x15\xd4R\x8e\x14\xa1\x95\x89\xf3K\x82\xfd\x8e\x91 \x00\x00\u07d4r\u06bb[n\ud799\xbe\x91X\x88\xf6V\x80V8\x16\b\xf8\x89\vL\x96\xc5,\xb4\xfe\x80\x00\u07d4r\xfbI\u009d#\xa1\x89P\u0132\xdc\r\xdfA\x0fS-oS\x89lk\x93[\x8b\xbd@\x00\x00\u07d4r\xfe\xaf\x12EyR9Td[\u007f\xaf\xff\x03x\xd1\xc8$.\x8965\u026d\xc5\u07a0\x00\x00\u07d4s\x01\xdcL\xf2mq\x86\xf2\xa1\x1b\xf8\xb0\x8b\xf2)F?d\xa3\x89lk\x93[\x8b\xbd@\x00\x00\u07d4s\x04G\xf9|\xe9\xb2_\"\xba\x1a\xfb6\xdf'\xf9Xk\ub6c9,s\xc97t,P\x00\x00\u07d4s\x06\xde\x0e(\x8bV\xcf\u07d8~\xf0\xd3\xcc)f\a\x93\xf6\u0749\x1b\x8a\xbf\xb6.\xc8\xf6\x00\x00\xe0\x94s\r\x87c\u01a4\xfd\x82J\xb8\xb8Y\x16\x1e\xf7\xe3\xa9j\x12\x00\x8a\x04<3\xc1\x93ud\x80\x00\x00\u07d4s\x12\x81sH\x95(\x01.v\xb4\x1a^(\u018b\xa4\xe3\xa9\u050965\u026d\xc5\u07a0\x00\x00\u07d4s\x13F\x12\bETUFTE\xa4Y\xb0l7s\xb0\xeb0\x89lk\x93[\x8b\xbd@\x00\x00\u07d4s/\xea\xd6\x0f{\xfd\u05a9\xde\u0101%\xe3s]\xb1\xb6eO\x89\x01\x15\x8eF\t\x13\xd0\x00\x00\u07d4sB#\xd2\u007f\xf2>Y\x06\xca\xed\"YW\x01\xbb4\x83\f\xa1\x89lk\x93[\x8b\xbd@\x00\x00\u07d4sG>r\x11Q\x10\xd0\xc3\xf1\x17\b\xf8nw\xbe+\xb0\x98<\x89\x01\x15\x8eF\t\x13\xd0\x00\x00\u07d4sRXm\x02\x1a\xd0\xcfw\xe0\xe9(@JY\xf3t\xffE\x82\x89\xb8Pz\x82\a( \x00\x00\u07d4sU\v\xebs+\xa9\u076f\xdaz\xe4\x06\xe1\x8f\u007f\xeb\x0f\x8b\xb2\x89\x97\xc9\xceL\xf6\xd5\xc0\x00\x00\u07d4s[\x97\xf2\xfc\x1b\xd2K\x12\an\xfa\xf3\xd1(\x80s\xd2\f\x8c\x89\x01\x15\x8eF\t\x13\xd0\x00\x00\u07d4s^2\x86f\xedV7\x14+3\x06\xb7|\xccT`\xe7,=\x89j\xb8\xf3xy\u0251\x00\x00\u07d4sc\u0350\xfb\xab[\xb8\u011a\xc2\x0f\xc6,9\x8f\xe6\xfbtL\x89lk\x93[\x8b\xbd@\x00\x00\u07d4skDP=\xd2\xf6\xddTi\xffL[-\xb8\xeaO\xece\u0409\x11\x04\xeeu\x9f!\xe3\x00\x00\xe0\x94sk\xf1@,\x83\x80\x0f\x89>X1\x92X*\x13N\xb52\xe9\x8a\x02\x1e\x19\u0493\xc0\x1f&\x00\x00\xe0\x94s\x8c\xa9M\xb7\u038b\xe1\xc3\x05l\u0598\x8e\xb3v5\x9f3S\x8a\x05f[\x96\xcf5\xac\xf0\x00\x00\u07d4s\x91K\"\xfc/\x13\x15\x84$}\x82\xbeO\ucfd7\x8a\u053a\x89lk\x93[\x8b\xbd@\x00\x00\u07d4s\x93'\t\xa9\u007f\x02\u024eQ\xb0\x911(e\x12#\x85\xae\x8e\x89M\x85<\x8f\x89\b\x98\x00\x00\u07d4s\x93\xcb\xe7\xf9\xba!e\xe5\xa7U5\x00\xb6\xe7]\xa3\xc3:\xbf\x89\x05k\xc7^-c\x10\x00\x00\u07d4s\xb4\u0519\xde?8\xbf5\xaa\xf7i\xa6\xe3\x18\xbcm\x126\x92\x89lk\x93[\x8b\xbd@\x00\x00\xe0\x94s\xbe\xddo\xda{\xa3'!\x85\b{cQ\xfc\x13=HN7\x8a\x01\x12&\xbf\x9d\xceYx\x00\x00\u07d4s\xbf\xe7q\x0f1\u02b9I\xb7\xa2`O\xbfR9\xce\xe7\x90\x15\x89lk\x93[\x8b\xbd@\x00\x00\xe0\x94s\u03c0\xae\x96\x88\xe1X\x0eh\xe7\x82\xcd\b\x11\xf7\xaaIM,\x8a\x01\xa4\xab\xa2%\xc2\a@\x00\x00\xe0\x94s\xd7&\x9f\xf0l\x9f\xfd3uL\xe5\x88\xf7J\x96j\xbb\xbb\xba\x8a\x01e\xc9fG\xb3\x8a \x00\x00\u07d4s\xd8\xfe\xe3\u02c6M\xce\"\xbb&\u029c/\bm^\x95\xe6;\x8965\u026d\xc5\u07a0\x00\x00\u07d4s\xdf<>yU\xf4\xf2\xd8Y\x83\x1b\xe3\x80\x00\xb1\ak8\x84\x89j\xcb=\xf2~\x1f\x88\x00\x00\u07d4s\u48b6\f\U0010e2ef+w~\x17Z[\x1eM\f-\x8f\x89\x05k\xc7^-c\x10\x00\x00\xe0\x94t\n\xf1\xee\xfd3e\u05cb\xa7\xb1,\xb1\xa6s\xe0j\arF\x8a\x04+\xf0kx\xed;P\x00\x00\xe0\x94t\v\xfdR\xe0\x16g\xa3A\x9b\x02\x9a\x1b\x8eEWj\x86\xa2\u06ca\x03\x8e\xba\xd5\xcd\xc9\x02\x80\x00\x00\u07d4t\x0fd\x16\x14w\x9d\u03e8\x8e\xd1\xd4%\xd6\r\xb4*\x06\f\xa6\x896\"\xc6v\b\x10W\x00\x00\u07d4t\x12\u027c0\xb4\xdfC\x9f\x021\x00\xe69$\x06j\xfdS\xaf\x89\x1b\x1a\xe4\xd6\xe2\xefP\x00\x00\u07d4t\x16\x93\xc3\x03vP\x85\x13\b \xcc+c\xe9\xfa\x92\x13\x1b\x89A\rXj \xa4\xc0\x00\x00\u07d4t!\xce[\xe3\x81s\x8d\u0703\xf0&!\x97O\xf0hly\xb8\x89Xx\x8c\xb9K\x1d\x80\x00\x00\u07d4t1j\xdf%7\x8c\x10\xf5v\u0574\x1aoG\xfa\x98\xfc\xe3=\x89\x128\x13\x1e\\z\xd5\x00\x00\u07d4t6Q\xb5^\xf8B\x9d\xf5\f\xf8\x198\xc2P\x8d\xe5\u0207\x0f\x89lk\x93[\x8b\xbd@\x00\x00\u07d4t=\xe5\x00&\xcag\xc9M\xf5O\x06b`\xe1\xd1J\xcc\x11\xac\x89lk\x93[\x8b\xbd@\x00\x00\u07d4tE /\ft)z\x00N\xb3rj\xa6\xa8-\xd7\xc0/\xa1\x89lk\x93[\x8b\xbd@\x00\x00\u07d4tK\x03\xbb\xa8X*\xe5I\x8e-\xc2-\x19\x94\x94g\xabS\xfc\x89\x1b\x1a\xe4\xd6\xe2\xefP\x00\x00\u07d4tL\fw\xba\u007f#i \xd1\xe44\xde]\xa3>H\xeb\xf0,\x89j\xcb=\xf2~\x1f\x88\x00\x00\u07d4tP\xff\u007f\x99\xea\xa9\x11bu\u07ach\xe4(\xdf[\xbc\u0639\x89lk\x93[\x8b\xbd@\x00\x00\u07d4tV\u0172\xc5Cn>W\x10\b\x93?\x18\x05\xcc\xfe4\xe9\xec\x8965\u026d\xc5\u07a0\x00\x00\u07d4tZ\u04eb\xc6\xee\xeb$qh\x9bS\x9ex\x9c\xe2\xb8&\x83\x06\x89=A\x94\xbe\xa0\x11\x92\x80\x00\xe0\x94tZ\xec\xba\xf9\xbb9\xb7Jg\xea\x1c\xe6#\xde6\x84\x81\xba\xa6\x8a\x02\x1e\x19\xe0\u027a\xb2@\x00\x00\u07d4t\\\xcf-\x81\x9e\u06fd\u07a8\x11{\\I\xed<*\x06n\x93\x89\xd8\xd7&\xb7\x17z\x80\x00\x00\u07d4tb\u021c\xaa\x9d\x8dx\x91\xb2T]\xef!otd\u057b!\x89\x05\xea\xedT\xa2\x8b1\x00\x00\u07d4td\x8c\xaa\xc7H\xdd\x13\\\xd9\x1e\xa1L(\xe1\xbdM\u007f\xf6\xae\x89\xa8\r$g~\xfe\xf0\x00\x00\xe0\x94tq\xf7.\xeb0\x06$\xeb(.\xabM\x03r<d\x9b\x1bX\x8a\x01\xb1\xaeMn.\xf5\x00\x00\x00\xe0\x94tz\xbc\x96I\x05m9&\x04M(\u00ed\t\xed\x17\xb6}p\x8a\x01\x0f\r\xba\xe6\x10\tR\x80\x00\u07d4t\u007f\xf7\x94;q\xdcM\u0371f\x80x\xf8=\xd7\xccE \u0089\x03@\xaa\xd2\x1b;p\x00\x00\xe0\x94t\x80\xdeb%O+\xa8+W\x82\x19\xc0{\xa5\xbeC\r\xc3\u02ca\x01}\xa3\xa0L{>\x00\x00\x00\xe0\x94t\x84\xd2k\xec\xc1\xee\xa8\xc61^\xc3\xee\nE\x01\x17\u0706\xa0\x8a\x02\x8a\x85t%Fo\x80\x00\x00\u07d4t\x86:\xce\xc7]\x03\xd5>\x86\x0ed\x00/,\x16^S\x83w\x8965\u026d\xc5\u07a0\x00\x00\u07d4t\x89\u030a\xbeu\u0364\xef\r\x01\xce\xf2`^G\xed\xa6z\xb1\x89\a?u\u0460\x85\xba\x00\x00\u07d4t\x8c(^\xf1#?\xe4\xd3\x1c\x8f\xb17\x833r\x1c\x12\xe2z\x89lk\x93[\x8b\xbd@\x00\x00\u07d4t\x90\x87\xac\x0fZ\x97\xc6\xfa\xd0!S\x8b\xf1\xd6\u0361\x8e\r\xaa\x8965\u026d\xc5\u07a0\x00\x00\u07d4t\x95\xaex\xc0\xd9\x02a\xe2\x14\x0e\xf2\x061\x04s\x1a`\xd1\xed\x89\x01\xdbPq\x89%!\x00\x00\u07d4t\x9aJv\x8b_#rH\x93\x8a\x12\xc6#\x84{\xd4\xe6\x88\u0709\x03\xe73b\x87\x14 \x00\x00\u07d4t\x9a\xd6\xf2\xb5pk\xbe/h\x9aD\u0136@\xb5\x8e\x96\xb9\x92\x89\x05k\xc7^-c\x10\x00\x00\u07d4t\xa1\u007f\x06K4N\x84\xdbce\u0695\x91\xff\x16(%vC\x89\x01\x15\x8eF\t\x13\xd0\x00\x00\u07d4t\xae\xec\x91]\xe0\x1c\u019b,\xb5\xa65o\xee\xa1FX\xc6\u0149\f\x9a\x95\xee)\x86R\x00\x00\u07d4t\xaf\xe5I\x02\xd6\x15x%v\xf8\xba\xac\x13\xac\x97\f\x05\x0fn\x89\t\xa1\xaa\xa3\xa9\xfb\xa7\x00\x00\u07d4t\xb7\xe0\"\x8b\xae\xd6YW\xae\xbbM\x91m3:\xae\x16O\x0e\x89lk\x93[\x8b\xbd@\x00\x00\u07d4t\xbcJ^ E\xf4\xff\x8d\xb1\x84\xcf:\x9b\f\x06Z\xd8\a\u0489lk\x93[\x8b\xbd@\x00\x00\u07d4t\xbc\xe9\xec86-l\x94\u032c&\xd5\xc0\xe1:\x8b;\x1d@\x8965&A\x04B\xf5\x00\x00\u07d4t\xbfzZ\xb5\x92\x93\x14\x9b\\`\xcf6Bc\xe5\xeb\xf1\xaa\r\x89\x06G\f>w\x1e<\x00\x00\xe0\x94t\xc7<\x90R\x8a\x15s6\xf1\xe7\xea b\n\xe5?\xd2G(\x8a\x01\xe6:.S\x8f\x16\xe3\x00\x00\u07d4t\u0464\xd0\xc7RN\x01\x8dN\x06\xed;d\x80\x92\xb5\xb6\xaf,\x89\x02\xb5\xe3\xaf\x16\xb1\x88\x00\x00\xe0\x94t\xd3f\xb0{/VG}|pw\xaco\xe4\x97\xe0\xebeY\x8a\x01\x0f\f\xf0d\xddY \x00\x00\u07d4t\xd3zQt{\xf8\xb7q\xbf\xbfC\x9493\xd1\x00\xd2\x14\x83\x8965\u026d\xc5\u07a0\x00\x00\u07d4t\xd6q\u065c\xbe\xa1\xabW\x90cu\xb6?\xf4+PE\x1d\x17\x8965\u026d\xc5\u07a0\x00\x00\u07d4t\xeb\xf4BVF\xe6\u03c1\xb1\t\xce{\xf4\xa2\xa6=\x84\x81_\x89\x02+\x1c\x8c\x12'\xa0\x00\x00\u07d4t\xed3\xac\xf4?5\xb9\x8c\x920\xb9\xe6d.\xcbS0\x83\x9e\x89$\xf6\xdf\xfbI\x8d(\x00\x00\u07d4t\xef(i\xcb\xe6\b\x85`E\xd8\xc2\x04\x11\x18W\x9f\"6\xea\x89\x03<\xd6E\x91\x95n\x00\x00\u07d4t\xfcZ\x99\xc0\xc5F\x05\x03\xa1;\x05\tE\x9d\xa1\x9c\xe7\u0350\x89\n\u05ce\xbcZ\xc6 \x00\x00\u07d4u\v\xbb\x8c\x06\xbb\xbf$\bC\xccux.\xe0/\b\xa9tS\x89-C\xf3\xeb\xfa\xfb,\x00\x00\u07d4u\x14\xad\xbd\xc6?H?0M\x8e\x94\xb6\u007f\xf30\x9f\x18\v\x82\x89!\u0120n-\x13Y\x80\x00\u0794u\x17\xf1l(\xd12\xbb@\xe3\xba6\u01ae\xf11\xc4b\xda\x17\x88\xfc\x93c\x92\x80\x1c\x00\x00\u07d4u\x1a,\xa3Nq\x87\xc1c\u048e6\x18\xdb(\xb1<\x19m&\x89\x1b\x1a\xe4\xd6\xe2\xefP\x00\x00\xe0\x94u\x1a\xbc\xb6\xcc\x030Y\x91\x18\x15\xc9o\u04516\n\xb0D-\x8a\x01\xb1\xaeMn.\xf5\x00\x00\x00\u07d4u&\xe4\x82R\x9f\n\x14\xee\u0248q\xdd\xdd\x0er\x1b\f\u0662\x89\x01\x15\x8eF\t\x13\xd0\x00\x00\u07d4u)\xf3y{\xb6\xa2\x0f~\xa6I$\x19\xc8L\x86vA\xd8\x1c\x89lk\x93[\x8b\xbd@\x00\x00\xe0\x94u*^\xe22a,\xd3\x00_\xb2n[Y}\xe1\x9fwk\xe6\x8a\x01'\xfc\xb8\xaf\xae \xd0\x00\x00\u07d4u,\x9f\xeb\xf4/f\xc4x{\xfa~\xb1|\xf53;\xbaPp\x89j\x99\xf2\xb5O\xddX\x00\x00\u07d4u930F\u07b1\xef<M\xafPa\x99\x93\xf4D\xe1\xdeh\x89@\x13\x8b\x91~\u07f8\x00\x00\u07d4uS\xaa#\xb6\x8a\xa5\xf5~\x13_\xe3\x9f\xdc#^\xac\xa8\u024c\x8965\u026d\xc5\u07a0\x00\x00\xe0\x94uZ`\xbfR/\xbd\x8f\xff\x97#Dk~4:phV~\x8a\x04<3\xc1\x93ud\x80\x00\x00\u07d4u_X~^\xff\xf7s\xa2 rj\x13\xd0\xf2\x13\r\x9f\x89k\x8965\u026d\xc5\u07a0\x00\x00\u07d4ub\x18e\xb6Y\x13e`n\xd3x0\x8c-\x1d\xefO\",\x89\xa8\r$g~\xfe\xf0\x00\x00\xe0\x94ucl\xdb\x10\x90P\xe4=]n\xc4~5\x9e!\x8e\x85~\u028a\x04\u0632'l\x89b(\x00\x00\u07d4ufIab\xbaXCw\xbe\x04\nO\x87wzpz\xca\xeb\x89\xd8\xd7&\xb7\x17z\x80\x00\x00\u07d4uk\x84\xeb\x85\xfc\xc1\xf4\xfc\xdc\u00b0\x8d\xb6\xa8n\x13_\xbc%\x89\xae\x8ez\v\xb5u\xd0\x00\x00\u07d4uoE\xe3\xfai4z\x9a\x97:r^<\x98\xbcM\xb0\xb5\xa0\x89\n\u05ce\xbcZ\xc6 \x00\x00\u07d4u{e\x87m\xbf)\xbf\x91\x1dO\x06\x92\xa2\u027e\xb1\x13\x98\b\x89\u07d3\xa5\x937\xd6\u0740\x00\u07d4u\u007f\xa5TF\xc4`\x96\x8b\xb7K^\xbc\xa9lN\xf2\xc7\t\u01497\b\xba\xed=h\x90\x00\x00\u07d4u\x80J\xacd\xb4\x19\x90\x83\x98)\x02\x99M\x9c^\u0602\x8f\x11\x89\x1e=\a\xb0\xa6 \xe4\x00\x00\u07d4u\x92\u019d\x06{Q\xb6\xccc\x9d\x11d\xd5W\x8c`\xd2\xd2D\x89\x01\x15\x8eF\t\x13\xd0\x00\x00\u07d4u\xab\xe5'\x0f:x\xce\x00|\xf3\u007f\x8f\xbc\x04]H\x9b{\xb1\x89lj\xccg\u05f1\xd4\x00\x00\xe0\x94u\xacTp\x17\x13L\x04\xae\x1e\x11\xd6\x0ec\xec\x04\u044d\xb4\xef\x8a\x01EB\xba\x12\xa37\xc0\x00\x00\u07d4u\xb0\xe9\xc9B\xa4\xf0\xf6\xf8m?\x95\xff\x99\x80\"\xfag\x96;\x89P\xc5\xe7a\xa4D\b\x00\x00\xe0\x94u\xb9V\x96\xe8\xecE\x10\xd5hh\xa7\xc1\xa75\u018b$H\x90\x8a\x01Z\xf1\u05cbX\xc4\x00\x00\x00\u07d4u\xbe\x8f\xf6^W\x88\xae\u01b2\xa5-_\xa7\xb1\xe7\xa0;\xa6u\x89\x03\xab\xcd\xc54=t\x00\x00\u07d4u\xc1\x1d\x02M\x12\xaeHl\x10\x95\xb7\xa7\xb9\u012f>\x8e\u07b9\x89\x01\x15\x8eF\t\x13\xd0\x00\x00\xe0\x94u\xc1\xad#\xd2?$\xb3\x84\xd0\xc3\x14\x91w\xe8f\x97a\r!\x8a\x01\\[\xcdl(\x8b\xbd\x00\x00\u07d4u\xc2\xff\xa1\xbe\xf5I\x19\xd2\t\u007fz\x14-.\x14\xf9\xb0JX\x89\x90\xf3XP@2\xa1\x00\x00\u07d4u\xd6|\xe1N\x8d)\xe8\xc2\xff\u3051{\x93\v\x1a\xff\x1a\x87\x89\xa2\xa1]\tQ\x9b\xe0\x00\x00\u07d4u\xde~\x93R\xe9\v\x13\xa5\x9aXx\xff\xec\u01c3\x1c\xacM\x82\x89\x94\x89#z\u06daP\x00\x00\u07d4u\xf7S\x9d0\x9e\x909\x98\x9e\xfe.\x8b-\xbd\x86Z\r\xf0\x88\x89\x85[[\xa6\\\x84\xf0\x00\x00\u07d4v\b\xf47\xb3\x1f\x18\xbc\vd\u04c1\xae\x86\xfd\x97\x8e\u05f3\x1f\x89\x02\xb5\xe3\xaf\x16\xb1\x88\x00\x00\xe0\x94v\x0f\xf35N\x0f\u0793\x8d\x0f\xb5\xb8,\xef[\xa1\\=)\x16\x8a\x02\x1e\x19\xe0\u027a\xb2@\x00\x00\u07d4v\x1an6,\x97\xfb\xbd|Yw\xac\xba-\xa7F\x876_I\x89\t\xf7J\xe1\xf9S\xd0\x00\x00\u07d4v\x1el\xae\xc1\x89\xc20\xa1b\xec\x00e0\x19>g\u03dd\x19\x89lk\x93[\x8b\xbd@\x00\x00\xe0\x94v\x1f\x8a:*\U00028f7e\x1d\xa0\t2\x1f\xb2\x97d\xebb\xa1\x8a\x02\x1e\x19\xe0\u027a\xb2@\x00\x00\u07d4v)\x98\xe1\xd7R'\xfc\xedzp\xbe\x10\x9aL\vN\xd8d\x14\x89\x01\x15\x8eF\t\x13\xd0\x00\x00\u07d4v-o0\u06b9\x915\xe4\xec\xa5\x1dRC\xd6\xc8b\x11\x02\u0549\x0fI\x89A\xe6d(\x00\x00\u07d4v3\x1e0yl\xe6d\xb2p\x0e\rASp\x0e\u0706\x97w\x89lk\x93[\x8b\xbd@\x00\x00\u07d4v8\x86\xe33\xc5o\xef\xf8[\xe3\x95\x1a\xb0\xb8\x89\xce&.\x95\x89lk\x93[\x8b\xbd@\x00\x00\u07d4v:|\xba\xb7\rzd\u0427\xe5)\x80\xf6\x81G%\x93I\f\x89 \x86\xac5\x10R`\x00\x00\u07d4v>\xec\u0c0a\u021e2\xbf\xa4\xbe\xcev\x95\x14\xd8\xcb[\x85\x89\xd8\xd7&\xb7\x17z\x80\x00\x00\u07d4v@\xa3\u007f\x80R\x98\x15\x15\xbc\xe0x\u0693\xaf\xa4x\x9bW4\x89lk\x93[\x8b\xbd@\x00\x00\u0794vA\xf7\xd2j\x86\xcd\xdb+\xe10\x81\x81\x0e\x01\xc9\xc8<K \x88\xb9\x8b\xc8)\xa6\xf9\x00\x00\u07d4vF\x92\xcc\xcb3@]\u042b\f3y\xb4\x9c\xaf\x8eb!\xba\x89\x01\x15\x8eF\t\x13\xd0\x00\x00\u07d4vMR\x12&:\xffJ*\x14\xf01\xf0N\xc7I\u0708>E\x89dI\xe8NG\xa8\xa8\x00\x00\xe0\x94vO\xc4mB\x8bm\xbc\"\x8a\x0f_U\xc9P\x8cw.\xab\x9f\x8a\x05\x81v{\xa6\x18\x9c@\x00\x00\u07d4vPn\xb4\xa7\x80\xc9Q\xc7J\x06\xb0=;\x83b\xf0\x99\x9dq\x89\x1b\x1a\xe4\xd6\xe2\xefP\x00\x00\xe0\x94v[\xe2\xe1/b\x9ecI\xb9}!\xb6*\x17\xb7\xc80\xed\xab\x8a\x01EB\xba\x12\xa37\xc0\x00\x00\xe0\x94vb\x81P\xe2\x99[['\x9f\xc8>\r\xd5\xf1\x02\xa6q\xdd\x1c\x8a\bxg\x83&\xea\xc9\x00\x00\x00\u07d4vk7Y\xe8yN\x92m\xacG=\x91:\x8f\xb6\x1a\xd0\xc2\u0249\x04\xb0m\xbb\xb4\x0fJ\x00\x00\u07d4vp\xb0/,<\xf8\xfdOG0\xf38\x1aq\xeaC\x1c3\u01c9\x0e~\xeb\xa3A\vt\x00\x00\u07d4vz\x03eZ\xf3`\x84\x1e\x81\r\x83\xf5\xe6\x1f\xb4\x0fL\xd1\x13\x895e\x9e\xf9?\x0f\xc4\x00\x00\u07d4vz\u0190y\x1c.#E\x10\x89\xfelp\x83\xfeU\u07b6+\x89,s\xc97t,P\x00\x00\u07d4v\u007f\xd7y}Qi\xa0_sd2\x1c\x19\x84:\x8c4\x8e\x1e\x89\x01\x04\xe7\x04d\xb1X\x00\x00\u0794v\x84o\r\xe0;Zv\x97\x1e\xad)\x8c\xdd\b\x84:K\xc6\u0188\xd7\x1b\x0f\u088e\x00\x00\xe0\x94v\x84\x98\x93N7\xe9\x05\xf1\xd0\xe7{D\xb5t\xbc\xf3\xecJ\xe8\x8a\x04<3\xc1\x93ud\x80\x00\x00\u07d4v\x8c\xe0\u06a0)\xb7\xde\xd0\"\xe5\xfcWM\x11\xcd\xe3\xec\xb5\x17\x89\x11t\xa5\xcd\xf8\x8b\xc8\x00\x00\xe0\x94v\x93\xbd\xebo\xc8+[\xcar\x13U\"1u\xd4z\bKM\x8a\x04\xa8\x9fT\xef\x01!\xc0\x00\x00\u07d4v\xaa\xf8\xc1\xac\x01/\x87R\xd4\xc0\x9b\xb4f\a\xb6e\x1d\\\xa8\x89\x01\x15\x8eF\t\x13\xd0\x00\x00\u07d4v\xab\x87\xddZ\x05\xad\x83\x9aN/\xc8\xc8Z\xa6\xba\x05d\x170\x89lk\x93[\x8b\xbd@\x00\x00\u07d4v\xaf\xc2%\xf4\xfa0}\xe4\x84U+\xbe\x1d\x9d?\x15\aLJ\x89\xa2\x90\xb5\u01ed9h\x00\x00\xe0\x94v\xbe\xca\xe4\xa3\x1d6\xf3\xcbW\u007f*CYO\xb1\xab\xc1\xbb\x96\x8a\x05C\xa9\xce\x0e\x132\xf0\x00\x00\u07d4v\xc2u5\xbc\xb5\x9c\xe1\xfa-\x8c\x91\x9c\xab\xebJk\xba\x01\u0449lk\x93[\x8b\xbd@\x00\x00\u07d4v\xca\"\xbc\xb8y\x9eS'\u012a*}\tI\xa1\xfc\xce_)\x89R\xa0?\"\x8cZ\xe2\x00\x00\u07d4v\xca\u0108\x11\x1aO\u0555\xf5h\xae:\x85\x87p\xfc\x91]_\x89\n\u05ce\xbcZ\xc6 \x00\x00\xe0\x94v\u02dc\x8bi\xf48vu\u0102S\xe24\xcb~\rt\xa4&\x8a\x01\x90\xf4H.\xb9\x1d\xae\x00\x00\u07d4v\xf8:\xc3\xda0\xf7\t&(\xc73\x9f \x8b\xfc\x14,\xb1\ue25a\x18\xff\xe7B}d\x00\x00\xe0\x94v\xf9\xad=\x9b\xbd\x04\xae\x05\\\x14w\xc0\xc3^u\x92\xcb* \x8a\b\x83?\x11\xe3E\x8f \x00\x00\u07d4v\xff\xc1W\xadk\xf8\xd5m\x9a\x1a\u007f\u077c\x0f\xea\x01\n\xab\xf4\x8965\u026d\xc5\u07a0\x00\x00\u07d4w\x02\x8e@\x9c\xc4:;\xd3=!\xa9\xfcS\xec`n\x94\x91\x0e\x89\xd2U\xd1\x12\xe1\x03\xa0\x00\x00\u07d4w\f/\xb2\u0128\x17S\xac\x01\x82\xeaF\x0e\xc0\x9c\x90\xa5\x16\xf8\x89\x01\x15\x8eF\t\x13\xd0\x00\x00\u07d4w\r\x98\xd3\x1bCS\xfc\xee\xe8V\fL\u03c0>\x88\xc0\xc4\xe0\x89 \x86\xac5\x10R`\x00\x00\xe0\x94w\x13\xab\x807A\x1c\t\xbah\u007fo\x93d\xf0\xd3#\x9f\xac(\x8a\x02\x1e\x19\xe0\u027a\xb2@\x00\x00\u07d4w\x15\a\xae\xeej%]\xc2\u035d\xf5QT\x06-\b\x97\xb2\x97\x89\x12\x1e\xa6\x8c\x11NQ\x00\x00\u07d4w\x19\x88\x87\x95\xadtY$\xc7W`\u0771\x82}\xff\xd8\u0368\x89lkLM\xa6\u077e\x00\x00\u07d4w'\xaf\x10\x1f\n\xab\xa4\xd2:\x1c\xaf\xe1|n\xb5\u06b1\xc6\u0709lk\x93[\x8b\xbd@\x00\x00\u07d4w,)\u007f\n\u0454H.\xe8\xc3\xf06\xbd\xeb\x01\xc2\x01\xd5\u0309\n\u05ce\xbcZ\xc6 \x00\x00\xe0\x94w0o\xfe.J\x8f<\xa8&\xc1\xa2I\xf7!-\xa4:\xef\xfd\x8a\x04<3\xc1\x93ud\x80\x00\x00\u07d4w1A\x12}\x8c\xf3\x18\xae\xbf\x886Z\xdd=U'\xd8[j\x8966\u05ef^\u024e\x00\x00\u07d4wF\xb6\xc6i\x9c\x8f4\xca'h\xa8 \xf1\xff\xa4\xc2\a\xfe\x05\x89\xd8\xd8X?\xa2\xd5/\x00\x00\u07d4wQ\xf3c\xa0\xa7\xfd\x053\x19\b\t\u076f\x93@\xd8\xd1\x12\x91\x89\x01\x15\x8eF\t\x13\xd0\x00\x00\u07d4wW\xa4\xb9\xcc=\x02G\u032a\xeb\x99\t\xa0\xe5n\x1d\xd6\xdc\u0089\x01\x15\x8eF\t\x13\xd0\x00\x00\u07d4w\\\x10\xc9>\r\xb7 [&CE\x823\xc6O\xc3?\xd7[\x89lk\x93[\x8b\xbd@\x00\x00\u07d4wa~\xbcK\xeb\xc5\xf5\xdd\xeb\x1bzp\xcd\xebj\xe2\xff\xa0$\x89j\xcb=\xf2~\x1f\x88\x00\x00\u07d4wiC\xff\xb2\xef\\\xdd5\xb8<(\xbc\x04k\xd4\xf4gp\x98\x89\xa2\xa1]\tQ\x9b\xe0\x00\x00\xe0\x94wp\x1e,I=\xa4|\x1bX\xf4!\xb5I]\xeeE\xbe\xa3\x9b\x8a\x01H\xf6I\xcfaB\xa5\x80\x00\u07d4wy\x8f \x12W\xb9\xc3R\x04\x95pW\xb5Ft\xae\xfaQ\u07c9\b\x13\xcaV\x90m4\x00\x00\u07d4w\x8cC\xd1\x1a\xfe;Xo\xf3t\x19-\x96\xa7\xf2=+\x9b\u007f\x89\x8b\xb4\xfc\xfa;}k\x80\x00\u07d4w\x8cy\xf4\xde\x19S\xeb\u0398\xfe\x80\x06\xd5:\x81\xfbQ@\x12\x8963\x03\"\xd5#\x8c\x00\x00\u07d4w\x92t\xbf\x18\x03\xa36\xe4\u04f0\r\u0753\xf2\xd4\xf5\xf4\xa6.\x8965\u026d\xc5\u07a0\x00\x00\u07d4w\xa1q\"\xfa1\xb9\x8f\x17\x11\xd3*\x99\xf0>\xc3&\xf3=\b\x89\\(=A\x03\x94\x10\x00\x00\u07d4w\xa3I\a\xf3\x05\xa5L\x85\xdb\t\xc3c\xfd\xe3\xc4~j\xe2\x1f\x895e\x9e\xf9?\x0f\xc4\x00\x00\u07d4w\xa7i\xfa\xfd\xec\xf4\xa68v-[\xa3\x96\x9d\xf61 \xa4\x1d\x89lk\x93[\x8b\xbd@\x00\x00\u07d4w\xbekd\xd7\xc73\xa46\xad\xec^\x14\xbf\x9a\xd7@+\x1bF\x8965\u026d\xc5\u07a0\x00\x00\u07d4w\xbf\xe9<\u0367P\x84~A\xa1\xaf\xfe\xe6\xb2\u0696\xe7!N\x89\x10CV\x1a\x88)0\x00\x00\u07d4w\u0126\x97\xe6\x03\xd4+\x12\x05l\xbb\xa7a\xe7\xf5\x1d\x04C\xf5\x89$\xdc\xe5M4\xa1\xa0\x00\x00\u07d4w\xcc\x02\xf6#\xa9\u03d8S\t\x97\xeag\xd9\\;I\x18Y\xae\x89Is\x03\xc3n\xa0\xc2\x00\x00\u07d4w\xd4?\xa7\xb4\x81\xdb\xf3\xdbS\f\xfb\xf5\xfd\xce\xd0\xe6W\x181\x89lk\x93[\x8b\xbd@\x00\x00\u07d4w\xda^lr\xfb6\xbc\xe1\xd9y\x8f{\xcd\xf1\u044fE\x9c.\x89\x016\x95\xbbl\xf9>\x00\x00\u07d4w\xf4\xe3\xbd\xf0V\x88<\xc8r\x80\xdb\xe6@\xa1\x8a\r\x02\xa2\a\x89\n\x81\x99:+\xfb[\x00\x00\u0794w\xf6\t\u0287 \xa0#&,U\xc4o-&\xfb90\xaci\x88\xf0\x15\xf2W6B\x00\x00\u07d4w\xf8\x1b\x1b&\xfc\x84\xd6\u0797\uf2df\xbdr\xa310\xccJ\x8965\u026d\xc5\u07a0\x00\x00\u07d4x\x19\xb0E\x8e1N+S\xbf\xe0\f8I_\u0539\xfd\xf8\u0589\x01\x15\x8eF\t\x13\xd0\x00\x00\u07d4x\x1b\x15\x01dz.\x06\xc0\xedC\xff\x19\u007f\xcc\xec5\xe1p\v\x89\xa2\xa1]\tQ\x9b\xe0\x00\x00\u07d4x/R\xf0\xa6v\xc7w\x16\xd5t\xc8\x1e\xc4hO\x9a\x02\n\x97\x89.\x14\xe2\x06\xb70\xad\x80\x00\u07d4x5]\xf0\xa20\xf8=\x03,p1TAM\xe3\xee\u06b5W\x89lk\x93[\x8b\xbd@\x00\x00\u07d4x6\xf7\xefk\u01fd\x0f\xf3\xac\xafD\x9c\x84\xddk\x1e,\x93\x9f\x89\xe0\x8d\xe7\xa9,\xd9|\x00\x00\u07d4x7\xfc\xb8v\xda\x00\xd1\xeb;\x88\xfe\xb3\xdf?\xa4\x04/\xac\x82\x89_h\xe8\x13\x1e\u03c0\x00\x00\u07d4x>\uc2a5\xda\xc7{.f#\xedQ\x98\xa41\xab\xba\xee\a\x89\x17\xda:\x04\u01f3\xe0\x00\x00\u07d4x\\\x8e\xa7t\xd70D\xa74\xfay\n\x1b\x1et>w\xed|\x89\f\xf1Rd\f\\\x83\x00\x00\u07d4x`\xa3\xde8\xdf8*\xe4\xa4\xdc\xe1\x8c\f\a\xb9\x8b\xce=\xfa\x8965\u026d\xc5\u07a0\x00\x00\xe0\x94xcCq\xe1s\x04\xcb\xf39\xb1E*L\xe48\xdcvL\u038a\x02\x1e\x19\xe0\u027a\xb2@\x00\x00\u07d4xd\u0719\x9f\xe4\xf8\xe0\x03\xc0\xf4=\xec\u00da\xae\x15\"\xdc\x0f\x89\x05\x1e\x10+\xd8\xec\xe0\x00\x00\u07d4xtj\x95\x8d\xce\xd4\xc7d\xf8vP\x8cAJh4,\uce49\x02\xbe7O\xe8\xe2\xc4\x00\x00\xe0\x94x}1?\xd3k\x05>\xee\xae\xdb\xcet\xb9\xfb\x06x32\x89\x8a\x05\xc0X\xb7\x84'\x19`\x00\x00\u07d4x\x85\x9c[T\x8bp\r\x92\x84\xce\xe4\xb6c</R\xe5)\u0089\xa00\xdc\xeb\xbd/L\x00\x00\xe0\x94x\x8e\x80\x97A\xa3\xb1J\"\xa4\xb1\xd97\xc8,\xfe\xa4\x89\uef8a\x01{x\x83\xc0i\x16`\x00\x00\u07d4x\xa1\xe2T@\x9f\xb1\xb5Z|\xb4\u074e\xba;0\u023a\xd9\xef\x89\x05k\xc7^-c\x10\x00\x00\xe0\x94x\xa5\xe8\x99\x00\xbd?\x81\xddq\xba\x86\x9d%\xfe\xc6Ra\xdf\x15\x8a\n\xfd\x81/\xee\x03\xd5p\x00\x00\xe0\x94x\xb9x\xa9\xd7\xe9\x1e\xe5)\xeaO\u0137o\xea\xf8v/i\x8c\x8a\x06\u01b95\xb8\xbb\xd4\x00\x00\x00\xe0\x94x\xce>=GJ\x8a\x04{\x92\xc4\x15B$-\n\b\xc7\x0f\x99\x8a\x02\x1e\x19\xe0\u027a\xb2@\x00\x00\u07d4x\u03c36\xb3(\xdb=\x87\x81:G+\x9e\x89\xb7^\f\xf3\xbc\x8965\u026d\xc5\u07a0\x00\x00\u07d4x\xd4\xf8\xc7\x1c\x1eh\xa6\x9a\x98\xf5/\xcbE\u068a\xf5n\xa1\xa0\x89lk\x93[\x8b\xbd@\x00\x00\u07d4x\xdf&\x81\xd6\xd6\x02\xe2!B\xd5A\x16\u07a1]EIW\xaa\x89\x10'\x94\xad \xdah\x00\x00\u07d4x\xe0\x8b\xc53A<&\u2473\x14?\xfa|\u026f\xb9{x\x89\n\u05ce\xbcZ\xc6 \x00\x00\u07d4x\xe8?\x80\xb3g\x8cz\nN>\x8c\x84\xdc\xcd\xe0dBbw\x89a\t=|,m8\x00\x00\u07d4x\xf5\xc7G\x85\xc5f\x8a\x83\x80r\x04\x8b\xf8\xb4SYM\u06ab\x89\x15\xaf\x1dx\xb5\x8c@\x00\x00\u07d4y\x0f\x91\xbd]\x1c\\\xc4s\x9a\xe9\x13\x00\u06c9\xe1\xc10<\x93\x89lk\x93[\x8b\xbd@\x00\x00\u07d4y\x17\u5f42\xa9y\x0f\xd6P\xd0C\xcd\xd90\xf7y\x963\u06c9\xd8\xd4`,&\xbfl\x00\x00\u07d4y\x19\xe7b\u007f\x9b}T\xea;\x14\xbbM\xd4d\x9fO9\xde\xe0\x89Z\x87\xe7\xd7\xf5\xf6X\x00\x00\u07d4y\x1f`@\xb4\xe3\xe5\r\xcf5S\xf1\x82\u0357\xa9\x060\xb7]\x89\xd8\xd7&\xb7\x17z\x80\x00\x00\u07d4y0\xc2\xd9\xcb\xfa\x87\xf5\x10\xf8\xf9\x87w\xff\x8a\x84H\xcaV)\x89\n\xd6\xee\xdd\x17\xcf;\x80\x00\u07d4yE)\u041d\x01rq5\x970\x02pu\xb8z\xd8=\xaen\x89\x10\xce\x1d=\x8c\xb3\x18\x00\x00\u07d4yKQ\u00deS\xd9\xe7b\xb0a;\x82\x9aD\xb4r\xf4\xff\xf3\x89$5\xe0dxA\u0300\x00\xe0\x94yU\x1c\xed\xe3v\xf7G\xe3ql\x8dy@\rvm.\x01\x95\x8a\t\xcb7\xaf\xa4\xffxh\x00\x00\u07d4y^\xbc&&\xfc9\xb0\xc8b\x94\xe0\xe87\xdc\xf5#U0\x90\x8965\u026d\xc5\u07a0\x00\x00\u07d4yn\xbb\xf4\x9b>6\xd6v\x94\xady\xf8\xff6vz\xc6\xfa\xb0\x89\x03K\xc4\xfd\xde'\xc0\x00\x00\u07d4yo\x87\xbaaz)0\xb1g\v\xe9.\xd1(\x1f\xb0\xb3F\xe1\x89\x06\xf5\xe8o\xb5((\x00\x00\u07d4yt'\xe3\xdb\xf0\xfe\xaez%\x06\xf1-\xf1\xdc@2n\x85\x05\x8965\u026d\xc5\u07a0\x00\x00\u07d4yu\x10\xe3\x86\xf5c\x93\xce\xd8\xf4w7\x8aDLHO}\xad\x8965\u026d\xc5\u07a0\x00\x00\u07d4y{\xb7\xf1W\xd9\xfe\xaa\x17\xf7m\xa4\xf7\x04\xb7M\xc1\x03\x83A\x89\xb5\x0f\u03ef\xeb\xec\xb0\x00\x00\u07d4y\x88\x90\x131\xe3\x87\xf7\x13\xfa\u03b9\x00\\\xb9\xb6Q6\xeb\x14\x89j\xcb=\xf2~\x1f\x88\x00\x00\u07d4y\x89\u041f8&\xc3\u5bccu*\x81\x15r:\x84\xd8\tp\x89\x16\x86\xf8aL\xf0\xad\x00\x00\xe0\x94y\x95\xbd\x8c\xe2\xe0\xc6{\xf1\u01e51\xd4w\xbc\xa1\xb2\xb9ua\x8a\x01BH\xd6\x17\x82\x9e\xce\x00\x00\u07d4y\xae\xb3Ef\xb9t\xc3ZX\x81\xde\xc0 \x92}\xa7\xdf]%\x89lk\x93[\x8b\xbd@\x00\x00\u07d4y\xb1 \xeb\x88\x06s#!(\x8fgZ'\xa9\"_\x1c\xd2\ub245\xa0\xbf7\xde\xc9\xe4\x00\x00\u07d4y\xb4\x8d-a7\u00c5Ma\x1c\x01\xeaBBz\x0fY{\xb7\x89\nZ\xa8P\t\xe3\x9c\x00\x00\u07d4y\xb8\xaa\xd8y\xdd0V~\x87x\xd2\xd21\xc8\xf3z\xb8sN\x89lk\x93[\x8b\xbd@\x00\x00\u07d4y\xbf/{n2\x8a\xaf&\xe0\xbb\t?\xa2-\xa2\x9e\xf2\xf4q\x89a\t=|,m8\x00\x00\u07d4y\xc10\xc7b\xb8v[\x19\u04ab\u0260\x83\xab\x8f:\xady@\x89\u0556{\xe4\xfc?\x10\x00\x00\u07d4y\xc1\xbe\x19q\x1fs\xbe\xe4\xe61j\xe7T\x94Y\xaa\u03a2\xe0\x89\x15\xaf\x1dx\xb5\x8c@\x00\x00\u07d4y\xc6\x00/\x84R\xca\x15\u007f\x13\x17\xe8\n/\xaf$GUY\xb7\x89\x01\x15\x8eF\t\x13\xd0\x00\x00\u07d4y\xca\xc6IO\x11\xef'\x98t\x8c\xb52\x85\xbd\x8e\"\xf9|\u0689lk\x93[\x8b\xbd@\x00\x00\u07d4y\u03e9x\n\xe6\xd8{,1\x88?\t'i\x86\u021ag5\x8965\u026d\xc5\u07a0\x00\x00\u07d4y\u06e2VG-\xb4\xe0X\xf2\xe4\xcd\xc3\xeaN\x8aBw83\x89O%\x91\xf8\x96\xa6P\x00\x00\u07d4y\xed\x10\xcf\x1fm\xb4\x82\x06\xb5\t\x19\xb9\xb6\x97\b\x1f\xbd\xaa\xf3\x89lk\x93[\x8b\xbd@\x00\x00\u0794y\xf0\x8e\x01\xce\t\x88\xe6<\u007f\x8f)\b\xfa\xdeC\xc7\xf9\xf5\u0248\xfc\x93c\x92\x80\x1c\x00\x00\u07d4y\xfdmH1Pf\xc2\x04\xf9e\x18i\xc1\tl\x14\xfc\x97\x81\x89lk\x93[\x8b\xbd@\x00\x00\u0794y\xff\xb4\xac\x13\x81*\vx\u0123{\x82u\">\x17k\xfd\xa5\x88\xf0\x15\xf2W6B\x00\x00\u07d4z\x05\x89\xb1C\xa8\xe5\xe1\a\u026cf\xa9\xf9\xf8Yz\xb3\u7ac9Q\xe92\xd7n\x8f{\x00\x00\u07d4z\nx\xa9\xcc9?\x91\xc3\xd9\xe3\x9ak\x8c\x06\x9f\a^k\xf5\x89Hz\x9a0E9D\x00\x00\u07d4z\x13p\xa7B\xec&\x87\xe7a\xa1\x9a\u0167\x942\x9e\xe6t\x04\x89\xa2\xa12ga\xe2\x92\x00\x00\xe0\x94z-\xfcw\x0e$6\x811\xb7\x84w\x95\xf2\x03\xf3\xd5\r[V\x8a\x02i\xfe\xc7\xf06\x1d \x00\x00\u07d4z3\x83N\x85\x83s>-R\xae\xadX\x9b\u046f\xfb\x1d\xd2V\x8965\u026d\xc5\u07a0\x00\x00\xe0\x94z6\xab\xa5\xc3\x1e\xa0\xca~'{\xaa2\xecF\u0393\xcfu\x06\x8a\x04<3\xc1\x93ud\x80\x00\x00\xe0\x94z8\x11\"\xba\xday\x1az\xb1\xf6\x03}\xac\x80C'S\xba\xad\x8a\x02\x1e\x19\xe0\u027a\xb2@\x00\x00\xe0\x94zH\xd8w\xb6:\x8f\x8f\x93\x83\xe9\xd0\x1eS\xe8\fR\x8e\x95_\x8a\x01\xb1\xaeMn.\xf5\x00\x00\x00\u07d4zO\x9b\x85\x06\x90\xc7\xc9F\x00\xdb\xee\f\xa4\xb0\xa4\x11\xe9\xc2!\x89g\x8a\x93 b\xe4\x18\x00\x00\u07d4zc\x86\x9f\xc7g\xa4\u01b1\xcd\x0e\x06I\xf3cL\xb1!\xd2K\x89\x043\x87Oc,\xc6\x00\x00\u07d4zg\xdd\x04:PO\xc2\xf2\xfcq\x94\xe9\xbe\xcfHL\xec\xb1\xfb\x89\r\x8drkqw\xa8\x00\x00\xe0\x94zk&\xf48\u0663RD\x91U\xb8\x87l\xbd\x17\xc9\u065bd\x8a\x01EB\xba\x12\xa37\xc0\x00\x00\u07d4zmx\x1cw\u013a\x1f\xca\xdfhsA\xc1\xe3\x17\x99\xe9='\x89\x0e\u0683\x8cI)\b\x00\x00\u07d4zph\xe1\xc37\\\x0eY\x9d\xb1\xfb\xe6\xb2\xea#\xb8\xf4\a\u0489lk\x93[\x8b\xbd@\x00\x00\u07d4zt\xce\xe4\xfa\x0fcp\xa7\x89O\x11l\xd0\f\x11G\xb8>Y\x89+^:\xf1k\x18\x80\x00\x00\u07d4zy\xe3\x0f\xf0W\xf7\n=\x01\x91\xf7\xf5?v\x157\xaf}\xff\x89\x15\xaf\x1dx\xb5\x8c@\x00\x00\xe0\x94zzO\x80sW\xa4\xbb\xe6\x8e\x1a\xa8\x0692\x10\xc4\x11\u0333\x8a\x06ZM\xa2]0\x16\xc0\x00\x00\u07d4z\x85c\x86y\x01 o?+\xf0\xfa>\x1c\x81\t\u02bc\u0345\x89\amA\xc6$\x94\x84\x00\x00\xe0\x94z\x87\x97i\n\xb7{Tp\xbf|\f\x1b\xbaa%\b\xe1\xac}\x8a\x01\xe0\x92\x96\xc37\x8d\xe4\x00\x00\u07d4z\x8c\x89\xc0\x14P\x9dV\u05f6\x810f\x8f\xf6\xa3\xec\xecsp\x89\x10CV\x1a\x88)0\x00\x00\xe0\x94z\x94\xb1\x99\x92\u03b8\xcec\xbc\x92\xeeKZ\xde\xd1\fM\x97%\x8a\x03\x8d\x1a\x80d\xbbd\xc8\x00\x00\u07d4z\xa7\x9a\xc0C\x16\u030d\b\xf2\x00e\xba\xa6\xd4\x14(\x97\xd5N\x89K\xe4\xe7&{j\xe0\x00\x00\u07d4z\xadM\xbc\u04ec\xf9\x97\u07d3XiV\xf7+d\u062d\x94\xee\x89\xd8\xd7&\xb7\x17z\x80\x00\x00\xe0\x94z\xb2V\xb2\x04\x80\n\xf2\x017\xfa\xbc\xc9\x16\xa22Xu%\x01\x8a\x04<3\xc1\x93ud\x80\x00\x00\u07d4z\xbaV\xf6:H\xbc\b\x17\u05b9p9\x03\x9az\xd6/\xae.\x89 \x86\xac5\x10R`\x00\x00\xe0\x94z\xbb\x10\xf5\xbd\x9b\xc3;\x8e\xc1\xa8-d\xb5[k\x18wuA\x8a\x04<3\xc1\x93ud\x80\x00\x00\u07d4z\u010d@\xc6d\u031am\x89\xf1\xc5\xf5\xc8\n\x1cp\xe7D\u6263\x10b\xbe\xee\xd7\x00\x00\x00\u07d4z\u014fo\xfcO\x81\a\xaen07\x8eN\x9f\x99\xc5\u007f\xbb$\x89\x02+\x1c\x8c\x12'\xa0\x00\x00\u07d4z\xd3\xf3\aao\x19\u0731C\xe6DM\xab\x9c<3a\x1fR\x89\x02\xb5\xe3\xaf\x16\xb1\x88\x00\x00\u07d4z\xd8,\xae\xa1\xa8\xb4\xed\x051\x9b\x9c\x98p\x17<\x81N\x06\xee\x89!d\xb7\xa0J\u0220\x00\x00\u07d4z\xde]f\xb9D\xbb\x86\f\x0e\xfd\xc8bv\u054fFS\xf7\x11\x89lk\x93[\x8b\xbd@\x00\x00\u07d4z\xdf\xed\xb0m\x91\xf3\xccs\x90E\v\x85U\x02p\x88<{\xb7\x89\x11x\xfa@Q]\xb4\x00\x00\u07d4z\xe1\xc1\x9eS\xc7\x1c\xeeLs\xfa\xe2\xd7\xfcs\xbf\x9a\xb5\u348965\u026d\xc5\u07a0\x00\x00\u07d4z\xe6Y\xeb;\xc4hR\xfa\x86\xfa\xc4\xe2\x1cv\x8dP8\x89E\x89\x0f\x81\f\x1c\xb5\x01\xb8\x00\x00\u07d4z\xea%\xd4+&\x12(n\x99\xc56\x97\u01bcA\x00\xe2\u06ff\x89lk\x93[\x8b\xbd@\x00\x00\u07d4z\xef{U\x1f\v\x9cF\xe7U\xc0\xf3\x8e[:s\xfe\x11\x99\xf5\x89P\xc5\xe7a\xa4D\b\x00\x00\u07d4{\v1\xffn$t^\xad\x8e\u067b\x85\xfc\v\xf2\xfe\x1dU\u0509+^:\xf1k\x18\x80\x00\x00\xe0\x94{\x0f\xea\x11v\xd5!Y3:\x14<)IC\xda6\xbb\u0774\x8a\x01\xfc}\xa6N\xa1L\x10\x00\x00\u07d4{\x11g<\xc0\x19bk)\f\xbd\xce&\x04o~m\x14\x1e!\x89\x1b\x1a\xe4\xd6\xe2\xefP\x00\x00\u07d4{\x12!b\xc9\x13\xe7\x14l\xad\v~\xd3z\xff\xc9*\v\xf2\u007f\x89Q\xaf\tk#\x01\u0440\x00\u07d4{\x1b\xf5:\x9c\xbe\x83\xa7\u07a44W\x9f\xe7*\xac\x8d*\f\u0409\n\xd4\xc81j\v\f\x00\x00\u07d4{\x1d\xaf\x14\x89\x1b\x8a\x1e\x1b\xd4)\u0633k\x9aJ\xa1\u066f\xbf\x89\x1b\x1a\xe4\xd6\xe2\xefP\x00\x00\u07d4{\x1f\xe1\xabM\xfd\x00\x88\xcd\xd7\xf6\x01c\xefY\xec*\xee\x06\xf5\x89lk\x93[\x8b\xbd@\x00\x00\u07d4{%\xbb\x9c\xa8\xe7\x02!~\x933\"RP\xe5<6\x80MH\x89e\xea=\xb7UF`\x00\x00\u07d4{'\xd0\xd1\xf3\xdd<\x14\x02\x94\xd0H\x8bx>\xbf@\x15'}\x89\x15\xaf\x1dx\xb5\x8c@\x00\x00\xe0\x94{@\a\xc4^ZW?\u06f6\xf8\xbdtk\xf9J\xd0J<&\x8a\x038!\xf5\x13]%\x9a\x00\x00\u07d4{C\xc7\xee\xa8\xd6#U\xb0\xa8\xa8\x1d\xa0\x81\xc6Dk3\xe9\xe0\x89\xd8\xd7&\xb7\x17z\x80\x00\x00\u07d4{M*8&\x90i\xc1\x85Ww\rY\x1d$\xc5\x12\x1f^\x83\x89%\xf2s\x93=\xb5p\x00\x00\xe0\x94{au\xec\x9b\xef\xc78$\x955\xdd\xde4h\x8c\xd3n\xdf%\x8a\x02\x1e\x19\xe0\u027a\xb2@\x00\x00\xe0\x94{f\x12hy\x84M\xfa4\xfee\xc9\xf2\x88\x11\u007f\xef\xb4I\xad\x8a\x01EB\xba\x12\xa37\xc0\x00\x00\u07d4{j\x84q\x8d\xd8nc3\x84)\xac\x81\x1d|\x8a\x86\x0f!\xf1\x89a\t=|,m8\x00\x00\xe0\x94{q,z\xf1\x16v\x00jf\xd2\xfc\\\x1a\xb4\xc4y\xce`7\x8a\x01\xb1\xaeMn.\xf5\x00\x00\x00\u07d4{s$-u\u029a\xd5X\xd6P)\r\xf1v\x92\xd5L\u0638\x89lnY\xe6|xT\x00\x00\u07d4{v\x1f\xeb\u007f\u03e7\xde\xd1\xf0\xeb\x05\x8fJ`\v\xf3\xa7\b\u02c9\xf9]\xd2\xec'\xcc\xe0\x00\x00\xe0\x94{\x82|\xae\u007f\xf4t\t\x18\xf2\xe00\xab&\u02d8\xc4\xf4l\xf5\x8a\x01\x94hL\v9\xde\x10\x00\x00\xe0\x94{\x892\x86B~r\xdb!\x9a!\xfcM\xcd_\xbfY(<1\x8a\x02\x1e\x19\xe0\u027a\xb2@\x00\x00\u07d4{\x92&\xd4o\xe7Q\x94\v\xc4\x16\xa7\x98\xb6\x9c\xcf\r\xfa\xb6g\x89\u3bb5sr@\xa0\x00\x00\u07d4{\x98\xe2<\xb9k\xee\xe8\n\x16\x80i\ube8f \xed\xd5\\\u03c9\v\xa0\xc9\x15\x87\xc1J\x00\x00\u07d4{\xb0\xfd\xf5\xa6c\xb5\xfb\xa2\x8d\x9c\x90*\xf0\xc8\x11\xe2R\xf2\x98\x89\n\u05ce\xbcZ\xc6 \x00\x00\u07d4{\xb9W\x1f9K\v\x1a\x8e\xbaVd\xe9\u0635\xe8@g{\xea\x89\x01\x11du\x9f\xfb2\x00\x00\xe0\x94{\xb9\x84\xc6\u06f9\xe2y\x96j\xfa\xfd\xa5\x9c\x01\xd0&'\xc8\x04\x8a\x01\xb4d1\x1dE\xa6\x88\x00\x00\u07d4{\xbb\xec^p\xbd\xea\u063b2\xb4(\x05\x98\x8e\x96H\xc0\xaa\x97\x8966\u05ef^\u024e\x00\x00\u07d4{\xca\x1d\xa6\xc8\nf\xba\xa5\xdbZ\u0245A\u013e'kD}\x89$\xcf\x04\x96\x80\xfa<\x00\x00\u07d4{\u0772\xee\x98\xde\x19\xeeL\x91\xf6a\xee\x8eg\xa9\x1d\x05K\x97\x8965\u026d\xc5\u07a0\x00\x00\u0794{\xe2\xf7h\f\x80-\xa6\x15L\x92\xc0\x19J\xe72Qzqi\x88\xfc\x93c\x92\x80\x1c\x00\x00\u07d4{\xe7\xf2Eiq\x88;\x9a\x8d\xbeL\x91\xde\xc0\x8a\xc3N\x88b\x89\xa2\xa1]\tQ\x9b\xe0\x00\x00\u07d4{\xe8\u0334\xf1\x1bf\xcan\x1dW\xc0\xb59b!\xa3\x1b\xa5:\x89\x01\x15\x8eF\t\x13\xd0\x00\x00\xe0\x94{\xeb\x81\xfb/^\x91Rk*\xc9y^v\u019b\xcf\xf0K\xc0\x8a\x0e\xb2.yO\n\x8d`\x00\x00\u07d4|\b\x83\x05L-\x02\xbcz\x85+\x1f\x86\xc4'w\xd0\xd5\xc8V\x89\x1b\x1a\xe4\xd6\xe2\xefP\x00\x00\u07d4|\x0f^\a C\xc9\xeet\x02B\x19~x\xccK\x98\xcd\xf9`\x89\n\u05ce\xbcZ\xc6 \x00\x00\u07d4|\x1d\xf2JO\u007f\xb2\u01f4r\xe0\xbb\x00l\xb2}\xcd\x16AV\x8965\u026d\xc5\u07a0\x00\x00\u07d4|)\xd4}W\xa73\xf5k\x9b!pc\xb5\x13\xdc;1Y#\x89\xd8\xd7&\xb7\x17z\x80\x00\x00\u07d4|+\x96\x03\x88JO.FN\u03b9}\x17\x93\x8d\x82\x8b\xc0,\x89\xa2\xa1]\tQ\x9b\xe0\x00\x00\u07d4|8,\x02\x96a.N\x97\xe4@\xe0-8q';U\xf5;\x89\n\xb6@9\x12\x010\x00\x00\u07d4|>\xb7\x13\xc4\xc9\xe08\x1c\xd8\x15L|\x9a}\xb8d\\\xde\x17\x89\n\u05ce\xbcZ\xc6 \x00\x00\u07d4|D\x01\xae\x98\xf1.\xf6\xde9\xae$\u03df\xc5\x1f\x80\xeb\xa1k\x89\n\u05ce\xbcZ\xc6 \x00\x00\u07d4|E\xf0\xf8D*V\xdb\u04dd\xbf\x15\x99\x95A\\R\xedG\x9b\x89lk\x93[\x8b\xbd@\x00\x00\xe0\x94|S-\xb9\xe0\xc0l&\xfd@\xac\xc5j\xc5\\\x1e\xe9-<:\x8a?\x87\bW\xa3\xe0\xe3\x80\x00\x00\u07d4|`\xa0_zJ_\x8c\xf2xC\x916.uZ\x83A\xefY\x89f\x94\xf0\x18*7\xae\x00\x00\u07d4|`\xe5\x1f\v\xe2(\xe4\xd5o\xdd)\x92\xc8\x14\xdaw@\u01bc\x89\n\u05ce\xbcZ\xc6 \x00\x00\u07d4|i$\xd0|>\xf5\x89\x19f\xfe\nxV\xc8{\xef\x9d 4\x89lk\x93[\x8b\xbd@\x00\x00\xe0\x94|\x8b\xb6Zo\xbbI\xbdA3\x96\xa9\xd7\xe3\x10S\xbb\xb3z\xa9\x8a\x01EB\xba\x12\xa37\xc0\x00\x00\xe0\x94|\x9a\x11\f\xb1\x1f%\x98\xb2\xb2\x0e,\xa4\x002^A\xe9\xdb3\x8a\x05\x81v{\xa6\x18\x9c@\x00\x00\u07d4|\xbc\xa8\x8f\xcaj\x00`\xb9`\x98\\\x9a\xa1\xb0%4\xdc\"\b\x89\x19\x12z\x13\x91\xea*\x00\x00\u07d4|\xbe\xb9\x992\xe9~n\x02\x05\x8c\xfcb\u0432k\xc7\u0325+\x89lk\x93[\x8b\xbd@\x00\x00\u07d4|\xc2Jj\x95\x8c \xc7\xd1$\x96`\xf7Xb&\x95\v\r\x9a\x89j\xcb=\xf2~\x1f\x88\x00\x00\u07d4|\xd2\x0e\u0335\x18\xb6\f\xab\t[r\x0fW\x15p\u02aaD~\x89\x1b\x1a\xe4\xd6\xe2\xefP\x00\x00\u07d4|\xd5\xd8\x1e\xab7\xe1\x1ebv\xa3\xa1\t\x12Q`~\r~8\x89\x03hM^\xf9\x81\xf4\x00\x00\u07d4|\xdft!9E\x95=\xb3\x9a\xd0\xe8\xa9x\x1a\xddy.M\x1d\x89lk\x93[\x8b\xbd@\x00\x00\u07d4|\xe4hdF\U000547be\xd6r\x15\xeb\rZ\x1d\xd7,\x11\xb8\x89x9\xd3!\xb8\x1a\xb8\x00\x00\u07d4|\xefMC\xaaA\u007f\x9e\xf8\xb7\x87\xf8\xb9\x9dS\xf1\xfe\xa1\ue209g\x8a\x93 b\xe4\x18\x00\x00\u07d4}\x03P\xe4\v3\x8d\xdasfa\x87+\xe3?\x1f\x97R\xd7U\x89\x02\xb4\xf5\xa6\U00051500\x00\xe0\x94}\x04\xd2\xed\xc0X\xa1\xaf\xc7a\xd9\u025a\xe4\xfc\\\x85\xd4\u0226\x8aB\xa9\xc4g\\\x94g\xd0\x00\x00\u07d4}\v%^\xfbW\xe1\x0fp\b\xaa\"\xd4\x0e\x97R\xdf\xcf\x03x\x89\x01\x9f\x8euY\x92L\x00\x00\xe0\x94}\x13\xd6pX\x84\xab!W\u074d\xccpF\xca\xf5\x8e\xe9K\xe4\x8a\x1d\r\xa0|\xbb>\xe9\xc0\x00\x00\u07d4}'>c~\xf1\xea\u0101\x11\x94\x13\xb9\x1c\x98\x9d\xc5\xea\xc1\"\x89\x1b\x1a\xe4\xd6\xe2\xefP\x00\x00\u07d4}*R\xa7\xcf\f\x846\xa8\xe0\a\x97kl&\xb7\"\x9d\x1e\x15\x89\x17\xbf\x06\xb3*$\x1c\x00\x00\u07d4}4\x805i\xe0\v\u05b5\x9f\xff\b\x1d\xfa\\\n\xb4\x19zb\x89\\\xd8|\xb7\xb9\xfb\x86\x00\x00\u07d4}4\xffY\xae\x84\nt\x13\u01baL[\xb2\xba,u\xea\xb0\x18\x89\xa2\xa1]\tQ\x9b\xe0\x00\x00\u07d4}9(R\xf3\xab\xd9/\xf4\xbb[\xb2l\xb6\bt\xf2\xbeg\x95\x8966\xc2^f\xec\xe7\x00\x00\u07d4}DRg\u015a\xb8\u04a2\xd9\xe7\t\x99\x0e\th%\x80\u011f\x8965\u026d\xc5\u07a0\x00\x00\xe0\x94}U\x13\x97\xf7\x9a)\x88\xb0d\xaf\xd0\xef\xeb\xee\x80,w!\xbc\x8a\bW\xe0\xd6\xf1\xdav\xa0\x00\x00\u07d4}Z\xa3?\xc1KQ\x84\x1a\x06\x90n\xdb+\xb4\x9c*\x11ri\x89\x10D\x00\xa2G\x0eh\x00\x00\xe0\x94}]/s\x94\x9d\xad\xda\bV\xb2\x06\x98\x9d\xf0\a\x8dQ\xa1\xe5\x8a\x02<upr\xb8\xdd\x00\x00\x00\xe0\x94}n\x99\r\xaaq\x05\xde%&3\x983\xf7{\\\v\x85\xd8O\x8a\x04<3\xc1\x93ud\x80\x00\x00\u07d4}s\x8608\xcc\xca\"\xf9j\xff\xda\x10InQ\xe1\xe6\xcdH\x89\x01\x15\x8eF\t\x13\xd0\x00\x00\u07d4}}\xd5\xeeaM\xbbo\xbf\xbc\xd2c\x05$z\x05\x8cA\xfa\xa1\x89lk\x93[\x8b\xbd@\x00\x00\u07d4}~|aw\x9a\xdbw\x06\xc9M2@\x9a+\xb4\u953f`\x89.\xf2\r\x9f\xc7\x1a\x14\x00\x00\u07d4}\x82\xe5#\xcc-\u0151\xda9T\u8dbb,\xafda\u6709}\x8d\xc2\xef\xff\xb1\xa9\x00\x00\u07d4}\x85\x84\x93\xf0t\x15\xe0\x91-\x05y<\x97!\x13\xea\u8b88\x89b\x8d\xd1w\u04bc(\x00\x00\u07d4}\x90\x1b(\xbf\u007f\x88\xefs\xd8\xf7<\u0297VI\x13\xea\x8a$\x893\xc5I\x901r\f\x00\x00\u07d4}\x98\x0fKVk\xb0EQ~L\x14\xc8wP\u0793FtK\x89Hz\x9a0E9D\x00\x00\xe0\x94}\x9cYc\x1e+\xa2\xe8\xe8(\x91\xf3\x97\x99\"\xaa\xa3\xb5g\xa1\x8a\x01\xb1\xaeMn.\xf5\x00\x00\x00\u07d4}\x9d\"\x1a=\xf8\x9d\xdd{_a\xc1F\x8cg\x87\u05b33\xe6\x89\a{\"|\xd8;\xe8\x00\x00\u07d4}\xa7a4E\xa2\x12\x99\xaat\xf0\xadqC\x1e\xc4?\xbb\x1b\xe9\x89\x03\xaf\xb0\x87\xb8v\x90\x00\x00\u07d4}\xb4\xc7\u0577\x97\xe9)nc\x82\xf2\x03i=\xb4\tD\x9db\x89\x15\xaf\x1dx\xb5\x8c@\x00\x00\u07d4}\xb9\xea\xccR\xe4)\u0703\xb4a\xc5\xf4\xd8`\x10\xe58:(\x8965\u026d\xc5\u07a0\x00\x00\u07d4}\xd4m\xa6w\xe1a\x82^\x12\xe8\r\xc4F\xf5\x82v\xe1\x12|\x89,s\xc97t,P\x00\x00\u07d4}\xd8\u05e1\xa3O\xa1\xf8\xe7<\xcb\x00_\u00a0:\x15\xb8\"\x9c\x89\n\u05ce\xbcZ\xc6 \x00\x00\u07d4}\xddW\x16\\\x87\xa2p\u007f\x02]\xcf\xc2P\x8c\t\x83GY\xbc\x89K\xe4\xe7&{j\xe0\x00\x00\u07d4}\xe4B\xc8#\x86\x15M.\x99<\xbd\x12\x80\xbb|\xa6\xb1*\u0689\xd8\xf2\xe8$~\xc9H\x00\x00\u07d4}\xe7\xfeA\x9c\xc6\x1f\x91\xf4\b\xd24\u0300\xd5\xca=\x05M\x99\x89\x01\x15\x8eF\t\x13\xd0\x00\x00\u07d4}\xec\u664a\xe1\x90\r\xd3w\f\xf4\xb98\x12\xba\xd8O\x03\"\x89\x05k\xc7^-c\x10\x00\x00\u07d4}\xfc4-\xff\xcfE\xdf\xeet\xf8L\t\x959{\u04661r\x89\r\x8drkqw\xa8\x00\x00\u07d4}\xfd)b\xb5u\xbc\xbe\xee\x97\xf4\x91B\xd6<0\xab\x00\x9ff\x89\xd8\xd7&\xb7\x17z\x80\x00\x00\u07d4~\x1e)r\x1dl\xb9\x10W\xf6\xc4\x04-\x8a\v\xbcdJ\xfes\x89\b\xa9\xab\xa5W\xe3l\x00\x00\u07d4~#ff\xb2\xd0nc\xeaN*\xb8CW\xe2\xdf\xc9w\xe5\x0e\x8965f3\xeb\xd8\xea\x00\x00\xe0\x94~$\xd9\xe2,\xe1\xda<\xe1\x9f!\x9c\xce\xe5#7hs\xf3g\x8a\x01?\xd9\a\x9c\xaa`\xff\x00\x00\u07d4~$\xfb\xda\u0490\x17^\xb2\xdfm\x18\n\x19\xb9\xa9\xf4\x13p\xbe\x8965\u026d\xc5\u07a0\x00\x00\xe0\x94~&\x8f\x13\x1d\xdfh|\xc3%\xc4\x12\xf7\x8b\xa9a ^\x91\x12\x8a\x03cd\xee}0\x1b<\x00\x00\u07d4~))\x008I5Y\x19N\x94mNF\v\x96\xfc8\xa1V\x89\x10\xc1<Rwc\x88\x00\x00\u07d4~+\xa8m\xa5.x]\x86%3O3\x97\xba\x1cK\xf2\xe8\u0449\n\xad\xec\x98?\xcf\xf4\x00\x00\u07d4~?c\xe11)\xa2!\xba\x1a\xb0c&4,\u064bQ&\xae\x89V\xa0&Y\xa5#4\x00\x00\u07d4~Gc~\x97\xc1F\"\x88+\xe0W\xbe\xa2)8o@R\xe5\x89\x17\xda:\x04\u01f3\xe0\x00\x00\u07d4~N\x94\tpA!\xd1\xd7y\x97\x02o\xf0n\xa9\xb1\x9a\x8b\x90\x89\x8d\x16T\x9e\u054f\xa4\x00\x00\u07d4~Y\xdc`\xbe\x8b/\xc1\x9a\xbd\nW\x82\xc5,(@\v\u0397\x8965\u026d\xc5\u07a0\x00\x00\u07d4~[\x19\xae\x1b\xe9O\xf4\xde\xe65I*\x1b\x01-\x14\xdb\x02\x13\x89\x05k\xc7^-c\x10\x00\x00\u07d4~]\x99\x93\x10NL\xb5E\xe1y\xa2\xa3\xf9q\xf7D\xf9\x84\x82\x89lk\x93[\x8b\xbd@\x00\x00\u07d4~q\x17\x1f)I\xfa\f:\xc2T%K\x1f\x04@\xe5\xe6\xa08\x89\x02+\x1c\x8c\x12'\xa0\x00\x00\u07d4~|\x1e\x9aa\xa0\x8a\x83\x98H5\xc7\x0e\xc3\x1d4\xd3\xea\xa8\u007f\x89\nZ\xa8P\t\xe3\x9c\x00\x00\u07d4~\u007f\x18\xa0.\u032a]a\xab\x8f\xbf\x03\x03C\xc44\xa2^\xf7\x89\x03\x9f\xba\xe8\xd0B\xdd\x00\x00\u07d4~\x81\xf6D\x9a\x037A\x91\xf3\xb7\xcb\x05\xd98\xb7.\t\r\xff\x89\x05k\xc7^-c\x10\x00\x00\u07d4~\x86I\xe6\x90\xfc\x8c\x1b\xfd\xa1\xb5\xe1\x86X\x1fd\x9bP\xfe3\x89\x05V\xf6L\x1f\xe7\xfa\x00\x00\u07d4~\x87\x86>\xc4:H\x1d\xf0M\x01wb\xed\xcb\\\xaab\x9bZ\x89\x02\"\xc8\xeb?\xf6d\x00\x00\u07d4~\x8f\x96\xcc)\xf5{\tu\x12\f\xb5\x93\xb7\u0743=`kS\x89\n\xad\xec\x98?\xcf\xf4\x00\x00\u07d4~\x97*\x8a|*D\xc9;!Cl8\xd2\x1b\x92R\xc3E\xfe\x89a\t=|,m8\x00\x00\u07d4~\x99\u07fe\x98\x9d;\xa5)\u0457Q\xb7\xf41\u007f\x89S\xa3\xe2\x89\x15\xaf\x1dx\xb5\x8c@\x00\x00\u07d4~\xa0\xf9n\xe0\xa5s\xa30\xb5h\x97v\x1f=L\x010\xa8\xe3\x89Hz\x9a0E9D\x00\x00\u0794~\xa7\x91\xeb\xab\x04E\xa0\x0e\xfd\xfcNJ\x8e\x9a~ue\x13m\x88\xfc\x93c\x92\x80\x1c\x00\x00\u07d4~\xab\xa05\xe2\xaf7\x93\xfdtgK\x10%@\xcf\x19\n\u0779\x89E\x02l\x83[`D\x00\x00\xe0\x94~\xb4\xb0\x18\\\x92\xb6C\x9a\b\xe72!h\xcb5<\x8awJ\x8a\x02'\x19l\xa0I\x83\xca\x00\x00\xe0\x94~\xbd\x95\xe9\xc4p\xf7(5\x83\xdcn\x9d,M\xce\v\ua3c4\x8a\x02\xf6\xf1\a\x80\xd2,\xc0\x00\x00\u07d4~\u0425\xa8G\xbe\xf9\xa9\xda|\xba\x1dd\x11\xf5\xc3\x161&\x19\x89\x02(\xeb7\xe8u\x1d\x00\x00\u07d4~\xda\xfb\xa8\x98K\xafc\x1a\x82\vk\x92\xbb\xc2\xc56U\xf6\xbd\x89lk\x93[\x8b\xbd@\x00\x00\u07d4~\xdb\x02\xc6\x1a\"r\x87a\x1a\xd9Pici\xccNdzh\x89\x0e\u0683\x8cI)\b\x00\x00\u07d4~\xe5\u0280]\xce#\xaf\x89\xc2\xd4D\xe7\xe4\af\xc5Lt\x04\x89\r\v\xd4\x12\xed\xbd\x82\x00\x00\xe0\x94~\xe6\x04\u01e9\xdc)\t\xce2\x1d\u6e72OWgWuU\x8a\x01+\xf9\u01d8\\\xf6-\x80\x00\u07d4~\xf1o\xd8\xd1[7\x8a\x0f\xba0k\x8d\x03\u0758\xfc\x92a\x9f\x89%\xf2s\x93=\xb5p\x00\x00\u07d4~\xf9\x8bR\xbe\xe9S\xbe\xf9\x92\xf3\x05\xfd\xa0'\xf8\x91\x1cXQ\x89\x1b\xe7\" i\x96\xbc\x80\x00\u07d4~\xfc\x90vj\x00\xbcR7,\xac\x97\xfa\xbd\x8a<\x83\x1f\x8e\u0349\b\x90\xb0\xc2\xe1O\xb8\x00\x00\u07d4~\xfe\xc0\xc6%<\xaf9\u007fq(|\x1c\a\xf6\xc9X+[\x86\x89\x1a,\xbc\xb8O0\u0540\x00\u07d4\u007f\x01\xdc|7G\xca`\x8f\x98=\xfc\x8c\x9b9\xe7U\xa3\xb9\x14\x89\v8l\xad_zZ\x00\x00\u07d4\u007f\x06b\xb4\x10)\x8c\x99\xf3\x11\u04e1EJ\x1e\xed\xba/\xeav\x89\n\u05ce\xbcZ\xc6 \x00\x00\xe0\x94\u007f\x06\u021dY\x80\u007f\xa6\v\xc6\x016\xfc\xf8\x14\u02ef%C\xbd\x8a\x02\x1e\x19\xe0\u027a\xb2@\x00\x00\u07d4\u007f\v\x90\xa1\xfd\u050f'\xb2h\xfe\xb3\x83\x82\xe5]\xdbP\xef\x0f\x892\xf5\x1e\u06ea\xa30\x00\x00\u07d4\u007f\x0e\xc3\u06c0F\x92\xd4\xd1\xea2E6Z\xab\x05\x90\a[\u0109\xd8\xd7&\xb7\x17z\x80\x00\x00\u07d4\u007f\x0f\x04\xfc\xf3zS\xa4\xe2N\xden\x93\x10Nx\xbe\x1d<\x9e\x89lk\x93[\x8b\xbd@\x00\x00\xe0\x94\u007f\x13\xd7`I\x8dq\x93\xcahY\xbc\x95\xc9\x018d#\xd7l\x8a\x01\x0f\f\xf0d\xddY \x00\x00\u07d4\u007f\x15\n\xfb\x1aw\u00b4Y(\xc2h\xc1\u9f74d\x1dG\u0609lk\x93[\x8b\xbd@\x00\x00\u07d4\u007f\x16\x19\x98\x8f7\x15\xe9O\xf1\xd2S&-\xc5X\x1d\xb3\xde\x1c\x890\xca\x02O\x98{\x90\x00\x00\u07d4\u007f\x1c\x81\xee\x16\x97\xfc\x14K|\v\xe5I;V\x15\xae\u007f\xdd\u0289\x1b\x1d\xaba\u04ead\x00\x00\u07d4\u007f#\x82\xff\xd8\xf89VFy7\xf9\xbar7F#\xf1\x1b8\x89 \x86\xac5\x10R`\x00\x00\u07d4\u007f7\t9\x1f?\xbe\xba5\x92\xd1u\xc7@\xe8z\tT\x1d\x02\x89\x1a\x05V\x90\xd9\u06c0\x00\x00\u07d4\u007f8\x9c\x12\xf3\xc6\x16OdFVlwf\x95\x03\xc2y%'\x89\x05V\xf6L\x1f\xe7\xfa\x00\x00\xe0\x94\u007f:\x1eE\xf6~\x92\u0200\xe5s\xb43y\xd7\x1e\xe0\x89\xdbT\x8a\x15-\x02\xc7\xe1J\xf6\x80\x00\x00\xe0\x94\u007f=r\x03\u0224G\xf7\xbf6\u060a\xe9\xb6\x06*^\xeex\xae\x8a\x01EB\xba\x12\xa37\xc0\x00\x00\xe0\x94\u007fF\xbb%F\r\xd7\xda\xe4!\x1c\xa7\xf1Z\xd3\x12\xfc}\xc7\\\x8a\x01je\x02\xf1Z\x1eT\x00\x00\u07d4\u007fI\xe7\xa4&\x98\x82\xbd\x87\"\u0526\xf5f4v)b@y\x89lk\x93[\x8b\xbd@\x00\x00\xe0\x94\u007fI\xf2\a&G\x1a\xc1\u01e8>\xf1\x06\xe9w\\\xebf%f\x8a\x01@a\xb9\xd7z^\x98\x00\x00\u07d4\u007fK^'\x85x\xc0F\xcc\xea\xf6W0\xa0\xe0h2\x9e\u0576\x89e\xea=\xb7UF`\x00\x00\u07d4\u007fOY;a\x8c3\v\xa2\xc3\xd5\xf4\x1e\xce\xeb\x92\xe2~Bl\x89\x96n\xdcuk|\xfc\x00\x00\u07d4\u007fT\x14\x91\u04ac\x00\xd2a/\x94\xaa\u007f\v\xcb\x01FQ\xfb\u0509\x14b\fW\xdd\xda\xe0\x00\x00\u07d4\u007fZ\xe0Z\xe0\xf8\xcb\xe5\xdf\xe7!\xf0D\u05e7\xbe\xf4\xc2y\x97\x89\x03@\xaa\xd2\x1b;p\x00\x00\u07d4\u007f`:\xec\x17Y\xea_\a\xc7\xf8\xd4\x1a\x14(\xfb\xba\xf9\xe7b\x89\x01\x15\x8eF\t\x13\xd0\x00\x00\u07d4\u007falo\x00\x8a\u07e0\x82\xf3M\xa7\xd0e\x04`6\x80u\xfb\x8965\u026d\xc5\u07a0\x00\x00\u07d4\u007fa\xfal\xf5\xf8\x98\xb4@\xda\u016b\xd8`\rmi\x1f\xde\xf9\x89\x0f-\xc7\xd4\u007f\x15`\x00\x00\xe0\x94\u007fe\\g\x89\xed\xdfE\\\xb4\xb8\x80\x99r\x0698\x9e\ubb0a\x01EB\xba\x12\xa37\xc0\x00\x00\u07d4\u007fk(\u0204!\xe4\x85~E\x92\x81\u05c4ai$\x89\xd3\xfb\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\u007fn\xfboC\x18\x87m.\xe6$\xe2u\x95\xf4DF\xf6\x8e\x93\x89T\x06\x923\xbf\u007fx\x00\x00\u07d4\u007fq\x92\xc0\xdf\x1c}\xb6\xd9\xede\xd7\x11\x84\xd8\xe4\x15Z\x17\xba\x89\x04Sr\x8d3\x94,\x00\x00\u07d4\u007fz:!\xb3\xf5\xa6]\x81\xe0\xfc\xb7\xd5-\xd0\n\x1a\xa3m\xba\x89\x05k\xc7^-c\x10\x00\x00\u07d4\u007f\x8d\xbc\xe1\x80\xed\x9cV65\xaa\xd2\xd9{L\xbcB\x89\x06\u0649\x90\xf54`\x8ar\x88\x00\x00\xe0\x94\u007f\x99=\xdb~\x02\u0082\xb8\x98\xf6\x15_h\x0e\xf5\xb9\xaf\xf9\a\x8a\x04<3\xc1\x93ud\x80\x00\x00\u07d4\u007f\x9f\x9bV\xe4(\x9d\xfbX\xe7\x0f\xd5\xf1*\x97\xb5m5\u01a5\x89j\xcb=\xf2~\x1f\x88\x00\x00\u07d4\u007f\xa3~\xd6x\x87u\x1aG\x1f\x0e\xb3\x06\xbeD\xe0\xdb\xcd`\x89\x899vt\u007f\xe1\x1a\x10\x00\x00\u07d4\u007f\xaa0\xc3\x15\x19\xb5\x84\xe9rP\xed*<\xf38^\xd5\xfdP\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\u007f\xcf[\xa6fo\x96lTH\xc1{\xf1\xcb\v\xbc\xd8\x01\x9b\x06\x89\x05k\xc3\u042e\xbeI\x80\x00\xe0\x94\u007f\xd6y\xe5\xfb\r\xa2\xa5\xd1\x16\x19M\xcbP\x83\x18\xed\u0140\xf3\x8a\x01c\x9eI\xbb\xa1b\x80\x00\x00\u07d4\u007f\u06e01\u01cf\x9c\tmb\xd0Z6\x9e\uac3c\xccU\u5257\xc9\xceL\xf6\xd5\xc0\x00\x00\u07d4\u007f\xdb\u00e8D\xe4\r\x96\xb2\xf3\xa652.`e\xf4\xca\x0e\x84\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\u007f\xdf\u020dx\xbf\x1b(Z\xc6O\x1a\xdb5\xdc\x11\xfc\xb09Q\x89|\x06\xfd\xa0/\xb06\x00\x00\u07d4\u007f\xea\x19b\xe3]b\x05\x97h\xc7I\xbe\u0756\u02b90\xd3x\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\u007f\xef\x8c8w\x9f\xb3\a\xeco\x04K\xeb\xe4\u007f<\xfa\xe7\x96\xf1\x89\t#@\xf8l\xf0\x9e\x80\x00\u07d4\u007f\xf0\xc6?p$\x1b\xec\xe1\x9bs~SA\xb1+\x10\x901\u0609\x12\xc1\xb6\xee\xd0=(\x00\x00\xe0\x94\u007f\xfa\xbf\xbc9\f\xbeC\u0389\x18\x8f\bh\xb2}\xcb\x0f\f\xad\x8a\x01YQ\x82\"K&H\x00\x00\xe0\x94\u007f\xfd\x02\xed7\fp`\xb2\xaeS\xc0x\xc8\x01!\x90\u07fbu\x8a\x02\x1e\x19\xe0\u027a\xb2@\x00\x00\u0794\x80\x02*\x12\a\xe9\x10\x91\x1f\xc9(I\xb0i\xab\f\xda\xd0C\u04c8\xb9\x8b\xc8)\xa6\xf9\x00\x00\u07d4\x80\t\xa7\xcb\u0452\xb3\xae\u052d\xb9\x83\xd5(ER\xc1ltQ\x89\xd8\xd7&\xb7\x17z\x80\x00\x00\u07d4\x80\x0e}c\x1cnW:\x903/\x17\xf7\x1f_\u045bR\x8c\xb9\x89\b=lz\xabc`\x00\x00\u07d4\x80\x15m\x10\ufa320\u0254\x10c\r7\xe2i\xd4\t<\xea\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\x80\x172\xa4\x81\u00c0\xe5~\xd6-l)\u0799\x8a\xf3\xfa;\x13\x89\x05k\xc7^-c\x10\x00\x00\u07d4\x80\x1de\xc5\x18\xb1\x1d\x0e?OG\x02!Ap\x13\xc8\xe5>\u0149\xd8\xd7&\xb7\x17z\x80\x00\x00\u07d4\x80&CZ\xacr\x8dI{\x19\xb3\xe7\xe5|(\xc5c\x95O+\x89]\u0212\xaa\x111\xc8\x00\x00\u07d4\x80-\xc3\xc4\xff-}\x92^\u215fJ\x06\u05fa`\xf10\x8c\x89\x05P\x94\f\x8f\xd3L\x00\x00\u07d4\x800\xb1\x11\u0198?\x04\x85\u076c\xa7b$\xc6\x18\x064x\x9f\x89\x04V9\x18$O@\x00\x00\u07d4\x805\xbc\xff\xae\xfd\xee\xea5\x83\fI}\x14(\x9d6 #\u0789\x10CV\x1a\x88)0\x00\x00\u07d4\x805\xfeNkj\xf2z\u44a5xQ^\x9d9\xfao\xa6[\x89\xd8\xd7&\xb7\x17z\x80\x00\x00\u07d4\x80C\xed\"\xf9\x97\u58a4\xc1n6D\x86\xaed\x97V\x92\u0109=I\x04\xff\xc9\x11.\x80\x00\u07d4\x80C\xfd\u043cL\x97=\x16c\xd5_\xc15P\x8e\xc5\xd4\xf4\xfa\x89\x01\x15\x8eF\t\x13\xd0\x00\x00\u07d4\x80L\xa9IrcOc:Q\xf3V\v\x1d\x06\xc0\xb2\x93\xb3\xb1\x89\n\u05ce\xbcZ\xc6 \x00\x00\u07d4\x80R-\u07d4N\xc5.'\xd7$\xedL\x93\xe1\xf7\xbe`\x83\u0589\n\u05ce\xbcZ\xc6 \x00\x00\xe0\x94\x80Y\x1aB\x17\x9f4\xe6M\x9d\xf7]\xcdF;(hoUt\x8a\x04<3\xc1\x93ud\x80\x00\x00\u07d4\x80\\\xe5\x12\x97\xa0y;\x81 g\xf0\x17\xb3\xe7\xb2\u07db\xb1\xf9\x89\x05k\xc7^-c\x10\x00\x00\xe0\x94\x80]\x84o\xb0\xbc\x02\xa73r&\u0585\xbe\x9e\xe7s\xb9\x19\x8a\x8a\x04<0\xfb\b\x84\xa9l\x00\x00\u07d4\x80c7\x9a{\xf2\u02d2:\x84\xc5\t>h\xda\xc7\xf7T\x81\u0149\x11v\x10.n2\xdf\x00\x00\u07d4\x80hTX\x8e\xcc\xe5AI_\x81\u008a)\x03s\xdf\x02t\xb2\x89\x1f\x8c\xdf\\n\x8dX\x00\x00\u07d4\x80oD\xbd\xebh\x807\x01^\x84\xff!\x80I\xe3\x823*3\x89l]\xb2\xa4\xd8\x15\xdc\x00\x00\u07d4\x80tF\x18\xde9jT1\x97\xeeH\x94\xab\xd0c\x98\xdd|'\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\x80w\xc3\xe4\xc4EXn\tL\xe1\x02\x93\u007f\xa0[s{V\x8c\x89\x05k\xc7^-c\x10\x00\x00\u07d4\x80\x90\u007fY1H\xb5|F\xc1w\xe2=%\xab\u012a\xe1\x83a\x89\x05k\xc7^-c\x10\x00\x00\u07d4\x80\x97s\x16\x94NYB\xe7\x9b\x0e:\xba\u04cd\xa7F\be\x19\x89\x02\x1auJm\xc5(\x00\x00\xe0\x94\x80\xa0\xf6\xcc\x18l\xf6 \x14\x00sn\x06Z9\x1fR\xa9\xdfJ\x8a\x02\x1e\x19\xe0\u027a\xb2@\x00\x00\u07d4\x80\xab\xecZ\xa3n\\\x9d\t\x8f\x1b\x94(\x81\xbdZ\xca\u0196=\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\x80\xb2=8\v\x82\\F\xe098\x99\xa8UVF-\xa0\u1309lk\x93[\x8b\xbd@\x00\x00\u07d4\x80\xb4-\xe1p\xdb\xd7#\xf4T\xe8\x8fw\x16E-\x92\x98P\x92\x89\x10F#\xc0v-\xd1\x00\x00\u07d4\x80\xb7\x9f3\x83\x90\u047a\x1b77\xa2\x9a\x02W\xe5\xd9\x1e\a1\x89\x01\x15\x8eF\t\x13\xd0\x00\x00\u07d4\x80\xbf\x99^\u063a\x92p\x1d\x10\xfe\u011f\x9e}\x01M\xbe\xe0&\x89\x1f\x047\xca\x1a~\x12\x80\x00\u07d4\x80\xc0N\xfd1\x0fD\x04\x83\xc7?tK[\x9edY\x9c\xe3\xec\x89A\rXj \xa4\xc0\x00\x00\u07d4\x80\u00e9\xf6\x95\xb1m\xb1Yr\x86\u0473\xa8\xb7il9\xfa'\x89\x05k\xc7^-c\x10\x00\x00\u07d4\x80\xc5>\xe7\xe35\u007f\x94\xce\rxh\x00\x9c \x8bJ\x13\x01%\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\x80\xcc!\xbd\x99\xf3\x90\x05\u014f\xe4\xa4H\x90\x92 !\x8ff\u02c966\xc9yd6t\x00\x00\u07d4\x80\xd5\xc4\fY\xc7\xf5N\xa3\xa5_\xcf\xd1uG\x1e\xa3P\x99\xb3\x8965\u026d\xc5\u07a0\x00\x00\u07d4\x80\xda/\u0762\x9a\x9e'\xf9\xe1\x15\x97^i\xae\x9c\xfb\xf3\xf2~\x89\n\u05ce\xbcZ\xc6 \x00\x00\xe0\x94\x80\xe7\xb3 R0\xa5f\xa1\xf0a\xd9\"\x81\x9b\xb4\xd4\u04a0\xe1\x8a\x02\xf6\xf1\a\x80\xd2,\xc0\x00\x00\u07d4\x80\xea\x1a\xcc\x13n\xcaKh\xc8B\xa9Z\xdfk\u007f\xee~\xb8\xa2\x89\xd8\xd7&\xb7\x17z\x80\x00\x00\u07d4\x80\xf0z\xc0\x9e{,<\n=\x1e\x94\x13\xa5D\xc7:A\xbe\u02c9\x01\x15\x8eF\t\x13\xd0\x00\x00\u07d4\x81\r\xb2Vu\xf4^\xa4\xc7\xf3\x17\u007f7\xce)\xe2-g\x99\x9c\x89\n\u05ce\xbcZ\xc6 \x00\x00\u07d4\x81\x13\x9b\xfd\u0326V\xc40 ?r\x95\x8cT;e\x80\xd4\f\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\x81\x14a\xa2\xb0\u0290\xba\xda\xc0j\x9e\xa1nx{3\xb1\x96\u0309\b\xe3\xf5\v\x17<\x10\x00\x00\u07d4\x81\x16M\xeb\x10\x81J\xe0\x83\x91\xf3,\bf{bH\xc2}z\x89\x15[\xd90\u007f\x9f\xe8\x00\x00\u07d4\x81\x18i1\x18A7\xd1\x19*\u020c\xd3\xe1\xe5\xd0\xfd\xb8jt\x89\x9d5\x95\xab$8\xd0\x00\x00\u0794\x81*U\xc4<\xae\xdcYr\x187\x90\x00\xceQ\rT\x886\xfd\x88\xfc\x93c\x92\x80\x1c\x00\x00\u07d4\x81.\xa7\xa3\xb2\xc8n\xed2\xffO,sQL\xc6;\xac\xfb\u038965\u026d\xc5\u07a0\x00\x00\u07d4\x814\xdd\x1c\x9d\xf0\xd6\u0225\x81$&\xbbU\xc7a\u0283\x1f\b\x89\x06\xa2\x16\v\xb5|\xcc\x00\x00\u07d4\x81A5\u068f\x98\x11\aW\x83\xbf\x1a\xb6pb\xaf\x8d>\x9f@\x89\x01\x15\x8eF\t\x13\xd0\x00\x00\u07d4\x81I\x8c\xa0{\x0f/\x17\xe8\xbb\xc7\xe6\x1a\u007fJ\xe7\xbef\xb7\x8b\x89\x05\x81\xfb\xb5\xb3;\xb0\x00\x00\u07d4\x81Um\xb2sI\xab\x8b'\x00ID\xedP\xa4n\x94\x1a\x0f_\x89\u063beI\xb0+\xb8\x00\x00\u07d4\x81U\xfalQ\xeb1\xd8\bA-t\x8a\xa0\x86\x10P\x18\x12/\x89e\xea=\xb7UF`\x00\x00\xe0\x94\x81V6\v\xbd7\ta\xce\xcakf\x91\xd7P\x06\xad L\xf2\x8a\bxg\x83&\xea\xc9\x00\x00\x00\u07d4\x81a\xd9@\xc3v\x01\x00\xb9\b\x05)\xf8\xa6\x03%\x03\x0fn\u0709\x10CV\x1a\x88)0\x00\x00\xe0\x94\x81d\xe7\x83\x14\xae\x16\xb2\x89&\xccU=,\xcb\x16\xf3V'\r\x8a\x01\xca\x13N\x95\xfb2\xc8\x00\x00\u07d4\x81e\u02b0\xea\xfbZ2\x8f\xc4\x1a\xc6M\xaeq[.\xef,e\x8965\u026d\xc5\u07a0\x00\x00\u07d4\x81h\xed\xce\u007f)a\xcf)[\x9f\xcdZE\xc0l\xde\xdan\xf5\x89\n\u05ce\xbcZ\xc6 \x00\x00\u07d4\x81m\x97r\xcf\x119\x91\x16\xcc\x1er\xc2lgt\xc9\xed\xd79\x89\n\u05ce\xbcZ\xc6 \x00\x00\u07d4\x81s\xc85djg.\x01R\xbe\x10\xff\xe8Ab\xdd%nL\x89\x1a\xab\xdf!E\xb40\x00\x00\u07d4\x81t\x93\u035b\xc6#p*$\xa5o\x9f\x82\xe3\xfdH\xf3\xcd1\x89\x9eK#\xf1-L\xa0\x00\x00\u07d4\x81y\xc8\tp\x18,\u0177\xd8*M\xf0n\xa9M\xb6:%\xf3\x89'o%\x9d\xe6k\xf4\x00\x00\u07d4\x81z\xc3;\xd8\xf8GVsr\x95\x1fJ\x10\u05e9\x1c\xe3\xf40\x89\n\xd7\xc4\x06\xc6m\xc1\x80\x00\xe0\x94\x81\x8f\xfe'\x1f\u00d75e\xc3\x03\xf2\x13\xf6\xd2\u0689\x89~\xbd\x8a\x016\xe0SB\xfe\u1e40\x00\u07d4\x81\x97\x94\x81!s.c\xd9\xc1H\x19N\xca\xd4n0\xb7I\u0209\xd8\xd7&\xb7\x17z\x80\x00\x00\u07d4\x81\x9a\xf9\xa1\xc2s2\xb1\xc3i\xbb\xda\x1b=\xe1\xc6\xe93\xd6@\x89\x11\t\xe6T\xb9\x8fz\x00\x00\xe0\x94\x81\x9c\u06a506x\xef|\xecY\u050c\x82\x16:\xcc`\xb9R\x8a\x03\x13QT_y\x81l\x00\x00\u07d4\x81\x9e\xb4\x99\vZ\xbaUG\t=\xa1+k<\x10\x93\xdfmF\x8965\u026d\xc5\u07a0\x00\x00\u07d4\x81\xa8\x81\x96\xfa\xc5\xf2<>\x12\xa6\x9d\xecK\x88\x0e\xb7\xd9s\x10\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\x81\xbc\xcb\xff\x8fD4~\xb7\xfc\xa9['\xce|\x95$\x92\xaa\xad\x89\b@\xc1!e\xddx\x00\x00\u07d4\x81\xbdu\xab\xd8e\xe0\xc3\xf0J\vO\xdb\xcbt\xd3@\x82\xfb\xb7\x89\xd8\xd7&\xb7\x17z\x80\x00\x00\u07d4\x81\xc1\x8c*#\x8d\xdcL\xba#\n\a-\xd7\xdc\x10\x1eb\x02s\x89Hz\x9a0E9D\x00\x00\u07d4\x81\xc9\xe1\xae\xe2\xd36]S\xbc\xfd\u0356\xc7\xc58\xb0\xfd~\xec\x89b\xa9\x92\xe5:\n\xf0\x00\x00\u07d4\x81\u03edv\t\x13\xd3\xc3\"\xfc\xc7{I\u00ae9\a\xe7On\x89\n\xad\xec\x98?\xcf\xf4\x00\x00\xe0\x94\x81\xd6\x19\xffW&\xf2@_\x12\x90Lr\xeb\x1e$\xa0\xaa\xeeO\x8a\x04<3\xc1\x93ud\x80\x00\x00\u07d4\x81\xef\u25aev\xc8`\xd1\xc5\xfb\xd3=G\xe8\u0399\x96\xd1W\x8965\u026d\xc5\u07a0\x00\x00\u07d4\x81\xf8\xde,(=_\u052f\xbd\xa8]\xed\xf9v\x0e\xab\xbb\xb5r\x89\xa2\xa1]\tQ\x9b\xe0\x00\x00\u07d4\x82\f\x19)\x11\x96P[e\x05\x9d\x99\x14\xb7\t\v\xe1\u06c7\u0789\a\x96\xe3\xea?\x8a\xb0\x00\x00\u07d4\x82\x1c\xb5\xcd\x05\xc7\uf41f\xe1\xbe`s=\x89c\xd7`\xdcA\x89\xd8\xd7&\xb7\x17z\x80\x00\x00\xe0\x94\x82\x1dy\x8a\xf1\x99\x89\u00ee[\x84\xa7\xa7(<\xd7\xfd\xa1\xfa\xbe\x8a\x04<3\xc1\x93ud\x80\x00\x00\xe0\x94\x82\x1e\xb9\t\x94\xa2\xfb\xf9K\xdc23\x91\x02\x96\xf7o\x9b\xf6\xe7\x8a\x02\x1e\x19\xe0\u027a\xb2@\x00\x00\xe0\x94\x82$\x9f\xe7\x0fa\u01b1o\x19\xa3$\x84\x0f\xdc\x02\x021\xbb\x02\x8a\x02\x036\xb0\x8a\x93c[\x00\x00\u07d4\x82(\xeb\xc0\x87H\x0f\xd6EG\xca(\x1f^\xac\xe3\x04\x14S\xb9\x89j\xcb=\xf2~\x1f\x88\x00\x00\xe0\x94\x82)\u03b9\xf0\xd7\b9I\x8dD\xe6\xab\xed\x93\xc5\xca\x05\x9f]\x8a\x1a\x1c\x1b<\x98\x9a \x10\x00\x00\u07d4\x82.\xdf\xf66V:a\x06\xe5.\x9a%\x98\xf7\xe6\xd0\xef'\x82\x89\x01\xf4\xf9i=B\u04c0\x00\u07d4\x822\x19\xa2Yv\xbb*\xa4\xaf\x8b\xadA\xac5&\xb4\x936\x1f\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\x822\xd1\xf9t.\u07cd\xd9'\xda5;*\xe7\xb4\xcb\xceu\x92\x89$=M\x18\"\x9c\xa2\x00\x00\u07d4\x824\xf4c\u0444\x85P\x1f\x8f\x85\xac\xe4\x97,\x9bc-\xbc\u0309lk\x93[\x8b\xbd@\x00\x00\u07d4\x827htg7\xcem\xa3\x12\xd5>TSN\x10o\x96|\xf3\x89\x01\x15\x8eF\t\x13\xd0\x00\x00\u07d4\x82;\xa7dr8\xd1\x13\xbc\xe9\x96JC\u0420\x98\x11\x8b\xfeM\x89\n\u05ce\xbcZ\xc6 \x00\x00\u07d4\x82@t1(\x06\xdaGHCBf\xee\x00!@\u305a\u0089Q\xb1\u04c3\x92a\xac\x00\x00\u07d4\x82C\x8f\u04b3*\x9b\xddgKI\xd8\xcc_\xa2\xef\xf9x\x18G\x89\x01\x15\x8eF\t\x13\xd0\x00\x00\u07d4\x82HW(\xd0\xe2\x81V7X\xc7Z\xb2~\xd9\u80a0\x00-\x89\a\xf8\b\xe9)\x1el\x00\x00\u07d4\x82K<<D>\x19)]~\xf6\xfa\xa7\xf3t\xa4y\x84\x86\xa8\x89\x01\x15\x8eF\t\x13\xd0\x00\x00\u07d4\x82Q5\x8c\xa4\xe0`\u0775Y\xcaX\xbc\v\u077e\xb4\a\x02\x03\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\x82Q5\xb1\xa7\xfc\x16\x05aL\x8a\xa4\u042cm\xba\u040fH\x0e\x89M\x85<\x8f\x89\b\x98\x00\x00\u07d4\x82S\t\xa7\xd4]\x18\x12\xf5\x1en\x8d\xf5\xa7\xb9ol\x90\x88\x87\x89\x804\xf7\u0671f\xd4\x00\x00\u07d4\x82Z\u007fN\x10\x94\x9c\xb6\xf8\x96Bh\xf1\xfa_W\xe7\x12\xb4\u0109\x01\x15\x8eF\t\x13\xd0\x00\x00\u07d4\x82a\xfa#\f\x90\x1dC\xffW\x9fG\x80\u04d9\xf3\x1e`v\xbc\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\x82b\x16\x9baXp\x13N\xb4\xacl_G\x1ck\xf2\xf7\x89\xfc\x89\x19\x12z\x13\x91\xea*\x00\x00\u07d4\x82c\xec\xe5\xd7\t\xe0\u05eeq\u0328h\xed7\xcd/\xef\x80{\x895\xab\x02\x8a\xc1T\xb8\x00\x00\xe0\x94\x82l\xe5y\x052\xe0T\x8ca\x02\xa3\r>\xac\x83k\xd68\x8f\x8a\x03\xcf\xc8.7\xe9\xa7@\x00\x00\u07d4\x82n\xb7\xcds\x19\xb8-\xd0z\x1f;@\x90q\xd9n9g\u007f\x8965\u026d\xc5\u07a0\x00\x00\u07d4\x82u1\xa6\u0141z\xe3_\x82\xb0\v\x97T\xfc\xf7LU\xe22\x89\xc3(\t>a\xee@\x00\x00\u0794\x82u\xcdhL6y\u0548}\x03fN3\x83E\xdc<\xdd\xe1\x88\xdbD\xe0I\xbb,\x00\x00\u07d4\x82\x84\x92;b\u62ff|+\x9f4\x14\xd1>\xf6\xc8\x12\xa9\x04\x89\xd2U\xd1\x12\xe1\x03\xa0\x00\x00\u07d4\x82\x8b\xa6Q\u02d3\x0e\xd9xqV)\x9a=\xe4L\u040br\x12\x89Hz\x9a0E9D\x00\x00\u07d4\x82\xa1\\\xef\x1dl\x82`\xea\xf1Y\xea?\x01\x80\xd8g}\xce\x1c\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\x82\xa8\xb9kl\x9e\x13\xeb\xec\x1e\x9f\x18\xac\x02\xa6\x0e\xa8\x8aH\xff\x89lk\x8c@\x8es\xb3\x00\x00\u07d4\x82\xa8\u02ff\xdf\xf0+.8\xaeK\xbf\xca\x15\xf1\xf0\xe8;\x1a\xea\x89\x04\x9b\x99\x1c'\xefm\x80\x00\u07d4\x82\xe4F\x1e\xb9\xd8I\xf0\x04\x1c\x14\x04!\x9eBr\u0110\n\xb4\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\x82\xe5w\xb5\x15\xcb+\b`\xaa\xfe\x1c\xe0\x9aY\xe0\x9f\xe7\xd0@\x89 \x86\xac5\x10R`\x00\x00\u07d4\x82\xea\x01\xe3\xbf.\x83\x83nqpN\"\xa2q\x93w\xef\xd9\u00c9\xa4\xccy\x95c\u00c0\x00\x00\u07d4\x82\xf2\xe9\x91\xfd2L_]\x17v\x8e\x9fa3]\xb61\x9dl\x89\x1b\x1a\xe4\xd6\xe2\xefP\x00\x00\xe0\x94\x82\xf3\x9b'X\xaeB'{\x86\u059fu\xe6(\xd9X\xeb\u02b0\x8a\bxg\x83&\xea\xc9\x00\x00\x00\xe0\x94\x82\xf8T\xc9\xc2\xf0\x87\xdf\xfa\x98Z\xc8 \x1ebl\xa5Fv\x86\x8a\x15-\x02\xc7\xe1J\xf6\x80\x00\x00\u07d4\x82\xffqo\xdf\x03>\xc7\xe9B\xc9\t\u0643\x18g\xb8\xb6\xe2\xef\x89a\t=|,m8\x00\x00\u07d4\x83\b\xed\n\xf7\xf8\xa3\xc1u\x1f\xaf\xc8w\xb5\xa4*\xf7\xd3X\x82\x8965\u026d\xc5\u07a0\x00\x00\u07d4\x83\x1cD\xb3\b@G\x18K*\xd2\x18h\x06@\x907P\xc4]\x89j\xcb=\xf2~\x1f\x88\x00\x00\u07d4\x83!\x05\x83\xc1jN\x1e\x1d\xac\x84\xeb\xd3~=\x0f|W\ub909lk\x93[\x8b\xbd@\x00\x00\u07d4\x83,T\x17k\xdfC\xd2\u027c\u05f8\b\xb8\x95V\xb8\x9c\xbf1\x89\n\u05ce\xbcZ\xc6 \x00\x00\u07d4\x833\x16\x98]Gt+\xfe\xd4\x10`J\x91\x95<\x05\xfb\x12\xb0\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\x834vK{9zNW\x8fP6M`\xceD\x89\x9b\xff\x94\x89\x05\x03\xb2\x03\xe9\xfb\xa2\x00\x00\xe0\x94\x83;j\x8e\xc8\xda@\x81\x86\xac\x8a}*m\xd6\x15#\xe7\u0384\x8a\x03c\\\x9a\xdc]\xea\x00\x00\x00\u07d4\x83=?\xaeT*\xd5\xf8\xb5\f\xe1\x9b\xde+\xecW\x91\x80\u020c\x89\x12\xc1\xb6\xee\xd0=(\x00\x00\xe0\x94\x83=\xb4,\x14\x16<{\xe4\u02b8j\u0153\xe0bf\u0599\u054a$\xe4\r+iC\xef\x90\x00\x00\xe0\x94\x83V;\xc3d\ud060\xc6\xda;V\xffI\xbb\xf2g\x82z\x9c\x8a\x03\xab\x91\xd1{ \xdeP\x00\x00\u07d4\x83zd]\xc9\\IT\x9f\x89\x9cN\x8b\u03c7S$\xb2\xf5|\x89 \x8c9J\xf1\u0208\x00\x00\u07d4\x83\x8b\xd5e\xf9\x9f\xdeH\x05?y\x17\xfe3<\xf8J\xd5H\xab\x89\n\u05ce\xbcZ\xc6 \x00\x00\u07d4\x83\x90\x8a\xa7G\x8am\x1c\x9b\x9b\x02\x81\x14\x8f\x8f\x9f$+\x9f\u0709lk\x93[\x8b\xbd@\x00\x00\u07d4\x83\x92\xe57vq5x\x01[\xffI@\xcfC\x84\x9d}\u02e1\x89\bM\xf05]V\x17\x00\x00\xe0\x94\x83\x97\xa1\xbcG\xac\xd6GA\x81Y\xb9\x9c\xeaW\xe1\xe6S-n\x8a\x01\xf1\x0f\xa8'\xb5P\xb4\x00\x00\u07d4\x83\x98\xe0~\xbc\xb4\xf7_\xf2\x11m\xe7|\x1c*\x99\xf3\x03\xa4\u03c9\x1b\x1a\xe4\xd6\xe2\xefP\x00\x00\u07d4\x83\xa3\x14\x883\xd9dI\x84\xf7\xc4u\xa7\x85\a\x16\ufd00\xff\x89\xb8Pz\x82\a( \x00\x00\u07d4\x83\xa4\x02C\x8e\x05\x19w=TH2k\xfba\xf8\xb2\f\xf5-\x89Rf<\u02b1\xe1\xc0\x00\x00\u07d4\x83\xa9;[\xa4\x1b\xf8\x87 \xe4\x15y\f\xdc\vg\xb4\xaf4\u0109\n\u05ce\xbcZ\xc6 \x00\x00\xe0\x94\x83\xc2=\x8aP!$\xee\x15\x0f\b\xd7\x1d\xc6rt\x10\xa0\xf9\x01\x8a\a3\x1f;\xfef\x1b\x18\x00\x00\u07d4\x83\u0217\xa8Ki^\xeb\xe4fy\xf7\xda\x19\xd7vb\x1c&\x94\x89\x1b\x1a\xe4\xd6\xe2\xefP\x00\x00\u07d4\x83\xd52\u04cdm\xee?`\xad\u018b\x93a3\u01e2\xa1\xb0\u0749\x1b\x1a\xe4\xd6\xe2\xefP\x00\x00\u07d4\x83\xdb\xf8\xa1(S\xb4\n\xc6\x19\x96\xf8\xbf\x1d\xc8\xfd\xba\xdd\xd3)\x894\x95tD\xb8@\xe8\x00\x00\u07d4\x83\xdb\xfd\x8e\xda\x01\xd0\u078e\x15\x8b\x16\u0413_\xc28\n]\u01c9 \x86\xac5\x10R`\x00\x00\u07d4\x83\xe4\x80U2|(\xb5\x93o\xd9\xf4D~s\xbd\xb2\xdd3v\x89\x90\xf54`\x8ar\x88\x00\x00\xe0\x94\x83\xfeZ\x1b2\x8b\xaeD\a\x11\xbe\xafj\xad`&\xed\xa6\xd2 \x8a\x04<3\xc1\x93ud\x80\x00\x00\u07d4\x84\x00\x8ar\xf8\x03o?\xeb\xa5B\xe3Px\xc0W\xf3*\x88%\x89\x05k\xc7^-c\x10\x00\x00\u07d4\x84\x0e\xc8>\xa96!\xf04\xe7\xbb7b\xbb\x8e)\xde\xd4\xc4y\x89\x87\x86x2n\xac\x90\x00\x00\xe0\x94\x84\x11E\xb4H@\xc9F\xe2\x1d\xbc\x19\x02d\xb8\xe0\xd5\x02\x93i\x8a?\x87\bW\xa3\xe0\xe3\x80\x00\x00\u07d4\x84#!\a\x93+\x12\xe01\x86X5%\xce\x02:p>\xf8\u0649lk\x93[\x8b\xbd@\x00\x00\u07d4\x84$O\xc9ZiW\xed|\x15\x04\xe4\x9f0\xb8\xc3^\xcaKy\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\x841'}{\xdd\x10E}\xc0\x17@\x8c\x8d\xbb\xbdAJ\x8d\xf3\x89\x02\"\xc8\xeb?\xf6d\x00\x00\u07d4\x847Z\xfb\xf5\x9b:\x1da\xa1\xbe2\xd0u\xe0\xe1ZO\xbc\xa5\x89\n\u05ce\xbcZ\xc6 \x00\x00\u07d4\x84;\xd3P/E\xf8\xbcM\xa3p\xb3#\xbd\xac?\xcf_\x19\xa6\x89P\x03\x9dc\xd1\x1c\x90\x00\x00\u07d4\x84P34c\rw\xf7AG\xf6\x8b.\bf\x13\xc8\xf1\xad\xe9\x89V\xbcu\xe2\xd61\x00\x00\x00\u07d4\x84R\x03u\x0fqH\xa9\xaa&)!\xe8mC\xbfd\x19t\xfd\x89\x05k\xc7^-c\x10\x00\x00\u07d4\x84a\xec\u0126\xa4^\xb1\xa5\xb9G\xfb\x86\xb8\x80i\xb9\x1f\xcdo\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\x84g^\x91wrmE\xea\xa4k9\x92\xa3@\xba\u007fq\f\x95\x8965\u026d\xc5\u07a0\x00\x00\u07d4\x84hl{\xadv,T\xb6g\u055f\x90\x94<\xd1M\x11z&\x89\x01\x15\x8eF\t\x13\xd0\x00\x00\u07d4\x84\x89\xf6\xad\x1d\x9a\x94\xa2\x97x\x91V\x89\x9d\xb6AT\xf1\u06f5\x89\x13t\a\xc0<\x8c&\x80\x00\u07d4\x84\x8c\x99Jy\x00?\xe7\xb7\xc2l\xc62\x12\xe1\xfc/\x9c\x19\xeb\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\x84\x8f\xbd)\xd6|\xf4\xa0\x13\xcb\x02\xa4\xb1v\xef$N\x9e\u6349\x01\x17*ck\xbd\xc2\x00\x00\u07d4\x84\x94\x9d\xbaU\x9ac\xbf\xc8E\xde\xd0n\x9f-\x9b\u007f\x11\xef$\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\x84\x9a\xb8\a\x90\xb2\x8f\xf1\xff\u05ba9N\xfctc\x10\\6\xf7\x89\x01\xe0+\xe4\xael\x84\x00\x00\u07d4\x84\x9b\x11oYc\x01\xc5\u063bb\xe0\xe9z\x82H\x12n9\xf3\x89\x10CV\x1a\x88)0\x00\x00\u07d4\x84\xa7L\xee\xcf\xf6\\\xb9;/\x94\x9dw>\xf1\xad\u007f\xb4\xa2E\x89\x05\n\x9bDF\x85\xc7\x00\x00\u07d4\x84\xaa\xc7\xfa\x19\u007f\xf8\\0\xe0;zS\x82\xb9W\xf4\x1f:\xfb\x89\b\x8b#\xac\xff\u0650\x00\x00\u07d4\x84\xaf\x1b\x15sB\xd5Ch&\r\x17\x87b0\xa54\xb5K\x0e\x895e\x9e\xf9?\x0f\xc4\x00\x00\u07d4\x84\xb0\xeek\xb87\u04e4\xc4\xc5\x01\x1c:\"\x8c\x0e\u06b4cJ\x89\x01\x15\x8eF\t\x13\xd0\x00\x00\u07d4\x84\xb4\xb7Nf#\xba\x9d\x15\x83\xe0\u03feId?\x168AI\x89\x01\x15\x8eF\t\x13\xd0\x00\x00\u07d4\x84\xb6\xb6\xad\xbe/[>-h,f\xaf\x1b\u0110S@\xc3\xed\x89!\x92\xf8\xd2\"\x15\x00\x80\x00\xe0\x94\x84\xb9\x1e.)\x02\xd0^+Y\x1bA\b;\u05fe\xb2\xd5,t\x8a\x02\x15\xe5\x12\x8bE\x04d\x80\x00\u07d4\x84\xbc\xbf\"\xc0\x96\a\xac\x844\x1d.\xdb\xc0;\xfb\x179\xd7D\x89\x1b\x1a\xe4\xd6\xe2\xefP\x00\x00\u07d4\x84\xbf\xce\xf0I\x1a\n\xe0iK7\u03ac\x02E\x84\xf2\xaa\x04g\x89lj\xccg\u05f1\xd4\x00\x00\u07d4\x84\xcb}\xa0P-\xf4\\\xf5a\x81{\xbd#b\xf4Q\xbe\x02\u0689Hz\x9a0E9D\x00\x00\u07d4\x84\xccxx\xda`_\xdb\x01\x9f\xab\x9bL\xcf\xc1Wp\x9c\u0765\x89Hy\x85\x13\xaf\x04\xc9\x00\x00\u07d4\x84\xdb\x14Y\xbb\x00\x81.\xa6~\xcb=\xc1\x89\xb7!\x87\xd9\xc5\x01\x89\b\x11\xb8\xfb\u0685\xab\x80\x00\u07d4\x84\u9516\x80\xbe\xcehA\xb9\xa7\xe5%\r\b\xac\xd8}\x16\u0349\n\u05ce\xbcZ\xc6 \x00\x00\u07d4\x84\xe9\u03c1f\xc3j\xbf\xa4\x90S\xb7\xa1\xad@6 &\x81\xef\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\x84\xec\x06\xf2G\x00\xfeBAL\xb9\x89|\x15L\x88\xde/a2\x89Hz\x9a0E9D\x00\x00\xe0\x94\x84\xf5\"\xf0R\x0e\xbaR\xdd\x18\xad!\xfaK\x82\x9f+\x89\u02d7\x8a\x01\fQ\x06\xd5\x13O\x13\x00\x00\u07d4\x85\v\x9d\xb1\x8f\xf8K\xf0\xc7\xdaI\xea7\x81\xd9 \x90\xad~d\x89\x8c\xf2?\x90\x9c\x0f\xa0\x00\x00\u07d4\x85\x10\xee\x93O\f\xbc\x90\x0e\x10\a\xeb8\xa2\x1e*Q\x01\xb8\xb2\x89\x05\xbf\v\xa6cOh\x00\x00\u07d4\x85\x16\xfc\xafw\u0213\x97\x0f\xcd\x1a\x95\x8b\xa9\xa0\x0eI\x04@\x19\x89\n\xa3\xeb\x16\x91\xbc\xe5\x80\x00\u07d4\x85\x1a\xa9\x1c\x82\xf4/\xad]\xd8\xe8\xbb^\xa6\x9c\x8f:Yw\u0449\b\x0eV\x1f%xy\x80\x00\u07d4\x85\x1c\rb\xbeF5\xd4w~\x805\xe3~K\xa8Q|a2\x89\x1b\x1a\xe4\xd6\xe2\xefP\x00\x00\u07d4\x85\x1d\u00ca\xdbE\x93r\x9av\xf3:\x86\x16\u06b6\xf5\xf5\x9aw\x89\x05k\xc7^-c\x10\x00\x00\u07d4\x852I\b\x97\xbb\xb4\u038b\u007fk\x83~L\xba\x84\x8f\xbe\x99v\x89\x05k\xc7^-c\x10\x00\x00\u07d4\x85>j\xba\xf4Di\xc7/\x15\x1dN\"8\x19\xac\xedN7(\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\x85F\x91\xceqO2\\\xedU\xceY(\u039b\xa1/\xac\u0478\x89\xedp\xb5\xe9\xc3\xf2\xf0\x00\x00\u07d4\x85L\fF\x9c$k\x83\xb5\u0473\xec\xa4C\xb3\x9a\xf5\xee\x12\x8a\x89V\xbcu\xe2\xd61\x00\x00\x00\u07d4\x85]\x9a\xef,9\xc6#\r\t\u025e\xf6II\x89\xab\u61c5\x89\b\xbaR\xe6\xfcE\xe4\x00\x00\u07d4\x85c\u0113a\xb6%\xe7hw\x1c\x96\x15\x1d\xbf\xbd\x1c\x90iv\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\x85fa\t\x01\xaa\xce8\xb82D\xf3\xa9\xc810jg\xb9\u0709\xb0\x82\x13\xbc\xf8\xff\xe0\x00\x00\xe0\x94\x85j\xa2<\x82\xd7![\xec\x8dW\xf6\n\xd7^\xf1O\xa3_D\x8a\x04<3\xc1\x93ud\x80\x00\x00\u07d4\x85nZ\xb3\xf6L\x9a\xb5k\x00\x93\x93\xb0\x16d\xfc\x03$\x05\x0e\x89a\t=|,m8\x00\x00\u07d4\x85n\xb2\x04$\x1a\x87\x83\x0f\xb2)\x03\x13C\xdc0\x85OX\x1a\x8965\u026d\xc5\u07a0\x00\x00\u07d4\x85s,\x06\\\xbdd\x11\x99A\xae\xd40\xacYg\vlQ\u0109'\xa5sb\xab\n\x0e\x80\x00\xe0\x94\x85x\xe1\x02\x12\xca\x14\xff\a2\xa8$\x1e7F}\xb8V2\xa9\x8a\x01EB\xba\x12\xa37\xc0\x00\x00\u07d4\x85y\xda\xdf\x1a9Z4q\xe2\vov=\x9a\x0f\xf1\x9a?o\x89\xd8\xd7&\xb7\x17z\x80\x00\x00\u07d4\x85\u007f\x10\v\x1aY0\"^\xfc~\x90 \u05c3'\xb4\x1c\x02\u02c9lk\x93[\x8b\xbd@\x00\x00\u07d4\x85\x94mV\xa4\xd3q\xa93hS\x96\x90\xb6\x0e\xc8%\x10tT\x89]\u0212\xaa\x111\xc8\x00\x00\xe0\x94\x85\x99\xcb\u0566\xa9\xdc\u0539f\xbe8}iw]\xa5\xe3<o\x8a\fQ\xf1\xb1\xd5&\"\x90\x00\x00\u07d4\x85\x9c`\f\xf1=\x1d\x02s\xd5\xd1\xda<\u05c9\u4549\x9f'\x89\x90\xf54`\x8ar\x88\x00\x00\u07d4\x85\xa2\xf6\xea\x94\xd0^\x8c\x1d\x9a\xe2\xf4\x91\x038\xa3X\xe9\x8d\xed\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\x85\xb1o\v\x8b4\xdf\xf3\x80Oi\xe2\x16\x8aO{$\xd1\x04+\x89\x11/B<vF\xd4\x00\x00\xe0\x94\x85\xb2\x99\x8d\fs0,\xb2\xba\x13\xf4\x8913\x01\xe0S\xbe\x15\x8a\x02\x1e\x19\xe0\u027a\xb2@\x00\x00\u07d4\x85\xbbQ\xbc;\xfe\x9a\x1b*/k\x1c\u0695\xbc\xa8\xb3\x8c\x8d^\x89\x11q-\xa0K\xa1\xef\x00\x00\u07d4\x85\xc8\xf3\xccz5O\xea\u025a^{\xfe|\u07e3Q\xcf\xe3U\x89\x15\xaf\x1dx\xb5\x8c@\x00\x00\u0794\x85\xca\x1er~\x9d\x1a\x87\x99\x1c\xc2\xc4\x18@\xeb\xb9\xed\xf2\x1d\x1b\x88\xb9\x8b\xc8)\xa6\xf9\x00\x00\u07d4\x85\u028b\xc6\xda(\x03\xd0r_^\x1aEl\x89\xf9\xbcwN/\x89 \x86\xac5\x10R`\x00\x00\u07d4\x85\xd0\u0607T\xac\x84\xb8\xb2\x1b\xa9=\u04bf\xecrbo\xab\xa8\x8965\u026d\xc5\u07a0\x00\x00\u07d4\x85\xeb%kQ\xc8\x19\xd6\x0e\xa6\x1a\x82\xd1,\x93X\u055c\x1c\xae\x89\x18\xef\xc8J\xd0\u01f0\x00\x00\u07d4\x85\xf0\xe7\xc1\xe3\xaf\xf8\x05\xa6'\xa2\xaa\xf2\xcf\xf6\xb4\xc0\xdb\xe9\u02c9\x01\x15\x8eF\t\x13\xd0\x00\x00\u07d4\x86\x02l\xad?\xe4\xea\x1c\xe7\xfc\xa2`\xd3\xd4^\xb0\x9e\xa6\xa3d\x89\n\u05ce\xbcZ\xc6 \x00\x00\xe0\x94\x86\x0f_\xfc\x10\xdev}\xed\x80\u007fq\xe8a\xd6G\xdf\xd2\x19\xb1\x8a\x02\x1e\x19\xe0\u027a\xb2@\x00\x00\u07d4\x86\x150c\xa1\xae\u007f\x02\xf1\xa8\x816\xd4\u059c|^>C'\x8965\u026d\xc5\u07a0\x00\x00\u07d4\x86$_Yf\x91\t>\xce?=<\xa2&>\xac\xe8\x19A\u0649\n1\x06+\xee\xedp\x00\x00\u07d4\x86%i!\x1e\x8cc'\xb5A^:g\xe5s\x8b\x15\xba\xafn\x89\a\x96\xe3\xea?\x8a\xb0\x00\x00\u07d4\x86)}s\x0f\xe0\xf7\xa9\xee$\xe0\x8f\xb1\b{1\xad\xb3\x06\xa7\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\x86D\xcc(\x1b\xe32\xcc\xce\xd3m\xa4\x83\xfb*\aF\u067a.\x89\x15\xaf\x1dx\xb5\x8c@\x00\x00\u07d4\x86I\x9a\x12(\xff-~\xe3\au\x93dPo\x8e\x8c\x83\a\xa5\x89j\xcb=\xf2~\x1f\x88\x00\x00\u07d4\x86K\xecPi\xf8U\xa4\xfdX\x92\xa6\xc4I\x1d\xb0|\x88\xff|\x8965\u026d\xc5\u07a0\x00\x00\u07d4\x86W\n\xb2Y\u0271\xc3,\x97) /w\xf5\x90\xc0}\xd6\x12\x89\n\u05ce\xbcZ\xc6 \x00\x00\xe0\x94\x86c\xa2A\xa0\xa8\x9ep\xe1\x82\xc8E\xe2\x10\\\x8a\xd7&K\u03ca\x03#\xb1=\x83\x98\xf3#\x80\x00\u07d4\x86g\xfa\x11U\xfe\xd72\u03f8\u0725\xa0\xd7e\xce\r\a\x05\xed\x89\x04n\xc9e\u00d3\xb1\x00\x00\u07d4\x86h\xaf\x86\x8a\x1e\x98\x88_\x93\u007f&\x15\xde\xd6u\x18\x04\xeb-\x89\x01\x15\x8eF\t\x13\xd0\x00\x00\xe0\x94\x86t\nFd\x8e\x84Z]\x96F\x1b\x18\t\x1f\xf5{\xe8\xa1o\x8a\x14\xc0\x974\x85\xbf9@\x00\x00\xe0\x94\x86~\xbaVt\x8aY\x045\r,\xa2\xa5\u039c\xa0\vg\n\x9b\x8a\x04<3\xc1\x93ud\x80\x00\x00\xe0\x94\x86\x80dt\xc3X\x04}\x94\x06\xe6\xa0\u007f@\x94[\xc82\x8eg\x8a\x01u.\xb0\xf7\x01=\x10\x00\x00\u07d4\x86\x88=T\xcd9\x15\xe5I\tU0\xf9\xab\x18\x05\xe8\xc5C-\x89\xd8\xd7&\xb7\x17z\x80\x00\x00\u07d4\x86\x8c#\xbe\x874f\xd4\xc7L\"\n\x19\xb2E\xd1x~\x80\u007f\x89J\x13\xbb\xbd\x92\u020e\x80\x00\xe0\x94\x86\x92O\xb2\x11\xaa\xd2<\xf5\xce`\x0e\n\xae\x80c\x96D@\x87\x8a\x02\x1e\x19\xe0\u027a\xb2@\x00\x00\u07d4\x86\x93\u9e3e\x94B^\xefyi\xbci\xf9\xd4/|\xadg\x1e\x8967\tlK\xcci\x00\x00\xe0\x94\x86\x9f\x1a\xa3\x0eDU\xbe\xb1\x82 \x91\xde\\\xad\xecy\xa8\xf9F\x8a\x01\xb1\xaeMn.\xf5\x00\x00\x00\u07d4\x86\xa1\xea\xde\xeb0F\x13E\xd9\xefk\xd0R\x16\xfa$|\r\f\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\x86\xa5\xf8%\x9e\u0570\x9e\x18\x8c\xe3F\xee\x92\xd3J\xa5\u0753\xfa\x89\n\u05ce\xbcZ\xc6 \x00\x00\xe0\x94\x86\xb7\xbdV<\uad86\xf9bD\xf9\xdd\xc0*\u05f0\xb1K\u008a\x02\x1e\x19\xe0\u027a\xb2@\x00\x00\u07d4\x86\u008bVx\xaf7\xd7'\xec\x05\xe4Dw\x90\xf1_q\xf2\xea\x89\n\u05ce\xbcZ\xc6 \x00\x00\xe0\x94\x86\xc4\xce\x06\u066c\x18[\xb1H\xd9o{z\xbes\xf4A\x00m\x8a\x02\x1e\x19\xe0\u027a\xb2@\x00\x00\xe0\x94\x86\xc8\xd0\u0642\xb59\xf4\x8f\x980\xf9\x89\x1f\x9d`z\x94&Y\x8a\x02\xce\xd3wa\x82O\xb0\x00\x00\u07d4\x86\xc94\xe3\x8eS\xbe;3\xf2t\xd0S\x9c\xfc\xa1Y\xa4\xd0\u04494\x95tD\xb8@\xe8\x00\x00\xe0\x94\x86\xca\x01E\x95~k\r\xfe6\x87_\xbez\r\xecU\xe1z(\x8a\x02\x1e\x19\xe0\u027a\xb2@\x00\x00\xe0\x94\x86\u02af\xac\xf3*\xa01|\x03*\xc3k\xab\xed\x97G\x91\xdc\x03\x8a\bxg\x83&\xea\xc9\x00\x00\x00\u07d4\x86\u0377\xe5\x1a\xc4Gr\xbe6\x90\xf6\x1d\x0eYvn\x8b\xfc\x18\x89\xd8\xd7&\xb7\x17z\x80\x00\x00\u07d4\x86\xdfs\xbd7\u007f,\t\xdec\xc4]g\xf2\x83\xea\xef\xa0\xf4\xab\x8965\u026d\xc5\u07a0\x00\x00\u07d4\x86\xe3\xfe\x86\xe9=\xa4\x86\xb1Bf\xea\xdf\x05l\xbf\xa4\xd9\x14C\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\x86\xe8g\x0e'Y\x8e\xa0\x9c8\x99\xabw\x11\u04f9\xfe\x90\x1c\x17\x89\n\u05ce\xbcZ\xc6 \x00\x00\xe0\x94\x86\xefd&!\x19I\xcc7\xf4\xc7^xP6\x9d\f\xf5\xf4y\x8a\x02\xd6_2\xea\x04Z\xf6\x00\x00\u07d4\x86\xf0]\x19\x06>\x93i\xc6\x00N\xb3\xf1#\x94:|\xffN\xab\x89lj\xccg\u05f1\xd4\x00\x00\u07d4\x86\xf2>\x9c\n\xaf\u01cb\x9c@M\xcd`3\x9a\x92[\xff\xa2f\x89\x15\xaf\x1dx\xb5\x8c@\x00\x00\u07d4\x86\xf4\xf4\n\u0644\xfb\xb8\t3\xaebn\x0eB\xf93?\xddA\x8965\u026d\xc5\u07a0\x00\x00\xe0\x94\x86\xf9\\[\x11\xa2\x93\x94\x0e5\xc0\xb8\x98\u0637_\b\xaa\xb0m\x8a\x06D\xe3\xe8u\xfc\xcft\x00\x00\u07d4\x86\xff\xf2 \xe5\x93\x05\xc0\x9fH8`\xd6\xf9N\x96\xfb\xe3/W\x89\x02S[j\xb4\xc0B\x00\x00\u07d4\x87\a\x96\xab\xc0\u06c4\xaf\x82\xdaR\xa0\xedhsM\xe7\xe66\xf5\x89\x10CV\x1a\x88)0\x00\x00\u07d4\x87\x0f\x15\xe5\u07cb\x0e\xab\xd0%iSz\x8e\xf9;Vx\\B\x89\x15\b\x94\xe8I\xb3\x90\x00\x00\u07d4\x87\x181`\xd1r\xd2\xe0\x84\xd3'\xb8k\xcb|\x1d\x8eg\x84\xef\x89\xd8\xd8X?\xa2\xd5/\x00\x00\xe0\x94\x87\x1b\x8a\x8bQ\u07a1\x98\x9aY!\xf1>\xc1\xa9U\xa5\x15\xadG\x8a\x01\xb1\xaeMn.\xf5\x00\x00\x00\u07d4\x87%\xe8\xc7S\xb3\xac\xbf\u0725_<b\xdf\u1954T\x96\x8a\x8967\tlK\xcci\x00\x00\u07d4\x877\xda\xe6q\x82:\x8dY\x17\xe0\x15z\u039cCF\x8d\x94k\x89lj\xccg\u05f1\xd4\x00\x00\u07d4\x87;\u007fxm<\x99\xff\x01,J|\xae&w'\x02@\xb9\u0149]\u0212\xaa\x111\xc8\x00\x00\u07d4\x87<op\ufdb1\xd0\xf2\xbb\xc5~\xeb\xcdpa|l\xe6b\x896\xf0\xd5']\tW\x00\x00\u07d4\x87>I\x13\\3\x91\x99\x10`)\n\xa7\xf6\u0338\xf8Zx\u06c9\x01\x15\x8eF\t\x13\xd0\x00\x00\u07d4\x87Pa\xee\x12\xe8 \x04\x1a\x01\x94,\xb0\xe6[\xb4'\xb0\x00`\x89\x97\xc9\xceL\xf6\xd5\xc0\x00\x00\u07d4\x87XJ?a;\xd4\xfa\xc7L\x1ex\v\x86\xd6\xca\xeb\x89\f\xb2\x89\\(=A\x03\x94\x10\x00\x00\u07d4\x87d\xd0'\"\x00\t\x96\xec\xd4u\xb43)\x8e\x9fT\v\x05\xbf\x89\n\u05ce\xbcZ\xc6 \x00\x00\u07d4\x87l?!\x8bGv\xdf<\xa9\xdb\xfb'\r\xe1R\xd9N\xd2R\x89\x05k\xc7^-c\x10\x00\x00\u07d4\x87u\xa6\x10\xc5\x02\xb9\xf1\xe6\xadL\xda\u06cc\xe2\x9b\xffu\xf6\xe4\x89 \x86\xac5\x10R`\x00\x00\u07d4\x87vN6w\xee\xf6\x04\xcb\u015a\xed$\xab\xdcVk\t\xfc%\x89\xa2\xa1]\tQ\x9b\xe0\x00\x00\xe0\x94\x87\x87\xd1&w\xa5\xec)\x1eW\xe3\x1f\xfb\xfa\xd1\x05\xc32K\x87\x8a\x02\xa2N\xb52\b\xf3\x12\x80\x00\u07d4\x87\x94\xbfG\xd5E@\xec\xe5\xc7\"7\xa1\xff\xb5\x11\u0777Gb\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\x87\xa5>\xa3\x9fY\xa3[\xad\xa85%!dU\x94\xa1\xa7\x14\u02c9g\x8a\x93 b\xe4\x18\x00\x00\u07d4\x87\xa7\xc5\b\xefqX-\u0665Cr\xf8\x9c\xb0\x1f%/\xb1\x80\x89\n\u05ce\xbcZ\xc6 \x00\x00\xe0\x94\x87\xaf%\xd3\xf6\xf8\xee\xa1S\x13\xd5\xfeEW\xe8\x10\xc5$\xc0\x83\x8a\x04+\xf0kx\xed;P\x00\x00\u07d4\x87\xb1\x0f\x9c(\x00\x98\x17\x9a+v\xe9\u0390\xbea\xfc\x84M\r\x89Hz\x9a0E9D\x00\x00\u07d4\x87\xbf|\xd5\u0629)\xe1\u01c5\xf9\xe5D\x91\x06\xac#$c\u0249\x047\xb1\x1f\xccEd\x00\x00\u07d4\x87\u0118\x17\t4\xb8#=\x1a\xd1\xe7i1}\\G_/@\x897\b\xba\xed=h\x90\x00\x00\u07d4\x87\xcf6\xad\x03\xc9\xea\xe9\x05:\xbbRB\u0791\x17\xbb\x0f*\v\x89\x1b\x1a\xe4\xd6\xe2\xefP\x00\x00\xe0\x94\x87\u05ec\x06S\xcc\xc6z\xa9\xc3F\x9e\xefCR\x19?}\xbb\x86\x8a*Z\x05\x8f\u0095\xed\x00\x00\x00\xe0\x94\x87\xe3\x06+#!\xe9\u07f0\x87\\\u311c\x9b.5\"\xd5\n\x8a\x02\x1e\x19\xe0\u027a\xb2@\x00\x00\u07d4\x87\xe6\x03N\xcf#\xf8\xb5c\x9d_\x0e\xa7\n\"S\x8a\x92\x04#\x89\x11\xc7\xea\x16.x \x00\x00\u07d4\x87\xefm\x8bj|\xbf\x9b\\\x8c\x97\xf6~\xe2\xad\u00a7;?w\x89\n\xdd\x1b\xd2<<H\x00\x00\u07d4\x87\xfb&\xc3\x1eHdMi14 \\\xaeC\xb2\x1f\x18aK\x89JD\x91\xbdm\xcd(\x00\x00\u07d4\x87\xfcF5&9D\xce\x14\xa4lu\xfaJ\x82\x1f9\xce\u007fr\x89\x01\x15\x8eF\t\x13\xd0\x00\x00\u07d4\x87\xfc\xbe|A\x93\xff\xcb\b\x147y\u027e\xc8?\xe7\xfd\xa9\xfc\x89\x05o\x98]8dK\x80\x00\xe0\x94\x88\x01]r\x03\xc5\xe0\"J\xed\xa2\x86\xed\x12\xf1\xa5\x1bx\x933\x8a\x01\x0f\b\xed\xa8\xe5U\t\x80\x00\u07d4\x88\x10l'\xd2\vt\xb4\xb9\x8c\xa6+#+\xd5\xc9t\x11\x17\x1f\x89\n\xad\xec\x98?\xcf\xf4\x00\x00\xe0\x94\x88\x120\x04|!\x1d-[\x00\xd8\xdeLQ9\xde^2'\u01ca\x02\x1e\x19\xe0\u027a\xb2@\x00\x00\u07d4\x88*\xa7\x98\xbfA\xdf\x17\x9f\x85R\x010\xf1\\\xcd\xf5\x9b^X\x89lk\x93[\x8b\xbd@\x00\x00\xe0\x94\x88+\u04e2\xe9\xd7A\x10\xb2Ia\xc57w\xf2/\x1fF\xdc]\x8a\x02\xd4\xca\x05\xe2\xb4<\xa8\x00\x00\xe0\x94\x88,\x8f\x81\x87,y\xfe\xd5!\xcb_\x95\r\x8b\x03#\"\xeai\x8a\bxg\x83&\xea\xc9\x00\x00\x00\u07d4\x88/up\x83\x86e<\x80\x17\x1d\x06c\xbf\xe3\v\x01~\u042d\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\x884I\tdLz\u0513\x0f\xd8s\xca\x1c\r\xa2\xd44\xc0\u007f\x89\a's\x9f\xcb\x00M\x00\x00\u07d4\x884\xb2E4q\xf3$\xfb&\xbe[%\x16k[W&\x02]\x89\x1f\x0f\xf8\xf0\x1d\xaa\xd4\x00\x00\u07d4\x88:x\xae\xab\xaaP\xd8\xdd\xd8W\v\xcd4&_\x14\xb1\x93c\x89\xd2U\"\xfd\xa3y\xa1\x80\x00\u07d4\x88E\xe9\xf9\x0e\x963k\xac<ak\xe9\u0604\x02h>\x00L\x89lk\x93[\x8b\xbd@\x00\x00\xe0\x94\x88F\x92\x8dh2\x89\xa2\xd1\x1d\xf8\xdbz\x94t\x98\x8e\xf0\x13H\x8a\x02\x1e\x19\xe0\u027a\xb2@\x00\x00\u07d4\x88I\x80\xebEe\xc1\x04\x83\x17\xa8\xf4\u007f\u06f4a\x96[\u4049\xd8\xd6\x11\x9a\x81F\x05\x00\x00\xe0\x94\x88Jz9\u0411n\x05\xf1\xc2B\xdfU`\u007f7\u07cc_\u068a\x04\xf4\x84<\x15|\x8c\xa0\x00\x00\u07d4\x88T\x93\xbd\xa3j\x042\x97eF\xc1\xdd\xceq\xc3\xf4W\x00!\x89\v\xbfQ\r\xdf\xcb&\x00\x00\xe0\x94\x88`\x9e\nF[n\x99\xfc\xe9\a\x16mW\xe9\xda\b\x14\xf5\u020a\x04<3\xc1\x93ud\x80\x00\x00\u07d4\x88m\n\x9e\x17\xc9\xc0\x95\xaf.\xa25\x8b\x89\xecpR\x12\ue509\x01\x84\x93\xfb\xa6N\xf0\x00\x00\u07d4\x88y~Xg^\xd5\xccL\x19\x98\a\x83\xdb\xd0\xc9V\bQS\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\x88|\xacA\xcdpo3E\xf2\xd3J\xc3N\x01u*nY\t\x89 F\\\ue7617\x00\x00\u07d4\x88\x88\x8aW\xbd\x96\x87\xcb\xf9P\xae\xea\u03d7@\xdc\xc4\xd1\xefY\x89b\xa9\x92\xe5:\n\xf0\x00\x00\u0794\x88\x89D\x83\x16\xcc\xf1N\xd8m\xf8\xe2\xf4x\xdcc\xc43\x83@\x88\xd2\xf1?w\x89\xf0\x00\x00\u07d4\x88\x8c\x16\x14I3\x19|\xac&PM\xd7n\x06\xfdf\x00\u01c9\x89\x05k\xc7^-c\x10\x00\x00\u07d4\x88\x8e\x94\x91p\x83\xd1R +S\x1699\x86\x9d'\x11u\xb4\x89\xd8\xd7&\xb7\x17z\x80\x00\x00\xe0\x94\x88\x90\x87\xf6o\xf2\x84\xf8\xb5\xef\xbd)I;pg3\xab\x14G\x8a\x02\x15\xf85\xbcv\x9d\xa8\x00\x00\u07d4\x88\x95\xebrb&\xed\xc3\xf7\x8c\u01a5\x15\a{2\x96\xfd\xb9^\x89\u0556{\xe4\xfc?\x10\x00\x00\u07d4\x88\x97Z_\x1e\xf2R\x8c0\v\x83\xc0\xc6\a\xb8\xe8}\u0593\x15\x89\x04\x86\u02d7\x99\x19\x1e\x00\x00\u07d4\x88\x9d\xa4\x0f\xb1\xb6\x0f\x9e\xa9\xbdzE>XL\xf7\xb1\xb4\xd9\xf7\x89\x02+\x1c\x8c\x12'\xa0\x00\x00\u07d4\x88\x9d\xa6b\xebJ\n*\x06\x9d+\xc2K\x05\xb4\xee.\x92\xc4\x1b\x89Z,\x8cTV\xc9\xf2\x80\x00\u07d4\x88\xa1\"\xa28,R91\xfbQ\xa0\u032d;\xeb[rY\u00c9lk\x93[\x8b\xbd@\x00\x00\u07d4\x88\xa2\x15D0\xc0\xe4\x11G\xd3\xc1\xfe\u3cf0\x06\xf8Q\xed\xbd\x8965f3\xeb\xd8\xea\x00\x00\u07d4\x88\xb2\x17\u0337\x86\xa2T\xcfM\xc5\u007f]\x9a\xc3\xc4U\xa3\x04\x83\x892$\xf4'#\xd4T\x00\x00\xe0\x94\x88\xbcC\x01.\xdb\x0e\xa9\xf0b\xacCxC%\n9\xb7\x8f\xbb\x8a\x04<3\xc1\x93ud\x80\x00\x00\u07d4\x88\xc2Qj|\xdb\t\xa6'mr\x97\xd3\x0fZM\xb1\xe8K\x86\x89\xd8\xd7&\xb7\x17z\x80\x00\x00\xe0\x94\x88\xc3ad\rki7;\b\x1c\xe0\xc43\xbdY\x02\x87\xd5\xec\x8a\n\x96\x81c\xf0\xa5{@\x00\x00\u07d4\x88\xd5A\xc8@\xceC\xce\xfb\xafm\x19\xafk\x98Y\xb5s\xc1E\x89\t79SM(h\x00\x00\u07d4\x88\xde\x13\xb0\x991\x87|\x91\rY1e\xc3d\u0221d\x1b\u04c9\xa2\xa1]\tQ\x9b\xe0\x00\x00\u07d4\x88\xde\u017d?N\xba-\x18\xb8\xaa\xce\xfa{r\x15H\xc3\x19\xba\x89JD\x91\xbdm\xcd(\x00\x00\u07d4\x88\xe6\xf9\xb2G\xf9\x88\xf6\xc0\xfc\x14\xc5o\x1d\xe5>\u019dC\u0309\x05k\xc7^-c\x10\x00\x00\u07d4\x88\xee\u007f\x0e\xfc\x8fw\x8ckh~\xc3+\xe9\xe7\xd6\xf0 \xb6t\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\x88\xf1\x04_\x19\xf2\xd3\x19\x18\x16\xb1\xdf\x18\xbbn\x145\xad\x1b8\x89\r\x02\xabHl\xed\xc0\x00\x00\xe0\x94\x89\x00\x9e<d\x88\xbd^W\r\x1d\xa3N\xab\xe2\x8e\xd0$\xde\x1b\x8a\x04<3\xc1\x93ud\x80\x00\x00\u07d4\x89\x05D0\xdc\xdc(\xac\x15\xfac^\xf8|\x10^`+\xf7\f\x89\x05\xda\xcd\x13\u029e0\x00\x00\xe0\x94\x89\bv\f\u04db\x9c\x1e\x81\x84\xe6\xa7R\ue20e?\vpE\x8a\x01EB\xba\x12\xa37\xc0\x00\x00\xe0\x94\x89\x0f\xe1\x1f<$\u06c72\xd6\xc2\xe7r\xe2)|~e\xf19\x8a\rV'\x13}\xa8\xb5\x90\x00\x00\u07d4\x89\x14\xa6\x80\xa5\xae\xc5\"mK\xaa\xec.UR\xb4M\xd7\xc8t\x89\x05l\xd5_\xc6M\xfe\x00\x00\u07d4\x89\x1c\xb8#\x8c\x88\xe9:\x1b\xcfa\xdbI\xbd\x82\xb4z\u007fO\x84\x89\x91Hx\xa8\xc0^\xe0\x00\x00\u07d4\x89%\xdaEI\xe1QU\xe5zb\x85\"\u03a9\xdd\xdfb}\x81\x8966\xc2^f\xec\xe7\x00\x00\u07d4\x890\x17\xff\x1a\xda\u0519\xaa\x06T\x01\xb4#l\xe6\xe9+bZ\x89lj\xccg\u05f1\xd4\x00\x00\xe0\x94\x893I\x17`\xc8\xf0\xb4\u07cc\xaa\u01ce\xd85\xca\xee!\x04m\x8a\x04<3\xc1\x93ud\x80\x00\x00\u07d4\x896\bu\x1dh\xd0F\xe8X\x02\x92fs\xcd\xf2\xf5\u007f|\xb8\x89\x01\x11du\x9f\xfb2\x00\x00\u0794\x898\u0474\xda\xeeU\xa5Ms\x8c\xf1~Dw\xf6yNF\xf7\x88\xfc\x93c\x92\x80\x1c\x00\x00\u07d4\x89:l.\xb8\xb4\n\xb0\x96\xb4\xf6~t\xa8\x97\xb8@tn\x86\x89]\u0212\xaa\x111\xc8\x00\x00\u07d4\x89<\xdd\xdfSw\xf3\xc7Q\xbf.T\x11 \x04ZG\u02e1\x01\x89\x05k\xc7^-c\x10\x00\x00\u07d4\x89V\x13#o5\x84!j\xd7\\]>\a\xe3\xfahc\xa7x\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\x89Wr~r\xcfb\x90 \xf4\xe0^\xdfy\x9a\xa7E\x80b\u0409wC\"\x17\xe6\x83`\x00\x00\u07d4\x89]iN\x88\v\x13\xcc\u0404\x8a\x86\xc5\xceA\x1f\x88Gk\xbf\x89\n\xd6\xee\xdd\x17\xcf;\x80\x00\u07d4\x89^\xc5TVD\u0dc30\xff\xfa\xb8\xdd\xea\xc9\xe83\x15l\x89 \x86\xac5\x10R`\x00\x00\u07d4\x89`\tRj,{\f\t\xa6\xf6:\x80\xbd\U0009d707\u079c\x89\xbb\xb8k\x82#\xed\xeb\x00\x00\u07d4\x89g\u05f9\xbd\xb7\xb4\xae\xd2.e\xa1]\xc8\x03\xcbz!?\x10\x89\x15\xaf\x1dx\xb5\x8c@\x00\x00\u07d4\x89n3\\\xa4z\xf5yb\xfa\x0fM\xbf>E\xe6\x88\u02e5\x84\x89J/\xc0\xab`R\x12\x00\x00\u07d4\x89s\xae\xfd^\xfa\xee\x96\t]\x9e(\x8fj\x04l\x977KC\x89\a\xa4\u0120\xf32\x14\x00\x00\u07d4\x89\x8cr\xddseX\xef\x9eK\xe9\xfd\xc3O\xefT\xd7\xfc~\b\x8965\u026d\xc5\u07a0\x00\x00\u07d4\x89\x9b<$\x9f\fK\x81\xdfu\xd2\x12\x00M=m\x95/\xd2#\x89lk\x93[\x8b\xbd@\x00\x00\xe0\x94\x89\xab\x13\xee&mw\x9c5\xe8\xbb\x04\u034a\x90\xcc!\x03\xa9[\x8a\f\xb4\x9bD\xba`-\x80\x00\x00\u07d4\x89\xc43\xd6\x01\xfa\xd7\x14\xdaci0\x8f\xd2l\x1d\u0254+\xbf\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\x89\xd7[\x8e\b1\xe4o\x80\xbc\x17A\x88\x18N\x00o\xde\x0e\xae\x8965\u026d\xc5\u07a0\x00\x00\u07d4\x89\u3d5a\x15\x86G7\u0513\xc1\xd2<\xc5=\xbf\x8d\xcb\x13b\x89\xd8\xd7&\xb7\x17z\x80\x00\x00\u07d4\x89\xfc\x8eM8k\r\v\xb4\xa7\a\xed\xf3\xbdV\r\xf1\xad\x8fN\x89\xa00\xdc\xeb\xbd/L\x00\x00\u07d4\x89\xfe\xe3\r\x17(\xd9l\xec\xc1\u06b3\xda.w\x1a\xfb\u03eaA\x89lj\xccg\u05f1\xd4\x00\x00\xe0\x94\x8a\x1c\u016c\x11\x1cI\xbf\xcf\xd8H\xf3}\xd7h\xaae\u0208\x02\x8a\x02\x1e\x19\xe0\u027a\xb2@\x00\x00\u07d4\x8a \xe5\xb5\xce\xe7\xcd\x1fU\x15\xba\xce;\xf4\xf7\u007f\xfd\xe5\xcc\a\x89\x04V9\x18$O@\x00\x00\xe0\x94\x8a!}\xb3\x8b\xc3_!_\xd9)\x06\xbeBCo\xe7\xe6\xed\x19\x8a\x01EB\xba\x12\xa37\xc0\x00\x00\u07d4\x8a$:\n\x9f\xeaI\xb89TwE\xff-\x11\xaf?K\x05\"\x895e\x9e\xf9?\x0f\xc4\x00\x00\u07d4\x8a$}\x18e\x10\x80\x9fq\xcf\xfcEYG\x1c9\x10\x85\x81!\x89a\t=|,m8\x00\x00\u07d4\x8a4p(-^**\xef\u05e7P\x94\xc8\"\xc4\xf5\xae\uf289\r(\xbc`dx\xa5\x80\x00\u07d4\x8a6\x86\x9a\xd4x\x99|\xbfm\x89$\xd2\n<\x80\x18\xe9\x85[\x89\x01\x15\x8eF\t\x13\xd0\x00\x00\u07d4\x8aC\x14\xfba\u0353\x8f\xc3>\x15\xe8\x16\xb1\x13\U000ac267\xfb\x89\x17vNz\xede\x10\x00\x00\u07d4\x8aOJ\u007fR\xa3U\xba\x10_\xca r\xd3\x06_\xc8\xf7\x94K\x89\x1b\x1a\xe4\xd6\xe2\xefP\x00\x00\u07d4\x8aX1(,\xe1Jezs\r\xc1\x88&\xf7\xf9\xb9\x9d\xb9h\x89\uaf8a[A\xc16\x00\x00\u07d4\x8a_\xb7W\x93\xd0C\xf1\xbc\xd48\x85\xe07\xbd0\xa5(\xc9'\x89\x13Snm.\x9a\xc2\x00\x00\u07d4\x8af\xab\xbc-0\xce!\xa83\xb0\u06ceV\x1dQ\x05\xe0\xa7,\x89%\xf1\xde\\v\xac\xdf\x00\x00\u07d4\x8atl]g\x06G\x11\xbf\xcah[\x95\xa4\xfe)\x1a'\x02\x8e\x89\x02+\x1c\x8c\x12'\xa0\x00\x00\u07d4\x8ax\n\xb8z\x91E\xfe\x10\xed`\xfaGjt\n\xf4\u02b1\u0489\x12\x1b.^ddx\x00\x00\u07d4\x8az\x06\xbe\x19\x9a:X\x01\x9d\x84j\xc9\xcb\xd4\xd9]\xd7W\u0789\xa2\xa4#\x94BV\xf4\x00\x00\u07d4\x8a\x81\x01\x14\xb2\x02]\xb9\xfb\xb5\x00\x99\xa6\xe0\u02de.\xfak\u0709g\x8a\x93 b\xe4\x18\x00\x00\u07d4\x8a\x86\xe4\xa5\x1c\x01;\x1f\xb4\xc7k\xcf0f|x\xd5.\xed\xef\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\x8a\x9e\u029cZ\xba\x8e\x13\x9f\x80\x03\xed\xf1\x16:\xfbp\xaa:\xa9\x89#\xc7W\a+\x8d\xd0\x00\x00\u07d4\x8a\xb89\xae\xaf*\xd3|\xb7\x8b\xac\xbb\xb63\xbc\xc5\xc0\x99\xdcF\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\x8a\u021b\u06780\x1ek\x06w\xfa%\xfc\xf0\xf5\x8f\f\u01f6\x11\x89\x01\x15\x8eF\t\x13\xd0\x00\x00\xe0\x94\x8a\xdcS\xef\x8c\x18\xed0Qx]\x88\xe9\x96\xf3\xe4\xb2\x0e\xcdQ\x8a\b\xe4\xd3\x16\x82v\x86@\x00\x00\u07d4\x8a\xe6\xf8\vp\xe1\xf2<\x91\xfb\u0569f\xb0\xe4\x99\xd9]\xf82\x89\n\xad\xec\x98?\xcf\xf4\x00\x00\u07d4\x8a\xe9\uf30a\x8a\u07e6\xaby\x8a\xb2\xcd\xc4\x05\b*\x1b\xbbp\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\x8a\xf6&\xa5\xf3'\xd7Pe\x89\xee\xb7\x01\x0f\xf9\xc9D` \u0489K\xe4\xe7&{j\xe0\x00\x00\xe0\x94\x8b\x01\xda4\xd4p\xc1\xd1\x15\xac\xf4\xd8\x11<M\u0628\xc38\xe4\x8a\x05W-\xce\xfa\xb6\x97\x90\x00\x00\u07d4\x8b\a\xd0PuM\u027a#\r\xb0\x1c1\n\xfd\xb59Z\xa1\xb3\x89\x06f\xb0nb\xa6 \x00\x00\u07d4\x8b \xad;\x94em\xbd\xc0\xdd!\xa3\x93\u0627\xd9\xe0!8\u02c9\xa2\xa1]\tQ\x9b\xe0\x00\x00\u07d4\x8b'9\"\x06\xb9X\xcd7]~\xf8\xaf,\xf8\xef\x05\x98\xc0\xbc\x8965\u026d\xc5\u07a0\x00\x00\xe0\x94\x8b0\xc0@\x98\u05e7\xe6B\f5~\xa7\xbf\xa4\x9b\xac\x9a\x8a\x18\x8a\x01\xb1\xb1\x13\xf9\x1f\xb0\x14\x00\x00\u07d4\x8b3\x84\x11\xf2l\xcf7e\x8c\xc7U!\xd7v)\t\x9eF}\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\x8b6\"LsV\xe7Q\xf0\xc0f\xc3^;D\x86\x03d\xbf\u00896'\xba\u01e3\xd9'\x80\x00\xe0\x94\x8b6\x96\xf3\xc6\r\xe3$2\xa2\xe4\u00d5\xef\x03\x03\xb7\xe8\x1eu\x8a\x06ZM\xa2]0\x16\xc0\x00\x00\u07d4\x8b9?\xb0\x81>\xe1\x01\xdb\x1e\x14\xec\xc7\xd3\"\xc7+\x8c\x04s\x89\x18\xb2j1>\x8a\xe9\x00\x00\xe0\x94\x8bH\xe1\x9d9\xdd5\xb6nn\x1b\xb6\xb9\xc6W\xcb,\xf5\x9d\x04\x8a\x03\xc7U\xac\x9c\x02J\x01\x80\x00\xe0\x94\x8bP^(q\xf7\u07b7\xa68\x95 \x8e\x82'\u072a\x1b\xff\x05\x8a\f\xf6\x8e\xfc0\x8dy\xbc\x00\x00\u07d4\x8bW\xb2\xbc\x83\u030dM\xe31 N\x89?/;\x1d\xb1\a\x9a\x89\x02+\x1c\x8c\x12'\xa0\x00\x00\u07d4\x8b\\\x91K\x12\x8b\xf1i\\\b\x89#\xfaF~y\x11\xf3Q\xfa\x89\x05V\xf6L\x1f\xe7\xfa\x00\x00\xe0\x94\x8b_)\xcc/\xaa&,\xde\xf3\x0e\xf5T\xf5\x0e\xb4\x88\x14n\xac\x8a\x01;hp\\\x97 \x81\x00\x00\u07d4\x8bpV\xf6\xab\xf3\xb1\x18\xd0&\xe9D\xd5\xc0sC<\xa4Q\u05c965\xc6 G9\u0640\x00\u07d4\x8bqE\"\xfa(9b\x04p\xed\xcf\fD\x01\xb7\x13f=\xf1\x89\n\u05ce\xbcZ\xc6 \x00\x00\xe0\x94\x8bt\xa7\xcb\x1b\xb8\u014f\xce&tf\xa3\x03X\xad\xafR\u007fa\x8a\x02\xe2WxN%\xb4P\x00\x00\u07d4\x8b~\x9fo\x05\xf7\xe3dv\xa1n>q\x00\xc9\x03\x1c\xf4\x04\xaf\x8965\u026d\xc5\u07a0\x00\x00\u07d4\x8b\x81\x15ni\x869\x94<\x01\xa7Rr\xad=5\x85\x1a\xb2\x82\x89\x12\xb3\x16_e\xd3\xe5\x00\x00\u07d4\x8b\x95w\x92\x00S\xb1\xa0\x01\x890M\x88\x80\x10\xd9\xef,\xb4\xbf\x89\x1b\x1a\xe4\xd6\xe2\xefP\x00\x00\u07d4\x8b\x98A\x86.w\xfb\xbe\x91\x94p\x93U\x83\xa9<\xf0'\xe4P\x89llS4B\u007f\x1f\x00\x00\u07d4\x8b\x99}\xbc\a\x8a\xd0)a5]\xa0\xa1Y\xf2\x92~\xd4=d\x89\n\xad\xec\x98?\xcf\xf4\x00\x00\xe0\x94\x8b\x9f\xda}\x98\x1f\xe9\xd6B\x87\xf8\\\x94\xd8?\x90t\x84\x9f\u030a\x02\xf6\xf1\a\x80\xd2,\xc0\x00\x00\u07d4\x8b\xb0!/2\x95\xe0)\u02b1\xd9a\xb0A3\xa1\x80\x9e{\x91\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\x8b\xbe\xac\xfc)\xcf\xe94\x02\xdb<A\u065a\xb7Yf.s\xec\x89lk\x93[\x8b\xbd@\x00\x00\xe0\x94\x8b\xc1\xff\x87\x14\x82\x8b\xf2\x86\xff~\x8aw\t\x10eH\xed\x1b\x18\x8a\x02\x1e\x19\xe0\u027a\xb2@\x00\x00\xe0\x94\x8b\u0436ZP\xef\\\xef\x84\xfe\xc4 \xbe{\x89\xed\x14p\u03b9\x8a\x02\x8aw\x93n\x92\xc8\x1c\x00\x00\u07d4\x8b\u05b1\xc6\xd7M\x01\r\x10\b\u06e6\xef\x83]D0\xb3\\2\x89\x02\xb5\xe3\xaf\x16\xb1\x88\x00\x00\u07d4\x8b\xd8\xd4\xc4\xe9C\xf6\xc8\a9!\xdc\x17\xe3\xe8\u05e0v\x16'\x89\x9f\x04!\x9d\x8d4\x95\x00\x00\u07d4\x8b\xdf\xdal!W \xed\xa2\x13o\x91\x05#!\xafN\x93l\x1f\x8965\xe6\x19\xbb\x04\xd4\x00\x00\u07d4\x8b\xea@7\x93G\xa5\u0211\u055acc1V@\xf5\xa7\xe0z\x89lkv\uf597\f\x00\x00\xe0\x94\x8b\xf0+\xd7Hi\x0e\x1f\xd1\xc7m'\b3\x04\x8bf\xb2_\u04ca\x02\u007f\xad\xe5h\xeb\xa9`\x00\x00\u07d4\x8b\xf2\x97\xf8\xf4SR>\xd6j\x1a\xcbvv\x85c7\xb9;\xf0\x89\xd8\xd7&\xb7\x17z\x80\x00\x00\u07d4\x8b\xf3s\xd0v\x81L\xbcW\xe1\xc6\xd1j\x82\u017e\x13\xc7=7\x89\n\u05ce\xbcZ\xc6 \x00\x00\xe0\x94\x8c\x10#\xfd\xe1WM\xb8\xbbT\xf1s\x96p\x15|\xa4}\xa6R\x8a\x01y\u03da\u00e1\xb1w\x00\x00\u07d4\x8c\x1f\xbe_\n\xea5\x9cZ\xa1\xfa\b\u0209T\x12\u028e\x05\xa6\x8965\u026d\xc5\u07a0\x00\x00\u07d4\x8c\"B`U\xb7o\x11\xf0\xa2\xde\x1a\u007f\x81\x9aa\x96\x85\xfe`\x89kV\x05\x15\x82\xa9p\x00\x00\u07d4\x8c+}\x8b`\x8d(\xb7\u007f\\\xaa\x9c\xd6E$*\x82>L\u0649b\xa9\x92\xe5:\n\xf0\x00\x00\u07d4\x8c/\xbe\ue3ac\xc5\xc5\xd7|\x16\xab\xd4b\ue701E\xf3K\x89i*\xe8\x89p\x81\xd0\x00\x00\u07d4\x8c:\x9e\xe7\x1fr\x9f#l\xba8g\xb4\u05dd\x8c\xee\xe2]\xbc\x89\x05k\xc7^-c\x10\x00\x00\u07d4\x8cP\xaa*\x92\x12\xbc\xdeVA\x8a\xe2a\xf0\xb3^z\x9d\xbb\x82\x89\x15\xaf\x1dx\xb5\x8c@\x00\x00\u07d4\x8cT\xc7\xf8\xb9\x89nu\xd7\xd5\xf5\xc7`%\x86\x99\x95qB\xad\x89\x02+\x1c\x8c\x12'\xa0\x00\x00\u07d4\x8c]\x16\xede\xe3\xed~\x8b\x96\u0297+\xc8as\xe3P\v\x03\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\x8cj\xa8\x82\xee2,\xa8HW\x8c\x06\xcb\x0f\xa9\x11\xd3`\x83\x05\x89 \x86\xac5\x10R`\x00\x00\xe0\x94\x8cj\xe7\xa0Z\x1d\xe5u\x82\xae'h Bv\xc0\xffG\xed\x03\x8a,\v\xb3\xdd0\xc4\xe2\x00\x00\x00\u07d4\x8co\x9fN[z\xe2v\xbfXI{\u05ff*}%$_d\x89\x93\xfe\\W\xd7\x10h\x00\x00\u07d4\x8cu\x95n\x8f\xedP\xf5\xa7\xdd|\xfd'\xda \x0fgF\xae\xa6\x8965\u026d\xc5\u07a0\x00\x00\u07d4\x8c|\xb4\xe4\x8b%\x03\x1a\xa1\xc4\xf9)%\xd61\xa8\xc3\xed\xc7a\x8965\u026d\xc5\u07a0\x00\x00\u07d4\x8c\u007f\xa5\xca\xe8/\xed\xb6\x9a\xb1\x89\xd3\xff'\xae \x92\x93\xfb\x93\x89\x15\xaf\x88\r\x8c\u06c3\x00\x00\xe0\x94\x8c\x81A\x0e\xa85L\xc5\xc6\\A\xbe\x8b\xd5\xdes<\v\x11\x1d\x8a\x02\x05\xb4\u07e1\xeetx\x00\x00\u07d4\x8c\x83\xd4$\xa3\xcf$\xd5\x1f\x01\x92=\xd5J\x18\u05b6\xfe\xde{\x89\xd8\xd7&\xb7\x17z\x80\x00\x00\u07d4\x8c\x90\n\x826\xb0\x8c+e@]9\xd7_ \x06*ua\xfd\x89X\xe7\x92n\xe8X\xa0\x00\x00\u07d4\x8c\x93\xc3\xc6\u06dd7q}\xe1e\u00e1\xb4\xfeQ\x95,\b\u0789\x15\xaf\x1dx\xb5\x8c@\x00\x00\u07d4\x8c\x99\x95\x91\xfdr\xefq\x11\xef\xcaz\x9e\x97\xa25k;\x00\n\x89\xddd\xe2\xaa\ngP\x00\x00\u07d4\x8c\xa6\x98\x97F\xb0n2\xe2Hta\xb1\u0399j':\xcf\u05c9\x01\x15\x8eF\t\x13\xd0\x00\x00\u07d4\x8c\xb3\xaa?\xcd!(T\xd7W\x8f\xcc0\xfd\xed\xe6t*1*\x89\x10CV\x1a\x88)0\x00\x00\u07d4\x8c\xc0\xd7\xc0\x16\xfaz\xa9P\x11J\xa1\xdb\tH\x82\xed\xa2t\xea\x89\b\xa9\xab\xa5W\xe3l\x00\x00\u07d4\x8c\xc6R\xdd\x13\xe7\xfe\x14\u06bb\xb3m]2\r\xb9\xff\xee\x8aT\x89a\t=|,m8\x00\x00\u07d4\x8c\u02bf%\a\u007f:\xa4\x15E4MS\xbe\x1b+\x9c3\x90\x00\x89[\xe8f\xc5b\xc5D\x00\x00\u07d4\x8c\xcf:\xa2\x1a\xb7BWj\xd8\xc4\"\xf7\x1b\xb1\x88Y\x1d\ua28965\u026d\xc5\u07a0\x00\x00\u07d4\x8c\xd0\xcd\"\xe6 \xed\xa7\x9c\x04a\xe8\x96\xc9<D\x83~)h\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\x8c\u078bs.`#\x87\x8e\xb2>\xd1b)\x12K_z\xfb\xec\x89\a?u\u0460\x85\xba\x00\x00\u07d4\x8c\xe2/\x9f\xa3rD\x9aB\x06\x10\xb4z\xe0\xc8\xd5eH\x122\x89lk\x93[\x8b\xbd@\x00\x00\xe0\x94\x8c\u451d\x8a\x16T-B<\x17\x98Ng9\xfar\u03b1w\x8a\x05K@Y&\xf4\xa6=\x80\x00\u07d4\x8c\xe5\xe3\xb5\xf5\x91\xd5\uc8ca\xbf\"\x8f.<5\x13K\xda\xc0\x89}\xc3[\x84\x89|8\x00\x00\xe0\x94\x8c\xee8\xd6YW\x88\xa5n?\xb9F4\xb3\xff\xe1\xfb\xdb&\u058a\x04<3\xc1\x93ud\x80\x00\x00\u07d4\x8c\xee\xa1^\xec;\xda\xd8\x02?\x98\xec\xf2[+\x8f\xef'\xdb)\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\x8c\xf3To\xd1\u0363=X\x84_\xc8\xfc\xfe\u02bc\xa7\xc5d*\x89\x1f\x1e9\x93,\xb3'\x80\x00\u07d4\x8c\xf6\xda\x02\x04\xdb\u0106\vF\xad\x97?\xc1\x11\x00\x8d\x9e\fF\x89\n\u05ce\xbcZ\xc6 \x00\x00\u07d4\x8c\xfe\xde\xf1\x98\xdb\n\x91C\xf0\x91)\xb3\xfdd\u073b\x9bIV\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\x8d\x04\xa5\xeb\xfb]\xb4\t\xdb\x06\x17\xc9\xfaV1\xc1\x92\x86\x1fJ\x894\x95tD\xb8@\xe8\x00\x00\u07d4\x8d\x06\xe4d$\\\xadaI9\xe0\xaf\bE\xe6\xd70\xe2\x03t\x89\n\u070a(\xf3\xd8}\x80\x00\u07d4\x8d\a\xd4-\x83\x1c-|\x83\x8a\xa1\x87+:\xd5\xd2w\x17h#\x89\x12\xee\x1f\x9d\xdb\xeeh\x00\x00\u07d4\x8d\v\x9e\xa5?\xd2cA^\xac\x119\x1f|\xe9\x12<Dpb\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\x8d\x17\x94\xdaP\x9c\xb2\x97\x056a\xa1J\xa8\x92321\xe3\xc1\x89\n\xd2\x01\xa6yO\xf8\x00\x00\u07d4\x8d\x1a\xbd\x89}\xac\xd41.\x18\b\f\x88\xfb\x96G\xea\xb4@R\x89\v\xb5\x9a'\x95<`\x00\x00\u07d4\x8d#\x034\x1e\x1e\x1e\xb5\xe8\x18\x9b\xde\x03\xf7:`\xa2\xa5Ha\x89\x05k\xc7^-c\x10\x00\x00\u07d4\x8d#\x8e\x03e\x96\x98vC\xd71s\xc3{\n\xd0`U\xb9l\x89qH\xbf\n*\xf0f\x00\x00\xe0\x94\x8d.1\xb0\x88\x03\xb2\xc5\xf1=9\x8e\xca\u0605( \x9f`W\x8a\x02\x1d\xb8\xbb\xca\xd1\x1e\x84\x00\x00\u07d4\x8d7\x8f\x0e\xdc\v\xb0\xf0hmj \xbejv\x92\xc4\xfa$\xb8\x89\x05k\xc7^-c\x10\x00\x00\u0794\x8dK`<]\xd4W\f4f\x95\x15\xfd\xccfX\x90\x84\fw\x88\xfc\x93c\x92\x80\x1c\x00\x00\u07d4\x8dQ\xa4\xccb\x01\x13\"\u0196\xfdr[\x9f\xb8\xf5?\xea\xaa\a\x8965\u026d\xc5\u07a0\x00\x00\u07d4\x8dTL2\xc0\u007f\u0404,v\x1dS\xa8\x97\xd6\xc9P\xbbu\x99\x89\n\u05ce\xbcZ\xc6 \x00\x00\u07d4\x8d^\xf1r\xbfw1^\xa6N\x85\xd0\x06\x19\x86\u01d4\xc6\xf5\x19\x89\u0556{\xe4\xfc?\x10\x00\x00\u07d4\x8dak\x1e\xeew\xee\xf6\xf1v\xe0i\x8d\xb3\xc0\xc1A\xb2\xfc\x8f\x89\x1b\x1a\xe4\xd6\xe2\xefP\x00\x00\u07d4\x8dap\xfff\x97\x8ew;\xb6!\xbfr\xb1\xba{\xe3\xa7\xf8~\x89\n\u05ce\xbcZ\xc6 \x00\x00\u07d4\x8db\v\xde\x17\"\x8fl\xbb\xa7M\xf6\xbe\x87&M\x98\\\xc1y\x89\x05k\xc7^-c\x10\x00\x00\u07d4\x8db\x9c `\x815I\x1bP\x13\xf1\x00%\x86\xa0810\xe5\x89JD\x91\xbdm\xcd(\x00\x00\u07d4\x8dfW\xf5\x97\x11\xb1\xf8\x03\xc6\xeb\xefh/\x91[b\xf9-\u0249lk\x93[\x8b\xbd@\x00\x00\u07d4\x8dfv7\xe2\x9e\xca\x05\xb6\xbf\xbe\xf1\xf9mF\x0e\uffd9\x84\x89\xd8\xd7&\xb7\x17z\x80\x00\x00\u07d4\x8dm\xf2\tHM{\x94p+\x03\xa5>V\xb9\xfb\x06`\xf6\xf0\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\x8dy\\_JV\x89\xadb\u0696\x16q\xf0(\x06R\x86\xd5T\x89o\x05\xb5\x9d; \x00\x00\x00\u07d4\x8d\u007f>a)\x9c-\xb9\xb9\xc0H|\xf6'Q\x9e\xd0\n\x91#\x89^t\xa8P^\x80\xa0\x00\x00\xe0\x94\x8d\x89\x17\v\x92\xb2\xbe,\b\xd5|H\xa7\xb1\x90\xa2\xf1Fr\x0f\x8a\x04+\xf0kx\xed;P\x00\x00\u07d4\x8d\x93\xda\u01c5\xf8\x8f\x1a\x84\xbf\x92}Se+E\xa1T\xcc\u0749\b\x90\xb0\xc2\xe1O\xb8\x00\x00\u07d4\x8d\x99R\u043bN\xbf\xa0\xef\xd0\x1a:\xa9\xe8\xe8\u007f\x05%t.\x89\xbb\x91%T\"c\x90\x00\x00\u07d4\x8d\x9a\fp\xd2& B\xdf\x10\x17\xd6\xc3\x03\x13 $w'\x12\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\x8d\x9e\xd7\xf4U0X\xc2ox6\xa3\x80-0d\xeb\x1b6=\x89\x04\xe1\x00;(\xd9(\x00\x00\u07d4\x8d\xa1\x17\x8fU\xd9wr\xbb\x1d$\x11\x1a@JO\x87\x15\xb9]\x89/\x9a\xc3\xf6\xde\x00\x80\x80\x00\u07d4\x8d\xa1\xd3Y\xbal\xb4\xbc\xc5}zCw \xd5]\xb2\xf0\x1cr\x89\x04V9\x18$O@\x00\x00\u07d4\x8d\xab\x94\x8a\xe8\x1d\xa3\x01\xd9r\xe3\xf6\x17\xa9\x12\xe5\xa7Sq.\x89\x15\xaf\x1dx\xb5\x8c@\x00\x00\u07d4\x8d\xad\xdfR\xef\xbdt\u0695\xb9i\xa5GoO\xbb\xb5c\xbf\u0489-C\xf3\xeb\xfa\xfb,\x00\x00\u07d4\x8d\xb1\x85\xfe\x1bp\xa9Jj\b\x0e~#\xa8\xbe\xdcJ\xcb\xf3K\x89K\xe4\xe7&{j\xe0\x00\x00\u07d4\x8d\xb5\x8e@n -\xf9\xbcp<H\v\xd8\xed$\x8dR\xa02\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\x8d\xbc>l\xb43\xe1\x94\xf4\x0f\x82\xb4\x0f\xaa\xdb\x1f\x8b\x85a\x16\x89g\x8a\x93 b\xe4\x18\x00\x00\u07d4\x8d\xc1\xd5\x11\x1d\t\xaf%\xfd\xfc\xacE\\|\xec(>mgu\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\x8d\u0504\xff\x8a0sd\xebf\xc5%\xa5q\xaa\xc7\x01\xc5\xc3\x18\x89\xd8\xd7&\xb7\x17z\x80\x00\x00\u07d4\x8d\u05a9\xba\xe5\u007fQ\x85I\xad\xa6wFo\ua2b0O\u0674\x89\xd8\xd7&\xb7\x17z\x80\x00\x00\u07d4\x8d\xde<\xb8\x11\x85h\xefE\x03\xfe\x99\x8c\xcd\xf56\xbf\x19\xa0\x98\x89\xd8\xd7&\xb7\x17z\x80\x00\x00\u07d4\x8d\xde`\xeb\b\xa0\x99\xd7\u06a3V\u06aa\xb2G\r{\x02Zk\x89\n\xad\xec\x98?\xcf\xf4\x00\x00\xe0\x94\x8d\xf39!Kj\u0472Fc\xceq`4t\x9dn\xf88\u064a\x02TO\xaaw\x80\x90\xe0\x00\x00\xe0\x94\x8d\xf5=\x96\x19\x14q\xe0Y\xdeQ\xc7\x18\xb9\x83\xe4\xa5\x1d*\xfd\x8a\x06\u01b95\xb8\xbb\xd4\x00\x00\x00\u07d4\x8d\xfb\xaf\xbc\x0e[\\\x86\xcd\x1a\u0597\xfe\xea\x04\xf41\x88\u0796\x89\x15%+\u007f_\xa0\xde\x00\x00\u07d4\x8e\a;\xad%\xe4\"\x18a_J\x0ek.\xa8\xf8\xde\"0\xc0\x89\x82=b\x9d\x02k\xfa\x00\x00\u07d4\x8e\x0f\xee8hZ\x94\xaa\xbc\xd7\u0385{k\x14\t\x82Ou\xb8\x89\x1b\x1a\xe4\xd6\xe2\xefP\x00\x00\u07d4\x8e#\xfa\xcd\x12\xc7e\xc3j\xb8\x1am\xd3M\x8a\xa9\xe6\x89\x18\xae\x89\t\x11\u418d\xba\x9b\x00\x00\xe0\x94\x8e/\x904\xc9%G\x19\u00ceP\u026ad0^\u0596\xdf\x1e\x8a\x01\x00N.E\xfb~\xe0\x00\x00\u07d4\x8e2@\xb0\x81\x0e\x1c\xf4\a\xa5\x00\x80G@\u03cdad2\xa4\x89\x02/fU\xef\v8\x80\x00\u07d4\x8eHj\x04B\xd1q\xc8`[\xe3H\xfe\xe5~\xb5\b^\xff\r\x89\xd8\xd7&\xb7\x17z\x80\x00\x00\u07d4\x8eaV3k\xe2\u037e2\x14\r\xf0\x8a+\xa5_\u0425\x84c\x89\x04\t\x9e\x1dcW\x18\x00\x00\u07d4\x8eg\b\x15\xfbg\xae\xae\xa5{\x86SN\xdc\x00\xcd\xf5d\xfe\u5272\xe4\xb3#\xd9\xc5\x10\x00\x00\u07d4\x8emt\x85\xcb\u942c\xc1\xad\x0e\xe9\xe8\xcc\xf3\x9c\f\x93D\x0e\x893\xc5I\x901r\f\x00\x00\xe0\x94\x8et\xe0\u0477~\xbc\x82:\xca\x03\xf1\x19\x85L\xb1 '\xf6\u05ca\x16\xb3R\xda^\x0e\xd3\x00\x00\x00\u07d4\x8ex\xf3QE}\x01oJ\xd2u^\xc7BN\\!\xbamQ\x89\a\xea(2uw\b\x00\x00\u07d4\x8ey6\u0552\x00\x8f\xdcz\xa0N\xde\xebuZ\xb5\x13\u06f8\x9d\x89\x01\x15\x8eF\t\x13\xd0\x00\x00\u07d4\x8e\u007f\xd28H\xf4\xdb\a\x90j}\x10\xc0K!\x80;\xb0\x82'\x8965\u026d\xc5\u07a0\x00\x00\u07d4\x8e\x92\xab\xa3\x8er\xa0\x98\x17\v\x92\x95\x92FSz.UV\xc0\x89\x0e~\xeb\xa3A\vt\x00\x00\u07d4\x8e\x98ve$\xb0\xcf'G\xc5\r\xd4;\x95gYM\x971\u0789lD\xb7\xc2a\x82(\x00\x00\u07d4\x8e\x9b5\xadJ\n\x86\xf7XDo\xff\xde4&\x9d\x94\f\xea\u0349\xd8\xd7&\xb7\x17z\x80\x00\x00\u07d4\x8e\x9c\b\xf78f\x1f\x96v#n\xff\x82\xbaba\xdd?H\"\x89\x05k\xc7^-c\x10\x00\x00\u07d4\x8e\x9cB\x92f\xdf\x05~\xfax\xdd\x1d_w\xfc@t*\xd4f\x89\x10D.\u0475l|\x80\x00\u07d4\x8e\xa6V\xe7\x1e\xc6Q\xbf\xa1|ZWY\xd8`1\xcc5\x99w\x89\x05k\xc7^-c\x10\x00\x00\u07d4\x8e\xae)CU\x98\xba\x8f\x1c\x93B\x8c\xdb>+M1\a\x8e\x00\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\x8e\xb1\xfb\xe4\xe5\xd3\x01\x9c\xd7\xd3\r\xae\x9c\r[Lv\xfbc1\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\x8e\xb5\x17t\xaf k\x96k\x89\t\xc4Z\xa6r'H\x80,\f\x89\x1b\x1a\xe4\xd6\xe2\xefP\x00\x00\u07d4\x8e\xb8\xc7\x19\x82\xa0\x0f\xb8Bu)2S\xf8\x04ED\xb6kI\x89\x15\xaf\x1dx\xb5\x8c@\x00\x00\xe0\x94\x8e\xcb\u03ec\xbf\xaf\xe9\xf0\f9\"\xa2N,\xf0\x02gV\xca \x8a\x011\xbe\xb9%\xff\xd3 \x00\x00\u07d4\x8e\u03b2\xe1$Sl[_\xfcd\x0e\xd1O\xf1^\u0668\xcbq\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\x8e\u042f\x11\xff(p\xda\x06\x81\x00J\xfe\x18\xb0\x13\xf7\xbd8\x82\x89\xd8\xd7&\xb7\x17z\x80\x00\x00\u0794\x8e\xd1Cp\x1f/r(\x0f\xd0J{Ad(\x19y\xea\x87\u0248\xc2I\xfd\xd3'x\x00\x00\u07d4\x8e\xd1R\x8bD~\xd4)y\x02\xf69\xc5\x14\u0414J\x88\xf8\u0209\n\xc6\xe7z\xb6c\xa8\x00\x00\u07d4\x8e\xd4(L\x0fGD\x9c\x15\xb8\u0673$]\u8fb6\u0380\xbf\x89+^:\xf1k\x18\x80\x00\x00\xe0\x94\x8e\xde~=\xc5\aI\xc6\xc5\x0e.(\x16\x84x\xc3M\xb8\x19F\x8a\x04<0\xfb\b\x84\xa9l\x00\x00\u07d4\x8e\xe5\x843}\xdb\xc8\x0f\x9e4\x98\xdfU\xf0\xa2\x1e\xac\xb5\u007f\xb1\x89\x01\x15\x8eF\t\x13\xd0\x00\x00\u07d4\x8e\xeb\xec\x1ab\xc0\x8b\x05\xa7\xd1\u0551\x80\xaf\x9f\xf0\u044e?6\x89\x1b\x1a\xe4\xd6\xe2\xefP\x00\x00\u07d4\x8e\xf4\u0622\xc2<Ry\x18{d\xe9ot\x14\x04\bS\x85\xf3\x89\x10=\xc1\xe9\xa9i{\x00\x00\u07d4\x8e\xf7\x11\xe4:\x13\x91\x8f\x13\x03\xe8\x1d\x0e\xa7\x8c\x9e\xef\xd6~\xb2\x89\xd8\xd7&\xb7\x17z\x80\x00\x00\u07d4\x8e\xfe\xc0X\xccTaWvjc'u@J3J\xaa\u0687\x89l]\xb2\xa4\xd8\x15\xdc\x00\x00\u07d4\x8f\x02\xbd\xa6\xc3i\"\xa6\xbejP\x9b\xe5\x19\x06\u04d3\xf7\xb9\x9b\x897I\r\xc1.\xbe\u007f\x80\x00\u07d4\x8f\x058\xedq\xda\x11U\xe0\xf3\xbd\xe5f|\xeb\x841\x8a\x1a\x87\x89i*\xe8\x89p\x81\xd0\x00\x00\xe0\x94\x8f\x06||\x1b\xbdWx\v{\x9e\xeb\x9e\xc0\x03/\x90\xd0\xdc\xf9\x8a\x04<3\xc1\x93ud\x80\x00\x00\xe0\x94\x8f\n\xb8\x94\xbd?Ni}\xbc\xfb\x85\x9dIz\x9b\xa1\x95\x99J\x8a\b]c\x8beG*\xa2\x00\x00\u07d4\x8f\n\xf3uf\xd1R\x80/\x1a\xe8\xf9(\xb2Z\xf9\xb19\xb4H\x89\n\u05ce\xbcZ\xc6 \x00\x00\u07d4\x8f\x19R\xee\xd1\xc5H\xd9\ue6d7\xd0\x16\x9a\a\x93;\xe6\x9fc\x8965\u026d\xc5\u07a0\x00\x00\xe0\x94\x8f\x1f\xcc<Q\xe2R\xb6\x93\xbc[\x0e\xc3\xf65)\xfei(\x1e\x8a\x01EB\xba\x12\xa37\xc0\x00\x00\u07d4\x8f\"`\x96\xc1\x84\xeb\xb4\x01\x05\xe0\x8d\xacM\"\xe1\xc2\xd5M0\x89\x10\x9eC{\xd1a\x8c\x00\x00\xe0\x94\x8f)\xa1J\x84Z\xd4X\xf2\xd1\b\xb5h\xd8\x13\x16k\xcd\xf4w\x8a\x02\x1e\x19\xe0\u027a\xb2@\x00\x00\u07d4\x8f1\xc7\x00Q\x97\xec\x99z\x87\xe6\x9b\xecHd\x9a\xb9K\xb2\xa5\x89\xd8\xd7&\xb7\x17z\x80\x00\x00\u07d4\x8fA\xb1\xfb\xf5B\x98\xf5\u043c-\x12/N\xb9]\xa4\xe5\xcd=\x89\x133\x83/^3\\\x00\x00\u07d4\x8fG2\x8e\xe02\x01\xc9\xd3^\u04b5A+%\xde\u0305\x93b\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\x8fG=\n\xb8v\u076a\x15`\x86!\xd7\x01>o\xf7\x14\xb6u\x89\x19\x80\x1c\x83\xb6\xc7\xc0\x00\x00\u07d4\x8fM\x1dAi>F,\xf9\x82\xfd\x81\u042ap\x1d:St\u0249\xd8\xd7&\xb7\x17z\x80\x00\x00\u07d4\x8fM\x1e~Ea(J4\xfe\xf9g<\r4\xe1*\xf4\xaa\x03\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\x8fO\xb1\xae\xa7\xcd\x0fW\x0e\xa5\xe6\x1b@\xa4\xf4Q\vbd\xe4\x89\xd8\xd7&\xb7\x17z\x80\x00\x00\u07d4\x8fV\x1bA\xb2\t\xf2H\u0229\x9f\x85\x87\x887bP`\x9c\xf3\x89\\(=A\x03\x94\x10\x00\x00\xe0\x94\x8fX\xd84\x8f\xc1\xdcN\r\xd84;eC\xc8W\x04^\xe9@\x8a\x02\xe3\x03\x8d\xf4s\x03(\x00\x00\u07d4\x8f`\x89_\xbe\xbb\xb5\x01\u007f\xcb\xff<\u0763\x97)+\xf2[\xa6\x89\x17D\x06\xff\x9fo\u0480\x00\u07d4\x8fd\xb9\xc1$m\x85x1d1\a\xd3U\xb5\xc7_\xef]O\x89lj\xccg\u05f1\xd4\x00\x00\xe0\x94\x8ff\x0f\x8b.L|\u00b4\xac\x9cG\xed(P\x8d_\x8f\x86P\x8a\x04<3\xc1\x93ud\x80\x00\x00\u07d4\x8fi\xea\xfd\x023\xca\xdb@Y\xabw\x9cF\xed\xf2\xa0PnH\x89`\xf0f \xa8IE\x00\x00\xe0\x94\x8fq~\xc1U/LD\x00\x84\xfb\xa1\x15J\x81\xdc\x00>\xbd\xc0\x8a\x02\x1e\x19\xe0\u027a\xb2@\x00\x00\xe0\x94\x8f\x8a\xcb\x10v\a8\x84y\xf6K\xaa\xab\xea\x8f\xf0\a\xad\xa9}\x8a\x05\xc6\xf3\b\n\xd4#\xf4\x00\x00\u07d4\x8f\x8c\xd2n\x82\xe7\xc6\xde\xfd\x02\u07ed\a\x97\x90!\xcb\xf7\x15\f\x89\xa2\xa1]\tQ\x9b\xe0\x00\x00\u07d4\x8f\x8f7\u042d\x8f3]*q\x01\xb4\x11V\xb6\x88\xa8\x1a\x9c\xbe\x89\x03\xcbq\xf5\x1f\xc5X\x00\x00\u07d4\x8f\x92\x84O(*\x92\x99\x9e\u5d28\xd7s\xd0kiM\xbd\x9f\x89i*\xe8\x89p\x81\xd0\x00\x00\u07d4\x8f\xact\x8fxJ\x0f\xedh\u06e43\x19\xb4*u\xb4d\x9cn\x891T\xc9r\x9d\x05x\x00\x00\u07d4\x8f\u0665\xc3:}\x9e\xdc\xe0\x99{\xdfw\xab0d$\xa1\x1e\xa9\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\x8f\xef\xfa\xdb8z\x15G\xfb(M\xa9\xb8\x14\u007f>|m\xc6\u0689-b{\xe4S\x05\b\x00\x00\u07d4\x8f\xf4`Ehw#\xdc3\xe4\u0419\xa0i\x04\xf1\ubd44\u0709lk\x93[\x8b\xbd@\x00\x00\u07d4\x8f\xfa\x06!\"\xac0t\x18\x82\x1a\u06d3\x11\aZ7\x03\xbf\xa3\x8965\u026d\xc5\u07a0\x00\x00\u07d4\x8f\xfe2)\x97\xb8\xe4\x04B-\x19\xc5J\xad\xb1\x8f[\xc8\u9dc9\u0556{\xe4\xfc?\x10\x00\x00\u07d4\x90\x01\x94\u0131\aC\x05\u045d\xe4\x05\xb0\xacx(\x0e\xca\xf9g\x8965\u026d\xc5\u07a0\x00\x00\u07d4\x90\x03\xd2p\x89\x1b\xa2\xdfd=\xa84\x15\x83\x195E\xe3\xe0\x00\x89\xd8\xd7&\xb7\x17z\x80\x00\x00\xe0\x94\x90\x05z\xf9\xaaf0~\xc9\xf03\xb2\x97$\u04f2\xf4\x1e\xb6\xf9\x8a\x19\xd1\u05aa\xdb,R\xe8\x00\x00\u07d4\x90\x0f\v\x8e5\xb6h\xf8\x1e\xf2R\xb18U\xaaP\a\xd0\x12\xe7\x89\x17\n\x0fP@\xe5\x04\x00\x00\u07d4\x90\x18\xcc\x1fH\xd20\x8e%*\xb6\b\x9f\xb9\x9a|\x1dV\x94\x10\x89\n\u05ce\xbcZ\xc6 \x00\x00\u07d4\x90\x1d\x99\xb6\x99\xe5\u0191\x15\x19\xcb v\xb4\xc7c0\xc5M\"\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\x90-t\xa1W\xf7\u04b9\xa37\x8b\x1fVp70\xe0:\x17\x19\x89\xd8\xd7&\xb7\x17z\x80\x00\x00\xe0\x94\x904\x13\x87\x8a\xea;\xc1\bc\t\xa3\xfev\x8beU\x9e\x8c\xab\x8a\x01\xb1\xaeMn.\xf5\x00\x00\x00\u07d4\x90If\xcc\"\x13\xb5\xb8\xcb[\xd6\b\x9e\xf9\xcd\xdb\xef~\xdf\u0309lk\x93[\x8b\xbd@\x00\x00\u07d4\x90L\xaaB\x9ca\x9d\x94\x0f\x8egA\x82j\r\xb6\x92\xb1\x97(\x8965\u026d\xc5\u07a0\x00\x00\u07d4\x90R\xf2\xe4\xa3\xe3\xc1-\xd1\xc7\x1b\xf7\x8aN\xc3\x04=\u020b~\x89\x0e~\xeb\xa3A\vt\x00\x00\u0794\x90U&V\x8a\xc1#\xaf\xc0\xe8J\xa7\x15\x12O\xeb\xe8=\xc8|\x88\xf8i\x93)g~\x00\x00\u07d4\x90\x92\x91\x87\a\xc6!\xfd\xbd\x1d\x90\xfb\x80\xebx\u007f\xd2osP\x89\x85[[\xa6\\\x84\xf0\x00\x00\u07d4\x90\x9b^v:9\xdc\u01d5\"=s\xa1\u06f7\xd9L\xa7Z\u0209lk\x93[\x8b\xbd@\x00\x00\u07d4\x90\xac\xce\xd7\xe4\x8c\b\u01b94dm\xfa\n\xdf)\u0714\aO\x89\x03\vK\x15{\xbdI\x00\x00\u07d4\x90\xb1\xf3p\xf9\xc1\xeb\v\xe0\xfb\x8e+\x8a\xd9jAcq\u074a\x890\xca\x02O\x98{\x90\x00\x00\u07d4\x90\xb6/\x13\x1a_)\xb4UqQ>\xe7\xa7J\x8f\v#\"\x02\x89\b\x90\xb0\xc2\xe1O\xb8\x00\x00\u07d4\x90\xbdb\xa0P\x84Ra\xfaJ\x9f|\xf2A\xeac\v\x05\ufe09\x1b\x1a\xe4\xd6\xe2\xefP\x00\x00\u07d4\x90\xc4\x1e\xba\x00\x8e \xcb\xe9'\xf3F`?\u0206\x98\x12Yi\x89\x02F\xdd\xf9yvh\x00\x00\u07d4\x90\u0480\x9a\xe1\xd1\xff\xd8\xf6>\xda\x01\xdeI\xddU-\xf3\u047c\x89\u063beI\xb0+\xb8\x00\x00\u07d4\x90\xdc\t\xf7\x17\xfc*[i\xfd`\xba\b\xeb\xf4\v\xf4\xe8$l\x89\xd8\xd8X?\xa2\xd5/\x00\x00\u07d4\x90\xe3\x00\xacqE\x1e@\x1f\x88\u007fnw(\x85\x16G\xa8\x0e\a\x89\x15\xaf\x1dx\xb5\x8c@\x00\x00\u07d4\x90\xe3Z\xab\xb2\xde\xef@\x8b\xb9\xb5\xac\xefqDW\xdf\xdebr\x89\x05l\xd5_\xc6M\xfe\x00\x00\u07d4\x90\xe7\a\x0fM\x03?\xe6\x91\f\x9e\xfeZ'\x8e\x1f\xc6#M\xef\x89\x05q8\b\x19\xb3\x04\x00\x00\u07d4\x90\xe9>M\xc1q!HyR36\x14\x00+\xe4#VI\x8e\x89g\x8a\x93 b\xe4\x18\x00\x00\u07d4\x90\u9a68.\u06a8\x14\u0084\xd22\xb6\u9e90p\x1dIR\x89\x05k\xe0<\xa3\xe4}\x80\x00\u07d4\x90\xf7t\xc9\x14}\u0790\x85=\xdcC\xf0\x8f\x16\xd4U\x17\x8b\x8c\x89\xd8\xd7&\xb7\x17z\x80\x00\x00\u07d4\x90\xfcS{!\x06Xf\n\x83\xba\xa9\xacJ\x84\x02\xf6WF\xa8\x89e\xea=\xb7UF`\x00\x00\u07d4\x91\x05\n\\\xff\xad\xed\xb4\xbbn\xaa\xfb\xc9\xe5\x014(\xe9l\x80\x89\\(=A\x03\x94\x10\x00\x00\u07d4\x91\x05\x17d\xafk\x80\x8eB\x12\xc7~0\xa5W.\xaa1pp\x8965\u026d\xc5\u07a0\x00\x00\xe0\x94\x91\v}Wz~9\xaa#\xac\xf6*\xd7\xf1\xef4)4\xb9h\x8a\x02\x1e\x19\xe0\u027a\xb2@\x00\x00\u07d4\x91\x0e\x99eC4Lh\x15\xfb\x97\u0367\xafK\x86\x98vZ[\x89\x05\x9a\xf6\x98)\xcfd\x00\x00\u07d4\x91\x1f\xee\xa6\x1f\xe0\xedP\u0179\xe5\xa0\xd6`q9\x9d(\xbd\u0189\x03@\xaa\xd2\x1b;p\x00\x00\u07d4\x91\x1f\xf23\xe1\xa2\x11\xc0\x17,\x92\xb4l\xf9\x97\x03\x05\x82\xc8:\x89j\xcb=\xf2~\x1f\x88\x00\x00\u07d4\x91 \xe7\x11s\xe1\xba\x19\xba\x8f\x9fO\xdb\u072a4\xe1\u05bbx\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\x91!\x17\x12q\x9f+\bM;8u\xa8Pi\xf4f61A\x8965\u026d\xc5\u07a0\x00\x00\u07d4\x91#\x04\x11\x8b\x80G=\x9e\x9f\xe3\xeeE\x8f\xbea\x0f\xfd\xa2\xbb\x89\n\u05ce\xbcZ\xc6 \x00\x00\u07d4\x91Tky\xec\xf6\x9f\x93kZV\x15\b\xb0\xd7\xe5\f\u0159/\x89\x0e~\xeb\xa3A\vt\x00\x00\u07d4\x91V\u0440)5\x0eG\x04\b\xf1_\x1a\xa3\xbe\x9f\x04\ng\u018965\u026d\xc5\u07a0\x00\x00\u07d4\x91b\x0f>\xb3\x04\xe8\x13\u048b\x02\x97Ume\xdcN]\u5a89\xcf\x15&@\xc5\xc80\x00\x00\xe0\x94\x91k\xf7\xe3\xc5E\x92\x1d2\x06\xd9\x00\xc2O\x14\x12|\xbd^p\x8a\x03\xd0\u077c}\xf2\xbb\x10\x00\x00\u0794\x91l\xf1}qA(\x05\xf4\xaf\xc3DJ\v\x8d\xd1\xd93\x9d\x16\x88\xc6s\xce<@\x16\x00\x00\u07d4\x91{\x8f\x9f:\x8d\t\xe9 ,R\u009erA\x96\xb8\x97\xd3^\x89\b\xbaR\xe6\xfcE\xe4\x00\x00\u07d4\x91\x89g\x91\x8c\u0617\xdd\x00\x05\xe3m\xc6\u0203\xefC\x8f\xc8\u01c9\a\x96\xe3\xea?\x8a\xb0\x00\x00\u07d4\x91\x89\x8e\xab\x8c\x05\xc0\"(\x83\xcdM\xb2;w\x95\xe1\xa2J\u05c9lk\x93[\x8b\xbd@\x00\x00\u0794\x91\x91\xf9F\x98!\x05\x16\xcfc!\xa1B\a\x0e Yvt\xed\x88\xee\x9d[\xe6\xfc\x11\x00\x00\u07d4\x91\xa4\x14\x9a,{\x1b:g\xea(\xaf\xf3G%\u0fcdu$\x89i*\xe8\x89p\x81\xd0\x00\x00\u07d4\x91\xa7\x87\xbcQ\x96\xf3HW\xfe\f7/M\xf3v\xaa\xa7f\x13\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\x91\xa8\xba\xae\xd0\x12\xea.c\x80;Y=\r\f*\xabL[\n\x89QP\xae\x84\xa8\xcd\xf0\x00\x00\u07d4\x91\xac\\\xfeg\xc5J\xa7\xeb\xfb\xa4HflF\x1a;\x1f\xe2\xe1\x89\x15\xc94\x92\xbf\x9d\xfc\x00\x00\u07d4\x91\xbb?y\x02+\xf3\xc4S\xf4\xff%n&\x9b\x15\xcf,\x9c\xbd\x89RX\\\x13\xfe:\\\x00\x00\u07d4\x91\xc7^<\xb4\xaa\x89\xf3F\x19\xa1d\xe2\xa4x\x98\xf5gM\x9c\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\x91\xc8\f\xaa\b\x1b85\x1d*\x0e\x0e\x00\xf8\n4\xe5dt\xc1\x8965\u026d\xc5\u07a0\x00\x00\u07d4\x91\xccF\xaa7\x9f\x85jf@\xdc\xcdZd\x8ay\x02\xf8I\u0649\n\u05ce\xbcZ\xc6 \x00\x00\xe0\x94\x91\u04a9\xee\x1am\xb2\x0fS\x17\u0327\xfb\xe218\x95\u06ce\xf8\x8a\x01\xcc\u00e5/0n(\x00\x00\u07d4\x91\xd6n\xa6(\x8f\xaaK=`l*\xa4\\{k\x8a%'9\x89lk\x93[\x8b\xbd@\x00\x00\xe0\x94\x91\u06f6\xaa\xad\x14\x95\x85\xbeG7\\]m\xe5\xff\t\x19\x15\x18\x8a\x04<3\xc1\x93ud\x80\x00\x00\u07d4\x91\xe8\x81\x06R\xe8\xe6\x16\x15%\xd6;\xb7u\x1d\xc2\x0fg`v\x89'Mej\xc9\x0e4\x00\x00\u07d4\x91\xf5\x16\x14l\xda (\x17\x19\x97\x80`\u01beAI\x06|\x88\x89lk\x93[\x8b\xbd@\x00\x00\xe0\x94\x91\xf6$\xb2J\x1f\xa5\xa0V\xfeW\x12)\xe77\x9d\xb1K\x9a\x1e\x8a\x02\x8a\x85\x17\xc6i\xb3W\x00\x00\xe0\x94\x91\xfe\x8aLad\u07cf\xa6\x06\x99]k\xa7\xad\xca\xf1\u0213\u038a\x03\x99\x92d\x8a#\u0220\x00\x00\u07d4\x92\x1fRa\xf4\xf6\x12v\a\x06\x89&%\xc7^{\u0396\xb7\b\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\x92!\xc9\xce\x01#&et\x10\x96\xac\a#Y\x03\xad\x1f\xe2\xfc\x89\x06\xdbc3U\"b\x80\x00\u07d4\x92%\x988`\xa1\xcbF#\xc7$\x80\xac\x16'+\f\x95\xe5\xf5\x89lk\x93[\x8b\xbd@\x00\x00\xe0\x94\x92%\xd4jZ\x80\x949$\xa3\x9e[\x84\xb9m\xa0\xacE\x05\x81\x8a\bxg\x83&\xea\xc9\x00\x00\x00\u07d4\x92* \u01da\x1d:&\xdd8)g{\xf1\xd4\\\x8fg+\xb6\x89\xd8\xd7&\xb7\x17z\x80\x00\x00\u07d4\x92C\x8eR\x03\xb64o\xf8\x86\xd7\xc3b\x88\xaa\xcc\xccx\xce\u028965\u026d\xc5\u07a0\x00\x00\u07d4\x92C\xd7v-w({\x12c\x86\x88\xb9\x85N\x88\xa7i\xb2q\x8965\u026d\xc5\u07a0\x00\x00\u0794\x92K\xcez\x85<\x97\v\xb5\xec{\xb7Y\xba\xeb\x9ct\x10\x85{\x88\xbe -j\x0e\xda\x00\x00\u07d4\x92N\xfam\xb5\x95\xb7\x93\x13'~\x881\x96%\akX\n\x10\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\x92U\x82&\xb3\x84bl\xadH\xe0\x9d\x96k\xf19^\xe7\xea]\x89\x12\x1e\xa6\x8c\x11NQ\x00\x00\u07d4\x92`\x82\xcb~\xedK\x19\x93\xad$ZGrg\xe1\xc3<\xd5h\x89\x14Jt\xba\u07e4\xb6\x00\x00\u07d4\x92b\t\xb7\xfd\xa5N\x8d\u06dd\x9eM=\x19\xeb\u070e\x88\u009f\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\x92h\xd6&FV6\x11\xdc;\x83*0\xaa#\x94\xc6F\x13\xe3\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\x92i\x8e4Sx\xc6-\x8e\xda\x18M\x946j\x14K\f\x10[\x89K\xe4\xe7&{j\xe0\x00\x00\u07d4\x92y:\u0173rhwJq0\xde+\xbd3\x04\x05f\x17s\x89\x02,\xa3X|\xf4\xeb\x00\x00\xe0\x94\x92y\xb2\"\x8c\xec\x8f{M\xda?2\x0e\x9a\x04f\xc2\xf5\x85\u028a\x01\x0f\f\xf0d\xddY \x00\x00\u07d4\x92|\xb7\xdc\x18p6\xb5B{\xc7\xe2\x00\xc5\xecE\f\x1d'\u0509\v\xb5\x9a'\x95<`\x00\x00\u07d4\x92|\u00bf\xda\x0e\b\x8d\x02\xef\xf7\v8\xb0\x8a\xa5<\xc3\tA\x89do`\xa1\xf9\x866\x00\x00\xe0\x94\x92\x84\xf9m\xdbG\xb5\x18n\xe5X\xaa12M\xf56\x1c\x0fs\x8a\x03c\\\x9a\xdc]\xea\x00\x00\x00\u07d4\x92\x9d6\x8e\xb4j-\x1f\xbd\xc8\xff\xa0`~\xdeK\xa8\x8fY\xad\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\x92\xa7\u0166Cb\xe9\xf8B\xa2=\xec\xa2\x105\x85\u007f\x88\x98\x00\x89lj\xccg\u05f1\xd4\x00\x00\u07d4\x92\xa8\x98\xd4o\x19q\x9c8\x12j\x8a<'\x86z\xe2\xce\u5589lk\x93[\x8b\xbd@\x00\x00\u07d4\x92\xa9q\xa79y\x9f\x8c\xb4\x8e\xa8G]r\xb2\xd2GAr\xe6\x89\u0556{\xe4\xfc?\x10\x00\x00\u07d4\x92\xaa\xe5\x97h\xed\xdf\xf8<\xfe`\xbbQ.s\n\x05\xa1a\u05c9\\\x97xA\fv\u0440\x00\u07d4\x92\xad\x1b=u\xfb\xa6}Tf=\xa9\xfc\x84\x8a\x8a\xde\x10\xfag\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\x92\xae[|~\xb4\x92\xff\x1f\xfa\x16\xddB\xad\x9c\xad@\xb7\xf8\u0709.\xe4IU\b\x98\xe4\x00\x00\u07d4\x92\xc0\xf5s\xec\xcfb\xc5H\x10\xeek\xa8\xd1\xf1\x13T+0\x1b\x89\xb7ro\x16\u0331\xe0\x00\x00\u07d4\x92\xc1?\xe0\xd6\u0387\xfdP\xe0=\uf7e6@\x05\t\xbdps\x89\x02+\x1c\x8c\x12'\xa0\x00\x00\u07d4\x92\xc9L( \xdf\xcfqV\xe6\xf10\x88\xec\u754b6v\xfd\x89\x05-T(\x04\xf1\xce\x00\x00\u07d4\x92\xcf\xd6\x01\x88\xef\u07f2\xf8\xc2\xe7\xb1i\x8a\xbb\x95&\xc1Q\x1f\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\x92\u062d\x9aMah;\x80\u0526g.\x84\xc2\rbB\x1e\x80\x89\x01\x15\x8eF\t\x13\xd0\x00\x00\u07d4\x92\u0725\xe1\x02\xb3\xb8\x1b`\xf1\xa5\x04cIG\xc3t\xa8\x8c\u02c9lk\x93[\x8b\xbd@\x00\x00\u07d4\x92\xe454\x0e\x9d%<\x00%c\x89\xf5+\x06}U\x97Nv\x89\x0e\x87?D\x13<\xb0\x00\x00\xe0\x94\x92\xe49(\x16\xe5\xf2\xef_\xb6X7\xce\xc2\xc22\\\xc6I\"\x8a\x02\x1e\x19\xe0\u027a\xb2@\x00\x00\u07d4\x92\xe6X\x1e\x1d\xa1\xf9\xb8F\xe0\x93G3=\xc8\x18\xe2\u04acf\x89\xc5S%\xcat\x15\xe0\x00\x00\u07d4\x93\x1d\xf3M\x12%\xbc\xd4\"Nch\r\\L\t\xbc\xe75\xa6\x89\x03\xaf\xb0\x87\xb8v\x90\x00\x00\u07d4\x93\x1f\xe7\x12\xf6B\a\xa2\xfdP\"r\x88CT\x8b\xfb\x8c\xbb\x05\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\x93#_4\r(c\xe1\x8d/LR\x99e\x16\x13\x8d\"\x02g\x89\x04\x00.D\xfd\xa7\xd4\x00\x00\u07d4\x93%\x82U\xb3|\u007fX\xf4\xb1\x06s\xa92\xdd:\xfd\x90\xf4\xf2\x8965\u026d\xc5\u07a0\x00\x00\u07d4\x93(\xd5\\\xcb?\xceS\x1f\x19\x93\x823\x9f\x0eWn\xe8@\xa3\x89\xd8\xd7&\xb7\x17z\x80\x00\x00\u07d4\x93)\xff\xdc&\x8b\xab\u0788t\xb3f@l\x81D[\x9b-5\x89\x16\xe6/\x8cs\f\xa1\x80\x00\u07d4\x93+\x9c\x04\xd4\r*\xc80\x83\xd9B\x98\x16\x9d\xae\x81\xab.\u0409lk\x93[\x8b\xbd@\x00\x00\u07d4\x9346\xc8G&U\xf6L:\xfa\xaf|Lb\x1c\x83\xa6+8\x8965\u026d\xc5\u07a0\x00\x00\u0794\x93;\xf3?\x82\x99p+:\x90&B\xc3>\v\xfa\xea\\\x1c\xa3\x88\xd2\xf1?w\x89\xf0\x00\x00\u07d4\x93@4\\\xa6\xa3\uaf77sc\xf2X`C\xf2\x948\xce\v\x89\x1c\xc8\x05\xda\r\xff\xf1\x00\x00\xe0\x94\x93@\xb5\xf6x\xe4^\xe0^\xb7\b\xbbz\xbbn\xc8\xf0\x8f\x1bk\x8a\x01EB\xba\x12\xa37\xc0\x00\x00\xe0\x94\x93J\xf2\x1b~\xbf\xa4g\xe2\xce\xd6Z\xa3N\xdd:\x0e\xc7\x132\x8a\a\x80\x1f>\x80\xcc\x0f\xf0\x00\x00\xe0\x94\x93PiDJj\x98M\xe2\bNFi*\xb9\x9fg\x1f\xc7'\x8a\x01\xe7\xe4\x17\x1b\xf4\u04e0\x00\x00\xe0\x94\x93P~\x9e\x81\x19\xcb\xce\u068a\xb0\x87\xe7\xec\xb0q8=i\x81\x8a\x02\xf6\xf1\a\x80\xd2,\xc0\x00\x00\u07d4\x93g\x8a<W\x15\x1a\xebh\xef\xdcC\xefM6\xcbY\xa0\t\xf3\x89\x01\xa1*\x92\xbc<>\x00\x00\xe0\x94\x93m\xcf\x00\x01\x94\xe3\xbf\xf5\n\u0174$:;\xa0\x14\xd6a\u060a\x02\x1e\x19\xe0\u027a\xb2@\x00\x00\u07d4\x93o8\x13\xf5\xf6\xa1;\x8eO\xfe\xc8?\xe7\xf8&\x18jq\u0349\x1c0s\x1c\xec\x03 \x00\x00\u07d4\x93t\x86\x9dJ\x99\x11\xee\x1e\xafU\x8b\xc4\u00b6>\xc6:\xcf\u074965\u026d\xc5\u07a0\x00\x00\u07d4\x93uc\u0628\x0f\u05657\xb0\xe6m \xa0%%\xd5\u0606`\x89\x87\x86x2n\xac\x90\x00\x00\u07d4\x93v\xdc\xe2\xaf.\xc8\xdc\xdat\x1b~sEfF\x81\xd96h\x8965\u026d\xc5\u07a0\x00\x00\u07d4\x93\x86\x8d\xdb*yM\x02\xeb\xda/\xa4\x80|v\xe3`\x98X\u0709m\xee\x15\xfc|$\xa7\x80\x00\xe0\x94\x93\x9cC\x13\xd2(\x0e\xdf^\a\x1b\xce\xd8F\x06?\n\x97]T\x8a\x19i6\x89t\xc0[\x00\x00\x00\xe0\x94\x93\xa6\xb3\xabB0\x10\xf9\x81\xa7H\x9dJ\xad%\xe2b\\WA\x8a\x04F\x80\xfej\x1e\xdeN\x80\x00\u07d4\x93\xaa\x8f\x92\xeb\xff\xf9\x91\xfc\x05^\x90ne\x1a\xc7h\xd3+\u02092\xf5\x1e\u06ea\xa30\x00\x00\u07d4\x93\xb4\xbf?\xdf\xf6\xde?NV\xbamw\x99\xdcK\x93\xa6T\x8f\x89\x01\t\x10\xd4\xcd\xc9\xf6\x00\x00\u07d4\x93\xbc}\x9aJ\xbdD\u023b\xb8\xfe\x8b\xa8\x04\xc6\x1a\xd8\xd6Wl\x89\xd8\xd6\x11\x9a\x81F\x05\x00\x00\u07d4\x93\xc2\xe6N]\xe5X\x9e\xd2P\x06\xe8C\x19n\xe9\xb1\xcf\v>\x89Z\x87\xe7\xd7\xf5\xf6X\x00\x00\xe0\x94\x93\u020e-\x88b\x1e0\xf5\x8a\x95\x86\xbe\xd4\t\x89\x99\xebg\u074a\x06\x9bZ\xfa\xc7P\xbb\x80\x00\x00\u07d4\x93\xe0\xf3~\xcd\xfb\x00\x86\xe3\xe8b\xa9p4D{\x1eM\xec\x1a\x89\x01\xa0Ui\r\x9d\xb8\x00\x00\xe0\x94\x93\xe3\x03A\x1a\xfa\xf6\xc1\a\xa4A\x01\u026c[6\xe9\xd6S\x8b\x8a\r\xf9\xdd\xfe\xcd\x03e@\x00\x00\u07d4\x93\xf1\x8c\xd2R`@v\x14\x88\xc5\x13\x17M\x1eycv\x8b,\x89\x82\xff\xac\x9a\u0553r\x00\x00\u07d4\x94\x0fqQ@P\x9f\xfa\xbf\x97EF\xfa\xb3\x90\"\xa4\x19R\u0489K\xe4\xe7&{j\xe0\x00\x00\u07d4\x94,k\x8c\x95[\xc0\u0608\x12g\x8a#g%\xb3'9\xd9G\x89T\x06\x923\xbf\u007fx\x00\x00\u07d4\x94=7\x86JJS}5\xc8\u0657#\xcdd\x06\xce%b\xe6\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\x94C\x9c\xa9\xcc\x16\x9ay\u0520\x9c\xae^gvJo\x87\x1a!\x89\r\x02\xabHl\xed\xc0\x00\x00\xe0\x94\x94D\x9c\x01\xb3*\u007f\xa5Z\xf8\x10OB\xcd\xd8D\xaa\x8c\xbc@\x8a\x03\x81\x11\xa1\xf4\xf0<\x10\x00\x00\xe0\x94\x94E\xba\\0\xe9\x89a\xb8`$a\xd08]@\xfb\xd8\x03\x11\x8a\x02\x1e\x19\xe0\u027a\xb2@\x00\x00\u07d4\x94O\a\xb9o\x90\xc5\xf0\xd7\xc0\u0140S1I\xf3\xf5\x85\xa0x\x89\x04\x02\xf4\xcf\xeeb\xe8\x00\x00\u07d4\x94T\xb3\xa8\xbf\xf9p\x9f\xd0\u1407~l\xb6\u0219t\xdb\u0589\x90\xf54`\x8ar\x88\x00\x00\u07d4\x94]\x96\xeaW>\x8d\xf7&+\xbf\xa5r\"\x9bK\x16\x01k\x0f\x89\vX\x9e\xf9\x14\xc1B\x00\x00\u07d4\x94^\x18v\x9d~\xe7'\xc7\x01?\x92\xde$\xd1\x17\x96\u007f\xf3\x17\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\x94a'\x81\x03;W\xb1F\xeet\xe7S\xc6r\x01\u007fS\x85\xe4\x89\xc3(\t>a\xee@\x00\x00\xe0\x94\x94dJ\xd1\x16\xa4\x1c\xe2\xca\u007f\xbe\xc6\t\xbd\xefs\x8a*\xc7\u01ca\x01\x0f\f\xf0d\xddY \x00\x00\u07d4\x94p\xcc6YE\x86\x82\x18!\xc5\u0256\xb6\xed\xc8;mZ2\x89\x01M\x11 \u05f1`\x00\x00\xe0\x94\x94u\xc5\x10\xec\x9a&\x97\x92GtL=\x8c;\x0e\v_D\u04ca\x02\x1e\x19\xe0\u027a\xb2@\x00\x00\u07d4\x94~\x11\xe5\xea)\ro\u00f3\x80H\x97\x9e\f\xd4N\xc7\xc1\u007f\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\x94\x83\u064f\x14\xa3?\xdc\x11\x8d@9U\u00995\xed\xfc_p\x89\x18\xea;4\xefQ\x88\x00\x00\u07d4\x94\x911\xf2\x89C\x92\\\xfc\x97\xd4\x1e\f\xea\v&)s\xa70\x89\x97\xc9\xceL\xf6\xd5\xc0\x00\x00\u07d4\x94\x9f\x84\xf0\xb1\xd7\u0127\xcfI\xee\u007f\x8b,J\x13M\xe3(x\x89%\"H\u07b6\xe6\x94\x00\x00\u07d4\x94\x9f\x8c\x10{\xc7\xf0\xac\xea\xa0\xf1pR\xaa\xdb\xd2\xf9s+.\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\x94\xa7\u0368\xf4\x81\xf9\u061dB\xc3\x03\xae\x162\xb3\xb7\t\xdb\x1d\x89\x10CV\x1a\x88)0\x00\x00\u07d4\x94\xa9\xa7\x16\x911| d'\x1bQ\xc95?\xbd\xed5\x01\xa8\x89\xb5\x0f\u03ef\xeb\xec\xb0\x00\x00\u07d4\x94\xadK\xad\x82K\xd0\ub7a4\x9cX\u03bc\xc0\xff^\b4k\x89i*\xe8\x89p\x81\xd0\x00\x00\u07d4\x94\xbb\xc6}\x13\xf8\x9e\xbc\xa5\x94\xbe\x94\xbcQp\x92\f0\xd9\xf3\x89\x04X\xff\xa3\x15\nT\x00\x00\u07d4\x94\xbe:\xe5Ob\xd6c\xb0\xd4\u031e\x1e\xa8\xfe\x95V\ua7bf\x89\x01C\x13,\xa8C\x18\x00\x00\xe0\x94\x94\xc0U\xe8X5z\xaa0\xcf A\xfa\x90Y\xce\x16J\x1f\x91\x8a\x04<%\xe0\xdc\xc1\xbd\x1c\x00\x00\xe0\x94\x94\xc7B\xfdz\x8by\x06\xb3\xbf\xe4\xf8\x90O\xc0\xbe\\v\x803\x8a\x04<3\xc1\x93ud\x80\x00\x00\u07d4\x94\xcaV\xdew\u007f\xd4S\x17\u007f^\x06\x94\xc4x\xe6j\xff\x8a\x84\x89\x1b\x1a\xe4\xd6\xe2\xefP\x00\x00\xe0\x94\x94\xd8\x10t\xdbZ\xe1\x97\u04bb\x13s\xab\x80\xa8}\x12\x1cK\u04ca\x01\xfd\x934\x94\xaa_\xe0\x00\x00\u07d4\x94\u06c0xs\x86\n\xac=Z\xea\x1e\x88^R\xbf\xf2\x86\x99T\x89\xae\x8ez\v\xb5u\xd0\x00\x00\u07d4\x94\xe1\xf5\u02db\x8a\xba\xce\x03\xa1\xa6B\x82VU;i\f#U\x89\x01\x15\x8eF\t\x13\xd0\x00\x00\u07d4\x94\xef\x8b\xe4Pw\xc7\xd4\xc5e'@\u0794jbbOq?\x89\x05l\xf5Y:\x18\xf8\x80\x00\u07d4\x94\xf1?\x9f\b6\xa3\xee$7\xa8I\"\u0498M\xc0\xf7\xd5;\x89\xa2\xa02\x9b\u00ca\xbe\x00\x00\u07d4\x94\xf8\xf0W\xdb~`\xe6u\xad\x94\x0f\x15X\x85\u0464w4\x8e\x89\x15\xbeat\xe1\x91.\x00\x00\xe0\x94\x94\xfc\u03ad\xfe\\\x10\x9c^\xae\xafF-C\x871B\u020e\"\x8a\x01\x045a\xa8\x82\x93\x00\x00\x00\u07d4\x95\x03N\x16!\x86Q7\xcdG9\xb3F\xdc\x17\xda:'\xc3N\x89U\xa6\xe7\x9c\xcd\x1d0\x00\x00\u07d4\x95\fh\xa4\t\x88\x15M#\x93\xff\xf8\xda|\u0369\x96\x14\xf7,\x89\xf9AF\xfd\x8d\xcd\xe5\x80\x00\xe0\x94\x95\x0f\xe9\xc6\xca\xd5\f\x18\xf1\x1a\x9e\xd9\xc4W@\xa6\x18\x06\x12\u040a\x01\xb1\xaeMn.\xf5\x00\x00\x00\u07d4\x95!\x83\xcf\u04ce5.W\x9d6\xde\xce\u0171\x84P\xf7\xfb\xa0\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\x95'\x8b\b\xde\xe7\xc0\xf2\xc8\xc0\xf7\"\xf9\xfc\xbb\xb9\xa5$\x1f\u0689\x82\x93\t\xf6O\r\xb0\x00\x00\u07d4\x95,W\xd2\xfb\x19Q\a\xd4\xcd\\\xa3\x00wA\x19\u07ed/x\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\x955r\xf0\xeam\xf9\xb1\x97\xca\xe4\x0eK\x8e\xcc\x05lCq\u014965\u026d\xc5\u07a0\x00\x00\u07d4\x95>\xf6R\xe7\xb7i\xf5=nxjX\x95/\xa9>\xe6\xab\u725b\ny\x1f\x12\x110\x00\x00\u07d4\x95DpF1;/:^\x19\xb9H\xfd;\x8b\xed\xc8,q|\x89\x1b\x1a\xe4\xd6\xe2\xefP\x00\x00\xe0\x94\x95]\xb3\xb7C`\xb9\xa2hg~s\u03a8!f\x8a\xf6\xfa\u038a\x06ZM\xa2]0\x16\xc0\x00\x00\u07d4\x95`\xe8\xacg\x18\xa6\xa1\xcd\xcf\xf1\x89\xd6\x03\xc9\x06>A=\xa6\x89\xd8\xd7&\xb7\x17z\x80\x00\x00\u07d4\x95g\xa0\u0781\x1d\xe6\xff\t[~\xe6N\u007f\x1b\x83\xc2a[\x80\x89\x0e~\xeb\xa3A\vt\x00\x00\u07d4\x95h\x1c\xda\xe6\x9b I\xce\x10\x1e2\\u\x98\x92\xca\xc3\xf8\x11\x89\x9a\xe9*\x9b\xc9L@\x00\x00\xe0\x94\x95h\xb7\xdeuV(\xaf5\x9a\x84T=\xe25\x04\xe1^A\xe6\x8a\bxg\x83&\xea\xc9\x00\x00\x00\u07d4\x95i\xc6:\x92\x84\xa8\x05bm\xb3\xa3.\x9d#c\x93GaQ\x89j\xcb=\xf2~\x1f\x88\x00\x00\u07d4\x95\x80\x9e\x8d\xa3\xfb\xe4\xb7\xf2\x81\xf0\xb8\xb1q_B\x0f}}c\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\x95\x9fW\xfd\xedj\xe3y\x13\xd9\x00\xb8\x1e_H\xa7\x93\"\xc6'\x89\r\xdb&\x10GI\x11\x80\x00\u07d4\x95\x9f\xf1\u007f\x1dQ\xb4s\xb4@\x10\x05'U\xa7\xfa\x8cu\xbdT\x89j\xcb=\xf2~\x1f\x88\x00\x00\u07d4\x95\xa5w\xdc.\xb3\xael\xb9\xdf\xc7z\xf6\x97\xd7\xef\xdf\xe8\x9a\x01\x89\a_a\x0fp\xed \x00\x00\u07d4\x95\xcbm\x8acy\xf9J\xba\x8b\x88ViV,MD\x8eV\xa7\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\x95\xd5PB{ZQLu\x1ds\xa0\xf6\u049f\xb6]\"\xed\x10\x89\x10CV\x1a\x88)0\x00\x00\u07d4\x95\u064d\f\x10i\x90\x8f\x06zR\xac\xac+\x8bSM\xa3z\xfd\x89oY\xb60\xa9)p\x80\x00\xe0\x94\x95\xdfN4E\xd7f&$\u010e\xbat\u03de\nS\xe9\xf72\x8a\v\xdb\xc4\x1e\x03H\xb3\x00\x00\x00\u07d4\x95\xe6\xa5K-_g\xa2JHu\xafu\x10|\xa7\xea\x9f\xd2\xfa\x89Hz\x9a0E9D\x00\x00\xe0\x94\x95\xe6\xf9=\xac\"\x8b\xc7XZ%sZ\xc2\xd0v\xcc:@\x17\x8a\x01EB\xba\x12\xa37\xc0\x00\x00\u07d4\x95\xe7ad$\xcd\ta\xa7\x17'$t7\xf0\x06\x92r(\x0e\x89\x15\xaf\x1dx\xb5\x8c@\x00\x00\u07d4\x95\xe8\n\x82\xc2\f\xbe= `$,\xb9-sX\x10\xd04\xa2\x89\x01\xc3.F?\u0539\x80\x00\u07d4\x95\xf6-\x02C\xed\xe6\x1d\xad\x9a1e\xf59\x05'\rT\xe2B\x89WG=\x05\u06ba\xe8\x00\x00\u07d4\x95\xfbZ\xfb\x14\xc1\uf6b7\xd1y\xc5\xc3\x00P?\xd6j^\xe2\x89\x01\xda\xf7\xa0+\r\xbe\x80\x00\u07d4\x96\x10Y\"\x02\u0082\xab\x9b\u0628\x84Q\x8b>\v\xd4u\x817\x89\x0e\x87?D\x13<\xb0\x00\x00\xe0\x94\x96\x1cY\xad\xc7E\x05\u0446M\x1e\xcf\u02ca\xfa\x04\x12Y<\x93\x8a\bxg\x83&\xea\xc9\x00\x00\x00\u07d4\x96,\r\xec\x8a=FK\xf3\x9b\x12\x15\xea\xfd&H\n\xe4\x90\u0349l\x82\xe3\xea\xa5\x13\xe8\x00\x00\u07d4\x96,\xd2*\x8e\xdf\x1eONU\xb4\xb1]\xdb\xfb]\x9dT\x19q\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\x963K\xfe\x04\xff\xfaY\x02\x13\xea\xb3e\x14\xf38\xb8d\xb76\x89\x15\xaf\x1dx\xb5\x8c@\x00\x00\u07d4\x967\xdc\x12r=\x9cxX\x85B\uac02fO?\x03\x8d\x9d\x8965\u026d\xc5\u07a0\x00\x00\u07d4\x96N\xabK'kL\u0618>\x15\xcar\xb1\x06\x90\x0f\xe4\x1f\u0389\x1b\x1a\xe4\xd6\xe2\xefP\x00\x00\u07d4\x96b\xee\x02\x19&h+1\xc5\xf2\x00\xceEz\xbe\xa7ll\xe9\x89$Y\x0e\x85\x89\xebj\x00\x00\xe0\x94\x96l\x04x\x1c\xb5\xe6}\xde25\xd7\xf8b\x0e\x1a\xb6c\xa9\xa5\x8a\x10\r P\xdacQ`\x00\x00\u07d4\x96pv\xa8w\xb1\x8e\xc1ZA[\xb1\x16\xf0n\xf3&E\u06e3\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\x96{\xfa\xf7bC\u0379@<g\xd2\xce\xef\xde\xe9\n?\xebs\x894\x9d\x87\xf2\xa2\xdc/\x00\x00\u07d4\x96}AB\xafw\x05\x15\xddpb\xaf\x93I\x8d\xbf\xdf\xf2\x9f \x89\x01\x18T\xd0\xf9\xce\xe4\x00\x00\u07d4\x96\x8b\x14d\x8f\x01\x833h|\xd2\x13\xfad\n\xec\x04\xcec#\x8965\u026d\xc5\u07a0\x00\x00\xe0\x94\x96\x8d\xea`\xdf>\t\xae<\x8d5\x05\xe9\xc0\x80EK\xe0\xe8\x19\x8a\x01EB\xba\x12\xa37\xc0\x00\x00\u07d4\x96\x92A\x91\xb7\xdfe[3\x19\xdcma7\xf4\x81\xa7:\x0f\xf3\x89\xd9\xec\xb4\xfd \x8eP\x00\x00\u07d4\x96\x96\x05!83\x8cr/\x11@\x81\\\xf7t\x9d\r;:t\x89\x1b\x1a\xe4\xd6\xe2\xefP\x00\x00\u07d4\x96\xa5_\x00\xdf\xf4\x05\xdcM\xe5\xe5\x8cW\xf6\xf6\xf0\xca\xc5]/\x89jf\x167\x9c\x87\xb5\x80\x00\u07d4\x96\xaaW?\xed/#4\x10\u06eeQ\x80\x14[#\xc3\x1a\x02\xf0\x89]\u0212\xaa\x111\xc8\x00\x00\u07d4\x96\xadW\x9b\xbf\xa8\u06ce\xbe\xc9\u0486\xa7.Fa\xee\xd8\xe3V\x89:\v\xa4+\xeca\x83\x00\x00\u07d4\x96\xb44\xfe\x06W\xe4*\u0302\x12\xb6\x86Q9\xde\xde\x15\x97\x9c\x89\xd8\xd7&\xb7\x17z\x80\x00\x00\u07d4\x96\xb9\x06\xear\x9fFU\xaf\xe3\xe5}5'|\x96}\xfa\x15w\x8965\u026d\xc5\u07a0\x00\x00\u07d4\x96\xd6-\xfdF\b\u007fb@\x9d\x93\xdd`a\x88\xe7\x0e8\x12W\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\x96\xd9\u0328\xf5^\xea\x00@\xecn\xb3H\xa1wK\x95\xd9>\xf4\x89\xd8\xd7&\xb7\x17z\x80\x00\x00\u07d4\x96\xe7\xc0\xc9\u057f\x10\x82\x1b\xf1@\xc5X\xa1E\xb7\xca\xc2\x13\x97\x899>\xf1\xa5\x12|\x80\x00\x00\u07d4\x96\xeaj\u021a+\xac\x954{Q\u06e6=\x8b\xd5\xeb\xde\xdc\xe1\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\x96\xea\xfb\xf2\xfboM\xb9\xa46\xa7LE\xb5eDR\xe28\x19\x89\x01\x15\x8eF\t\x13\xd0\x00\x00\u07d4\x96\xebR>\x83/P\n\x01}\xe1>\xc2\u007f]6lV\x0e\xff\x89\x10\xac\u03baC\xee(\x00\x00\u07d4\x96\xf0F*\xe6\xf8\xb9`\x88\xf7\xe9\u018ct\xb9\u062d4\xb3G\x89a\t=|,m8\x00\x00\u07d4\x96\xf8 P\vp\xf4\xa3\xe3#\x9da\x9c\xff\x8f\" u\xb15\x89\n\u05ce\xbcZ\xc6 \x00\x00\xe0\x94\x96\xfeY\xc3\u06f3\xaa|\xc8\xcbbH\fe\xe5nb\x04\xa7\xe2\x8a\x04<3\xc1\x93ud\x80\x00\x00\u07d4\x96\xffoP\x99h\xf3l\xb4,\xbaH\xdb2\xf2\x1fVv\xab\xf8\x89j\xcb=\xf2~\x1f\x88\x00\x00\u07d4\x97\t8R*\xfb^\x8f\x99Hs\xc9\xfb\xdc&\xe3\xb3~1L\x8965\u026d\xc5\u07a0\x00\x00\u07d4\x97\n\xbdS\xa5O\xcaJd) |\x18-MW\xbb9\u0520\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\x97\r\x8b\x8a\x00\x16\xd1C\x05O\x14\x9f\xb3\xb8\xe5P\xdc\a\x97\u01c965\u026d\xc5\u07a0\x00\x00\u07d4\x97,/\x96\xaa\x00\u03ca/ Z\xbc\xf8\x93|\fu\xf5\xd8\u0649\n\u05ce\xbcZ\xc6 \x00\x00\u07d4\x97?N6\x1f\xe5\xde\u0358\x9dL\x8f}|\xc9y\x908]\xaf\x89\x15\x0f\x85C\xa3\x87B\x00\x00\u07d4\x97M\x05A\xabJG\xec\u007fu6\x9c\x00i\xb6J\x1b\x81w\x10\x89\x15\xaf\x1dx\xb5\x8c@\x00\x00\u0794\x97M/\x17\x89_)\x02\x04\x9d\xea\xae\xcf\t\xc3\x04e\a@-\x88\xcc\x19\u00947\xab\x80\x00\u07d4\x97R\xd1O^\x10\x93\xf0qq\x1c\x1a\xdb\xc4\xe3\xeb\x1e\\W\xf3\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\x97V\xe1v\xc9\xefi>\xe1\xee\u01b9\xf8\xb1Q\xd3\x13\xbe\xb0\x99\x89A\rXj \xa4\xc0\x00\x00\u07d4\x97_7d\xe9{\xbc\xcfv|\xbd;y[\xa8m\x8b\xa9\x84\x0e\x89\x12\xc1\xb6\xee\xd0=(\x00\x00\xe0\x94\x97j\x18Sj\xf4\x18tBc\b\x87\x1b\xcd\x15\x12\xa7u\xc9\xf8\x8a\x02\x1e\x19\xe0\u027a\xb2@\x00\x00\u07d4\x97n<\xea\xf3\xf1\xafQ\xf8\u009a\xff]\u007f\xa2\x1f\x03\x86\xd8\xee\x89\r\x02\xabHl\xed\xc0\x00\x00\xe0\x94\x97w\xcca\xcfuk\xe3\xb3\xc2\f\xd4I\x1ci\xd2u\xe7\xa1 \x8a\x02\x1e\x19\xe0\u027a\xb2@\x00\x00\u07d4\x97\x81\v\xaf\xc3~\x840c2\xaa\xcb5\xe9*\xd9\x11\xd2=$\x8965\u026d\xc5\u07a0\x00\x00\u07d4\x97\x8cC\f\xe45\x9b\x06\xbc,\xdf\\)\x85\xfc\x95\x0eP\xd5\u0209\x1a\x05V\x90\xd9\u06c0\x00\x00\u07d4\x97\x95\xf6C\x19\xfc\x17\xdd\x0f\x82a\xf9\xd2\x06\xfbf\xb6L\xd0\u0249\n\u05ce\xbcZ\xc6 \x00\x00\u07d4\x97\x99\xca!\xdb\xcfi\xbf\xa1\xb3\xf7+\xacQ\xb9\xe3\xcaX|\xf9\x89\\(=A\x03\x94\x10\x00\x00\u07d4\x97\x9c\xbf!\xdf\xec\x8a\xce?\x1c\x19m\x82\u07d6%4\xdf9O\x89\x99\x91\xd4x\xddM\x16\x00\x00\u07d4\x97\x9dh\x1ca}\xa1o!\xbc\xac\xa1\x01\xed\x16\xed\x01Z\xb6\x96\x89e\xea=\xb7UF`\x00\x00\u07d4\x97\x9f0\x15\x8bWK\x99\x9a\xab4\x81\a\xb9\xee\xd8[\x1f\xf8\xc1\x894\x95tD\xb8@\xe8\x00\x00\u07d4\x97\xa8o\x01\xce?|\xfdDA3\x0e\x1c\x9b\x19\xe1\xb1\x06\x06\xef\x89lk\x93[\x8b\xbd@\x00\x00\xe0\x94\x97\xb9\x1e\xfesP\xc2\xd5~~@k\xab\x18\xf3a{\xcd\xe1J\x8a\x02\x1e\x19\x99\xbb\xd5\u04be\x00\x00\u07d4\x97\xd0\xd9r^;p\xe6u\x841s\x93\x8e\xd3q\xb6,\u007f\xac\x89\t79SM(h\x00\x00\u07d4\x97\xd9\xe4jv\x04\u05f5\xa4\xeaN\xe6\x1aB\xb3\xd25\x0f\xc3\xed\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\x97\xdc&\xecg\n1\xe0\"\x1d*u\xbc]\xc9\xf9\f\x1fo\u0509\x02\xb5\xe3\xaf\x16\xb1\x88\x00\x00\xe0\x94\x97\xde!\xe4!\xc3\u007f\xe4\xb8\x02_\x9aQ\xb7\xb3\x90\xb5\xdfx\x04\x8a\x10\xf0\xcf\x06M\u0552\x00\x00\x00\u07d4\x97\xe2\x89s\xb8`\xc5g@(\x00\xfb\xb6<\xe3\x9a\x04\x8a=y\x89\x05B%:\x12l\xe4\x00\x00\u07d4\x97\xe5\xcca'\xc4\xf8\x85\xbe\x02\xf4KB\xd1\u0230\xac\x91\u44c9\n\u05ce\xbcZ\xc6 \x00\x00\u07d4\x97\xf1\xfeL\x80\x83\xe5\x96!*\x18w(\xdd\\\xf8\n1\xbe\u0149\x01\x15\x8eF\t\x13\xd0\x00\x00\xe0\x94\x97\xf7v\x06W\xc1\xe2\x02u\x90\x86\x96>\xb4!\x1c_\x819\xb9\x8a\n\x8a\t\u007f\xcb=\x17h\x00\x00\xe0\x94\x97\xf9\x9bk\xa3\x13F\u0358\xa9\xfeL0\x8f\x87\u0165\x8cQQ\x8a\x01EB\xba\x12\xa37\xc0\x00\x00\u07d4\x98\n\x84\xb6\x86\xfc1\xbd\xc8<\"\x10XTjq\xb1\x1f\x83\x8a\x89*AUH\xaf\x86\x81\x80\x00\u07d4\x98\x10\xe3J\x94\xdbn\xd1V\xd08\x9a\x0e+\x80\xf4\xfdk\n\x8a\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\x98\x1d\xdf\x04\x04\xe4\xd2-\xdaUj\a&\xf0\v-\x98\xab\x95i\x8965f3\xeb\xd8\xea\x00\x00\xe0\x94\x98\x1fq'u\xc0\xda\xd9u\x18\xff\xed\xcbG\xb9\xad\x1dl'b\x8a\x01je\x02\xf1Z\x1eT\x00\x00\u07d4\x984h!\x80\xb9\x82\xd1f\xba\u06dd\x9d\x1d\x9b\xbf\x01m\x87\xee\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\x986\xb4\xd3\x04sd\x1a\xb5j\xee\xe1\x92Bv\x1drrQx\x89lk\x93[\x8b\xbd@\x00\x00\xe0\x94\x989sB\xec_=L\xb8w\xe5N\xf5\xd6\xf1\xd3fs\x1b\u050a\x01@a\xb9\xd7z^\x98\x00\x00\xe0\x94\x98Fd\x886\xa3\a\xa0W\x18O\xd5\x1fb\x8a_\x8c\x12B|\x8a\x04\vi\xbfC\xdc\xe8\xf0\x00\x00\xe0\x94\x98Jy\x85\xe3\xcc~\xb5\xc96\x91\xf6\xf8\xcc{\x8f$]\x01\xb2\x8a\x01EB\xba\x12\xa37\xc0\x00\x00\xe0\x94\x98]p\xd2\a\x89+\xed9\x85\x90\x02N$!\xb1\xcc\x11\x93Y\x8a\x04<3\xc1\x93ud\x80\x00\x00\xe0\x94\x98m\xf4~v\xe4\u05e7\x89\xcd\xee\x91<\u0243\x16P\x93l\x9d\x8a\x01\x0f\f\xf0d\xddY \x00\x00\u07d4\x98t\x80?\xe1\xf3\xa06^y\"\xb1Bp\xea\xeb\x03,\xc1\xb5\x89<\xf5\x92\x88$\xc6\xc2\x00\x00\u07d4\x98ub4\x95\xa4l\xdb\xf2YS\x0f\xf88\xa1y\x9e\u00c9\x91\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\x98v\x18\xc8VV |{\xac\x15\a\xc0\xff\xef\xa2\xfbd\xb0\x92\x89\x03}\xfeC1\x89\xe3\x80\x00\u07d4\x98|\x9b\xcdn?9\x90\xa5+\xe3\xed\xa4q\f'Q\x8fOr\x89\x15\xaf\x1dx\xb5\x8c@\x00\x00\u07d4\x98\x82\x96|\xeeh\u04a89\xfa\u062bJ|=\xdd\xf6\xc0\xad\u0209Hx\xbe\x1f\xfa\xf9]\x00\x00\u07d4\x98\x85\\}\xfb\xee3SD\x90J\x12\xc4\fs\x17\x95\xb1:T\x899\xfb\xae\x8d\x04-\xd0\x00\x00\u07d4\x98\x9c\f\xcf\xf6T\xda\x03\xae\xb1\x1a\xf7\x01\x05Ea\xd6)~\x1d\x89\xd8\xd7&\xb7\x17z\x80\x00\x00\u07d4\x98\xa0\xe5Lm\x9d\u023e\x96'l\xeb\xf4\xfe\xc4`\xf6#]\x85\x89j\u0202\x10\tR\u01c0\x00\u07d4\x98\xb7i\xcc0\\\xec\xfbb\x9a\x00\xc9\a\x06\x9d~\xf9\xbc:\x12\x89\x01h\u048e?\x00(\x00\x00\xe0\x94\x98\xbaN\x9c\xa7/\xdd\xc2\fi\xb49ov\xf8\x18?z*N\x8a\x02\xb5\xe3\xaf\x16\xb1\x88\x00\x00\x00\u07d4\x98\xbeimQ\xe3\x90\xff\x1cP\x1b\x8a\x0fc1\xb6(\xdd\u016d\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\x98\xbe\u04e7.\xcc\xfb\xaf\xb9#H\x92\x93\xe4)\xe7\x03\xc7\xe2[\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\x98\xbfJ\xf3\x81\v\x84#\x87\xdbp\xc1MF\t\x96&\x00=\x10\x89\xd8\xd7&\xb7\x17z\x80\x00\x00\u07d4\x98\xc1\x0e\xbf,O\x97\u02e5\xa1\xab?*\xaf\xe1\xca\xc4#\xf8\u02c9\x10CV\x1a\x88)0\x00\x00\u07d4\x98\xc1\x9d\xba\x81\v\xa6\x11\xe6\x8f/\x83\xee\x16\xf6\xe7tO\f\x1f\x89\n\u05ce\xbcZ\xc6 \x00\x00\xe0\x94\x98\xc5IJ\x03\xac\x91\xa7h\xdf\xfc\x0e\xa1\xdd\u0b3f\x88\x90\x19\x8a*Z\x05\x8f\u0095\xed\x00\x00\x00\u07d4\x98\xd2\x04\xf9\b_\x8c\x8e}\xe2>X\x9bd\xc6\xef\xf6\x92\xccc\x89lk\x93[\x8b\xbd@\x00\x00\xe0\x94\x98\xd3s\x19\x92\xd1\xd4\x0e\x12\x11\xc7\xf75\xf2\x18\x9a\xfa\a\x02\xe0\x8a\x01\xb1\xaeMn.\xf5\x00\x00\x00\u07d4\x98\xe2\xb6\xd6\x06\xfd-i\x91\xc9\xd6\xd4\a\u007f\xdf?\xddE\x85\u06890\xdf\x1ao\x8a\xd6(\x00\x00\u07d4\x98\xe3\xe9\v(\xfc\xca\ue087y\xb8\xd4\nUh\xc4\x11n!\x89\x02+\x1c\x8c\x12'\xa0\x00\x00\u07d4\x98\xe6\xf5G\u06c8\xe7_\x1f\x9c\x8a\xc2\xc5\xcf\x16'\xbaX\v>\x8965\u026d\xc5\u07a0\x00\x00\xe0\x94\x98\xf4\xaf:\xf0\xae\xde_\xaf\xdcB\xa0\x81\xec\xc1\xf8\x9e<\xcf \x8a\x01\xfd\x934\x94\xaa_\xe0\x00\x00\u07d4\x98\xf6\xb8\xe6!=\xbc\x9aU\x81\xf4\xcc\xe6e_\x95%+\xdb\a\x89\x11Xr\xb0\xbc\xa40\x00\x00\u07d4\x99\te\r\u05719{\x8b\x8b\x0e\xb6\x94\x99\xb2\x91\xb0\xad\x12\x13\x89\n\u05ce\xbcZ\xc6 \x00\x00\u07d4\x99\x11s`\x19G\xc2\bJb\xd69R~\x96\x15\x12W\x9a\xf9\x89 \x86\xac5\x10R`\x00\x00\u07d4\x99\x12\x9d[<\f\xdeG\xea\r\xefM\xfc\a\r\x1fJY\x95'\x89lk\x93[\x8b\xbd@\x00\x00\xe0\x94\x99\x17\u058dJ\xf3A\xd6Q\xe7\xf0\a\\m\xe6\xd7\x14Nt\t\x8a\x012\xd4Gl\b\xe6\xf0\x00\x00\u07d4\x99\x1a\xc7\xcap\x97\x11_& ^\xee\x0e\xf7\xd4\x1e\xb4\xe3\x11\xae\x89\x01\x15\x8eF\t\x13\xd0\x00\x00\u0794\x99#e\xd7d\xc5\xce5@9\xdd\xfc\x91.\x02:u\xb8\xe1h\x88\xfc\x93c\x92\x80\x1c\x00\x00\u07d4\x99&F\xac\x1a\u02ab\xf5\u076b\xa8\xf9B\x9a\xa6\xa9Nt\x96\xa7\x8967Pz0\xab\xeb\x00\x00\u07d4\x99&\x83'\xc3s3.\x06\xc3\xf6\x16B\x87\xd4U\xb9\xd5\xfaK\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\x99(\xffqZ\xfc:+`\xf8\xebL\u013aN\xe8\u06b6\u5749\x17\xda:\x04\u01f3\xe0\x00\x00\u07d4\x992\xef\x1c\x85\xb7Z\x9b*\x80\x05}P\x874\xc5\x10\x85\xbe\u0309\x02\xb8?\xa50\x1dY\x00\x00\xe0\x94\x99?\x14ax`^f\xd5\x17\xbex.\xf0\xb3\xc6\x1aN\x19%\x8a\x01|\x1f\x055\u05e5\x83\x00\x00\xe0\x94\x99A7\x04\xb1\xa3.p\xf3\xbc\ri\u0748\x1c8VkT\u02ca\x05\xcckiF1\xf7\x12\x00\x00\u07d4\x99AR\xfc\x95\xd5\xc1\u028b\x88\x11:\xbb\xadMq\x0e@\xde\xf6\x89\x1b\x1a\xe4\xd6\xe2\xefP\x00\x00\u07d4\x99D\xfe\xe9\xd3JJ\x88\x00#\u01c92\xc0\vY\xd5\xc8*\x82\x89(\xa8\xa5k6\x90\a\x00\x00\u07d4\x99L\u00b5\"~\xc3\xcf\x04\x85\x12F|A\xb7\xb7\xb7H\x90\x9f\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\x99q\xdf`\xf0\xaef\xdc\xe9\xe8\xc8N\x17\x14\x9f\t\xf9\xc5/d\x89\n\u05ce\xbcZ\xc6 \x00\x00\xe0\x94\x99v\x94~\xff_j\xe5\xda\b\xddT\x11\x92\xf3x\xb4(\xff\x94\x8a\x01\xb1\xaeMn.\xf5\x00\x00\x00\u07d4\x99}e\x92\xa3\x15\x89\xac\xc3\x1b\x99\x01\xfb\xeb<\xc3\xd6[2\x15\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\x99\x82\xa5\x89\x0f\xfbT\x06\u04ec\xa8\u04bf\xc1\xddp\xaa\xa8\n\xe0\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\x99\x87\x8f\x9dn\n~\u066e\u01c2\x97\xb78y\xa8\x01\x95\xaf\xe0\x89\xd7\xc1\x98q\x0ef\xb0\x00\x00\u07d4\x99\x8c\x1f\x93\xbc\xdbo\xf2<\x10\xd0\u0712G(\xb7;\xe2\xff\x9f\x896[\xf3\xa43\xea\xf3\x00\x00\u07d4\x99\x91aL[\xaaG\xddl\x96\x87FE\xf9z\xdd,=\x83\x80\x89j\xcb=\xf2~\x1f\x88\x00\x00\u07d4\x99\x92J\x98\x16\xbb}\xdf?\xec\x18D\x82\x8e\x9a\xd7\xd0k\xf4\xe6\x89_h\xe8\x13\x1e\u03c0\x00\x00\u07d4\x99\x99vh\xf7\xc1\xa4\xff\x9e1\xf9\x97z\xe3\"K\u02c8z\x85\x89\x0f\xc969(\x01\xc0\x00\x00\u07d4\x99\x9cI\xc1t\xca\x13\xbc\x83l\x1e\n\x92\xbf\xf4\x8b'\x15C\u0289\xb1\xcf$\xdd\u0431@\x00\x00\u07d4\x99\xa4\xde\x19\xde\u05d0\b\xcf\xdc\xd4]\x01M.XK\x89\x14\xa8\x89QP\xae\x84\xa8\xcd\xf0\x00\x00\u07d4\x99\xa9k\xf2$.\xa1\xb3\x9e\xceo\xcc\r\x18\xae\xd0\f\x01y\xf3\x89\x10CV\x1a\x88)0\x00\x00\u07d4\x99\xb0\x18\x93+\xca\xd3U\xb6y+%]\xb6p-\xec\x8c\xe5\u0749\xd8\xd8X?\xa2\xd5/\x00\x00\u07d4\x99\xb7C\xd1\xd9\xef\xf9\r\x9a\x194\xb4\xdb!\xd5\x19\u061bJ8\x89\x05k\xc7^-c\x10\x00\x00\u07d4\x99\xb8\xc8$\x86\x9d\xe9\xed$\xf3\xbf\xf6\x85L\xb6\xddE\xcc?\x9f\x89e\xea=\xb7UF`\x00\x00\u07d4\x99\xc0\x17L\xf8N\a\x83\xc2 \xb4\xebj\xe1\x8f\xe7\x03\x85J\u04c9py\xa2W=\fx\x00\x00\u07d4\x99\xc1\xd9\xf4\fj\xb7\xf8\xa9/\xce/\xdc\xe4zT\xa5\x86\xc5?\x895e\x9e\xf9?\x0f\xc4\x00\x00\u07d4\x99\xc26\x14\x1d\xae\xc87\xec\xe0O\xda\xee\x1d\x90\u03cb\xbd\xc1\x04\x89ve\x16\xac\xac\r \x00\x00\u07d4\x99\xc3\x1f\xe7HX7\x87\xcd\xd3\xe5%\xb2\x81\xb2\x18\x96\x179\xe3\x897\b\xba\xed=h\x90\x00\x00\u07d4\x99\xc4u\xbf\x02\xe8\xb9!J\xda_\xad\x02\xfd\xfd\x15\xba6\\\f\x89 \t\xc5\u023fo\xdc\x00\x00\u07d4\x99\u0203%\x85F\xcc~N\x97\x1fR.8\x99\x18\xda^\xa6:\x89\xd8\xd7&\xb7\x17z\x80\x00\x00\u07d4\x99\xc9\xf9>E\xfe<\x14\x18\xc3S\xe4\u016c8\x94\xee\xf8\x12\x1e\x89\x05\x85\xba\xf1E\x05\v\x00\x00\xe0\x94\x99\xd1W\x9c\xd4&\x82\xb7dN\x1dOq(D\x1e\xef\xfe3\x9d\x8a\x04<3\xc1\x93ud\x80\x00\x00\xe0\x94\x99\u0475\x85\x96_@jB\xa4\x9a\x1c\xa7\x0fv\x9evZ?\x98\x8a\x03\x89O\x0eo\x9b\x9fp\x00\x00\u07d4\x99\xdf\xd0PL\x06\xc7C\xe4e4\xfd{U\xf1\xf9\xc7\xec3)\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\x99\xf4\x14|\xcck\u02c0\u0304.i\xf6\xd0\x0e0\xfaA3\u0649\x15\xaf\x1dx\xb5\x8c@\x00\x00\u07d4\x99\xf7\u007f\x99\x8b \xe0\xbc\xdc\xd9\xfc\x83\x86ARl\xf2Y\x18\xef\x89a\t=|,m8\x00\x00\u07d4\x99\xfa\xd5\x008\xd0\xd9\xd4\xc3\xfb\xb4\xbc\xe0V\x06\xec\xad\xcdQ!\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\x99\xfe\r \x12(\xa7S\x14VU\xd4(\xeb\x9f\xd9I\x85\xd3m\x89i \xbf\xf3QZ:\x00\x00\u07d4\x9a\a\x9c\x92\xa6)\xca\x15\xc8\xca\xfa.\xb2\x8d[\xc1z\xf8(\x11\x89\x1b\x1a\xe4\xd6\xe2\xefP\x00\x00\u07d4\x9a\r<\xee=\x98\x92\xea;7\x00\xa2\u007f\xf8A@\xd9\x02T\x93\x89\x03@\xaa\xd2\x1b;p\x00\x00\u07d4\x9a$\u038dH\\\xc4\xc8nI\u07b3\x90\"\xf9,t0\xe6~\x89Fy\x1f\xc8N\a\xd0\x00\x00\u07d4\x9a,\xe4;]\x89\u0593k\x8e\x8c5G\x91\xb8\xaf\xff\x96$%\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\x9a9\x01bS^9\x88w\xe4\x16x}b9\xe0uN\x93|\x8965\u026d\xc5\u07a0\x00\x00\u07d4\x9a=\xa6P#\xa10 \xd2!E\xcf\xc1\x8b\xab\x10\xbd\x19\xceN\x89\x18\xbfn\xa3FJ:\x00\x00\xe0\x94\x9a>+\x1b\xf3F\xdd\a\v\x02sW\xfe\xacD\xa4\xb2\xc9}\xb8\x8a\x02\x1e\x19\xe0\u027a\xb2@\x00\x00\u07d4\x9aL\xa8\xb8!\x17\x89NC\xdbr\xb9\xfax\xf0\xb9\xb9:\xce\t\x89\x02\xb5\xe3\xaf\x16\xb1\x88\x00\x00\u07d4\x9aR.R\xc1\x95\xbf\xb7\xcf_\xfa\xae\u06d1\xa3\xbath\x16\x1d\x8965\u026d\xc5\u07a0\x00\x00\u07d4\x9aZ\xf3\x1c~\x063\x9a\u0234b\x8d|M\xb0\xce\x0fE\u0224\x89\x1b\x1a\xe4\xd6\xe2\xefP\x00\x00\u0794\x9ac?\xcd\x11,\xce\xebv_\xe0A\x81ps*\x97\x05\u7708\xfc\x93c\x92\x80\x1c\x00\x00\u07d4\x9ac\u0445\xa7\x91)\xfd\xab\x19\xb5\x8b\xb61\xea6\xa4 TN\x89\x02F\xdd\xf9yvh\x00\x00\u07d4\x9ag\b\u0778\x90<(\x9f\x83\xfe\x88\x9c\x1e\xdc\xd6\x1f\x85D#\x8965\u026d\xc5\u07a0\x00\x00\u07d4\x9ao\xf5\xf6\xa7\xaf{z\xe0\xed\x9c \xec\xecP#\u0481\xb7\x86\x89\x8a\x12\xb9\xbdjg\xec\x00\x00\xe0\x94\x9a\x82\x82m<)H\x1d\xcc+\u0495\x00G\xe8\xb6\x04\x86\xc38\x8a\x04<3\xc1\x93ud\x80\x00\x00\u07d4\x9a\x8e\xcaA\x89\xffJ\xa8\xff~\u0536\xb7\x03\x9f\t\x02!\x9b\x15\x89\x01\x15\x8eF\t\x13\xd0\x00\x00\u07d4\x9a\x95;[\xccp\x93y\xfc\xb5Y\u05f9\x16\xaf\u06a5\f\xad\u0309\x05k\xc7^-c\x10\x00\x00\u07d4\x9a\x99\v\x8a\xebX\x8d~\xe7\xec.\xd8\xc2\xe6Os\x82\xa9\xfe\xe2\x89\x01\xd1'\xdbi\xfd\x8b\x00\x00\u07d4\x9a\x9d\x1d\xc0\xba\xa7}n \xc3\xd8I\u01c8b\xdd\x1c\x05L\x87\x89/\xb4t\t\x8fg\xc0\x00\x00\xe0\x94\x9a\xa4\x8cf\xe4\xfbJ\u0419\x93N2\x02.\x82t'\xf2w\xba\x8a\x02\x1e\x19\xe0\u027a\xb2@\x00\x00\u07d4\x9a\xa80\x8fB\x91\x0eZ\xde\t\xc1\xa5\xe2\x82\xd6\xd9\x17\x10\xbd\xbf\x89\n\u05ce\xbcZ\xc6 \x00\x00\u07d4\x9a\xaa\xfa\x00gd~\u0659\x06kzL\xa5\xb4\xb3\xf3\xfe\xaao\x8965\u026d\xc5\u07a0\x00\x00\u07d4\x9a\xb9\x88\xb5\x05\xcf\xee\x1d\xbe\x9c\u044e\x9bTs\xb9\xa2\xd4\xf56\x89\x11X\xe4`\x91=\x00\x00\x00\u07d4\x9a\xb9\x8dm\xbb\x1e\xaa\xe1mE\xa0EhT\x1a\xd3\xd8\xfe\x06\u0309\x0e\xc5\x04d\xfe#\xf3\x80\x00\xe0\x94\x9a\xba+^'\xffx\xba\xaa\xb5\xcd\u0248\xb7\xbe\x85\\\xeb\xbd\u038a\x02\x1e\f\x00\x13\a\n\xdc\x00\x00\u07d4\x9a\xc4\xdaQ\xd2x\"\xd1\xe2\b\xc9n\xa6J\x1e[U)\x97#\x89\x05lUy\xf7\"\x14\x00\x00\u0794\x9a\xc8S\x97y*i\u05cf(k\x86C*\a\xae\u03b6\x0ed\x88\xc6s\xce<@\x16\x00\x00\xe0\x94\x9a\xc9\a\xee\x85\xe6\xf3\xe2#E\x99\x92\xe2V\xa4?\xa0\x8f\xa8\xb2\x8a\x02\x1e\x19\xe0\u027a\xb2@\x00\x00\u07d4\x9a\xd4\u007f\xdc\xf9\u0354-(\xef\xfd[\x84\x11[1\xa6X\xa1>\x89\xb2Y\xec\x00\xd5;(\x00\x00\u07d4\x9a\xdb\u04fc{\n\xfc\x05\xd1\xd2\xed\xa4\x9f\xf8c\x93\x9cH\xdbF\x89\n\xd6\xee\xdd\x17\xcf;\x80\x00\u07d4\x9a\xdfE\x8b\xff5\x99\xee\xe1\xa2c\x98\x85<W[\u00ccc\x13\x89\x0f-\xc7\xd4\u007f\x15`\x00\x00\u07d4\x9a\xe1;\u0602\xf2Weu\x92\x1a\x94\x97L\xbe\xa8a\xba\r5\x89\xabM\xcf9\x9a:`\x00\x00\u07d4\x9a\xe9Gk\xfe\xcd5\x91\x96M\xd3%\u03cc*$\xfa\xed\x82\xc1\x89\xd8\xd7&\xb7\x17z\x80\x00\x00\u07d4\x9a\xf1\x00\xcc=\xae\x83\xa34\x02\x05\x1c\xe4Ik\x16aT\x83\xf6\x89lk\x93[\x8b\xbd@\x00\x00\xe0\x94\x9a\xf1\x13\x99Q\x1c!1\x81\xbf\xda:\x8b&L\x05\xfc\x81\xb3\u038a\x02\xf6\xf1\a\x80\xd2,\xc0\x00\x00\u0794\x9a\xf5\u0249L3\xe4,,Q\x8e:\xc6p\xea\x95\x05\u0475>\x88\xfc\x93c\x92\x80\x1c\x00\x00\u07d4\x9a\xf9\xdb\xe4t\"\xd1w\xf9E\xbd\xea\xd7\xe6\xd8)05b0\x89\u0556{\xe4\xfc?\x10\x00\x00\u07d4\x9a\xfaSkLf\xbc8\xd8u\u0133\x00\x99\xd9&\x1f\xdb8\xeb\x89\v*\x8f\x84*w\xbc\x80\x00\u07d4\x9b\x06\xad\x84\x1d\xff\xbeL\xcfF\xf1\x03\x9f\u00c6\xf3\xc3!Dn\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\x9b\x11h\u078a\xb6KGU/3\x89\x80\n\x9c\xc0\x8bFf\u03c9]\u0212\xaa\x111\xc8\x00\x00\u07d4\x9b\x18\x11\xc3\x05\x1fF\xe6d\xaeK\xc9\xc8$\u0445\x92\xc4WJ\x89\n\xd6\xee\xdd\x17\xcf;\x80\x00\u07d4\x9b\x18G\x86U\xa4\x85\x1c\xc9\x06\xe6`\xfe\xaca\xf7\xf4\u023f\xfc\x89\xe2G\x8d8\x90}\x84\x00\x00\u07d4\x9b\"\xa8\r\\{3t\xa0[D`\x81\xf9}\n4\a\x9e\u007f\x89\xa2\xa1]\tQ\x9b\xe0\x00\x00\u07d4\x9b+\xe7\xf5gT\xf5\x05\xe3D\x1a\x10\xf7\xf0\xe2\x0f\xd3\xdd\xf8I\x89\x12nr\xa6\x9aP\xd0\x00\x00\u07d4\x9b2\xcfOQ\x15\xf4\xb3J\x00\xa6La}\xe0c\x875C#\x89\x05\xb8\x1e\u0608 |\x80\x00\u07d4\x9bC\u0739_\xde1\x80u\xa5g\xf1\xe6\xb5v\x17\x05^\xf9\xe8\x89\u0556{\xe4\xfc?\x10\x00\x00\u07d4\x9bDO\xd37\xe5\xd7R\x93\xad\xcf\xffp\xe1\xea\x01\xdb\x022\"\x89\x05k\xc7^-c\x10\x00\x00\u07d4\x9bH$\xff\x9f\xb2\xab\xdaUM\xeeO\xb8\xcfT\x91eW\x061\x89\x01\x15\x8eF\t\x13\xd0\x00\x00\u07d4\x9bL'\x15x\f\xa4\xe9\x9e`\xeb\xf2\x19\xf1Y\f\x8c\xadP\n\x89V\xbcu\xe2\xd61\x00\x00\x00\u07d4\x9bY\xeb!;\x1eue\xe4PG\xe0N\xa07O\x10v-\x16\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\x9b\\9\xf7\xe0\xac\x16\x8c\x8e\xd0\xed4\x04w\x11}\x1bh.\xe9\x89\x05P\x05\xf0\xc6\x14H\x00\x00\u07d4\x9b^\xc1\x8e\x83\x13\x88}\xf4a\u0490.\x81\xe6z\x8f\x11;\xb1\x89\x05k\xc7^-c\x10\x00\x00\u07d4\x9bd\xd3\u034d+s\xf6hA\xb5\xc4k\xb6\x95\xb8\x8a\x9a\xb7]\x89\x01 :Ov\f\x16\x80\x00\u07d4\x9be\x8f\xb3a\xe0F\xd4\xfc\xaa\x8a\xefm\x02\xa9\x91\x11\"6%\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\x9bfA\xb1>\x17/\xc0r\xcaK\x83'\xa3\xbc(\xa1[f\xa9\x89\x06\x81U\xa46v\xe0\x00\x00\xe0\x94\x9bh\xf6t\x16\xa6;\xf4E\x1a1\x16L\x92\xf6r\xa6\x87Y\xe9\x8a\f\xb4\x9bD\xba`-\x80\x00\x00\u07d4\x9bw6i\xe8}v\x01\x8c\t\x0f\x82U\xe5D\t\xb9\u0728\xb2\x89\x01\x15\x8eF\t\x13\xd0\x00\x00\u07d4\x9bw\xeb\xce\xd7\xe2\x15\xf0\x92\x0e\x8c+\x87\x00$\xf6\xec\xb2\xff1\x8965\u026d\xc5\u07a0\x00\x00\u07d4\x9b|\x88\x10\xcc|\u021e\x80Nm>8\x12\x18PG(w\xfe\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\x9b\xa5=\xc8\xc9^\x9aG/\xeb\xa2\xc4\xe3,\x1d\xc4\xdd{\xabF\x89Hz\x9a0E9D\x00\x00\xe0\x94\x9b\xac\xd3\xd4\x0f;\x82\xac\x91\xa2d\xd9\u060d\x90\x8e\xac\x86d\xb9\x8a\x04<3\xc1\x93ud\x80\x00\x00\u07d4\x9b\xb7`\xd5\u0089\xa3\xe1\xdb\x18\xdb\tSE\xcaA;\x9aC\u0089\n\xad\xec\x98?\xcf\xf4\x00\x00\u07d4\x9b\xb7b\x04\x18j\xf2\xf6;\xe7\x91h`\x16\x87\xfc\x9b\xadf\x1f\x89\x10CV\x1a\x88)0\x00\x00\u07d4\x9b\xb9\xb0*&\xbf\xe1\xcc\xc3\xf0\xc6!\x9e&\x1c9\u007f\xc5\xcax\x89Hz\x9a0E9D\x00\x00\u07d4\x9b\xc5s\xbc\xda#\xb8\xb2o\x90s\xd9\f#\x0e\x8eq\xe0'\v\x896/u\xa40]\f\x00\x00\u07d4\x9b\xd7\u00caB\x100JMe>\xde\xff\x1b<\xe4_\xcexC\x89\x0fI\x89A\xe6d(\x00\x00\xe0\x94\x9b\u0600h\xe10u\xf3\xa8\xca\xc4d\xa5\xf9I\xd6\xd8\x18\xc0\xf6\x8a\x01EB\xba\x12\xa37\xc0\x00\x00\u07d4\x9b\xd9\x05\xf1q\x9f\u01ec\xd0\x15\x9dM\xc1\xf8\xdb/!G#8\x8965\u026d\xc5\u07a0\x00\x00\u07d4\x9b\xdb\u071b\x9741\xd1<\x89\xa3\xf9u~\x9b;bu\xbf\u01c9\x1b\x1a}\u03caD\u04c0\x00\u07d4\x9b\xe3\xc3)\xb6*(\xb8\xb0\x88l\xbd\x8b\x99\xf8\xbc\x93\f\xe3\xe6\x89\x04\t\xe5+H6\x9a\x00\x00\xe0\x94\x9b\xf5\x8e\xfb\xea\a\x84\xeb\x06\x8a\xde\u03e0\xbb!P\x84\xc7:5\x8a\x01:k+VHq\xa0\x00\x00\u07d4\x9b\xf6r\xd9y\xb3fR\xfcR\x82Tzjk\xc2\x12\xaeCh\x89#\x8f\xd4,\\\xf0@\x00\x00\xe0\x94\x9b\xf7\x03\xb4\x1c6$\xe1_@T\x96#\x90\xbc\xba0R\xf0\xfd\x8a\x01H>\x01S<.<\x00\x00\u07d4\x9b\xf7\x1f\u007f\xb57\xacT\xf4\xe5\x14\x94\u007f\xa7\xffg(\xf1m/\x89\x01\u03c4\xa3\n\n\f\x00\x00\u07d4\x9b\xf9\xb3\xb2\xf2<\xf4a\xebY\x1f(4\v\xc7\x19\x93\x1c\x83d\x8965\u026d\xc5\u07a0\x00\x00\xe0\x94\x9b\xfce\x9c\x9c`\x1e\xa4*k!\xb8\xf1p\x84\xec\x87\xd7\x02\x12\x8a\x02\x1e\x19\xe0\u027a\xb2@\x00\x00\u07d4\x9b\xff\xf5\r\xb3jxUU\xf0vR\xa1S\xb0\xc4+\x1b\x8bv\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\x9c\x05\xe9\xd0\xf0u\x8eyS\x03q~1\xda!<\xa1W\u618965\u026d\xc5\u07a0\x00\x00\u07d4\x9c\x1bw\x1f\t\xaf\x88*\xf0d0\x83\xde*\xa7\x9d\xc0\x97\xc4\x0e\x89\x86p\xe9\xece\x98\xc0\x00\x00\u07d4\x9c(\xa2\xc4\b`\x91\xcb]\xa2&\xa6W\xce2H\xe8\xea{o\x89\x0f-\xc7\xd4\u007f\x15`\x00\x00\u07d4\x9c/\xd5@\x89\xaff]\xf5\x97\x1ds\xb8\x04a`9dsu\x8965\u026d\xc5\u07a0\x00\x00\u07d4\x9c4@\x98\xbaaZ9\x8f\x11\xd0\t\x90[\x17|D\xa7\xb6\x02\x8965\u026d\xc5\u07a0\x00\x00\u07d4\x9c=\x06\x92\xce\xee\xf8\n\xa4\x96\\\xee\xd2b\xff\xc7\xf0i\xf2\u0709\n\u05ce\xbcZ\xc6 \x00\x00\u07d4\x9c@\\\xf6\x97\x95a8\x06^\x11\xc5\xf7U\x9eg$[\u0465\x89\n\u05ce\xbcZ\xc6 \x00\x00\xe0\x94\x9cE *%\xf6\xad\x00\x11\xf1\x15\xa5\xa7\"\x04\xf2\xf2\x19\x88f\x8a\x01\x0f\xcf:b\xb0\x80\x98\x00\x00\xe0\x94\x9cI\xde\xffG\b_\xc0\x97\x04\u02a2\u0728\u0087\xa9\xa17\u068a\x01\xb1\xaeMn.\xf5\x00\x00\x00\u07d4\x9cK\xbc\xd5\xf1dJo\aX$\xdd\xfe\x85\xc5q\u05ab\xf6\x9c\x89a\x94\x04\x9f0\xf7 \x00\x00\u07d4\x9cRj\x14\x06\x83\xed\xf1C\x1c\xfa\xa1(\xa95\xe2\xb6\x14\u060b\x89\x06\x04o7\xe5\x94\\\x00\x00\xe0\x94\x9cT\xe4\xedG\x9a\x85h)\u01bbB\u069f\vi*u\xf7(\x8a\x01\x97\xa8\xf6\xddU\x19\x80\x00\x00\xe0\x94\x9cX\x1a`\xb6\x10(\xd94\x16y)\xb2-p\xb3\x13\xc3O\u040a\n\x96\x81c\xf0\xa5{@\x00\x00\u07d4\x9c\\\xc1\x11\t,\x12!\x16\xf1\xa8_N\xe3\x14\bt\x1a}/\x89\x1a\xb2\xcf|\x9f\x87\xe2\x00\x00\u07d4\x9ck\u0264k\x03\xaeT\x04\xf0C\xdf\xcf!\x88>A\x10\xcc3\x89\n\u05ce\xbcZ\xc6 \x00\x00\xe0\x94\x9cx\x96?\xbc&<\t\xbdr\xe4\xf8\xde\xf7J\x94u\xf7\x05\\\x8a\x02\ub3b1\xa1r\u0738\x00\x00\u07d4\x9cx\xfb\xb4\xdfv\x9c\xe2\xc1V\x92\f\xfe\xdf\xda\x03:\x0e%J\x89j\xcb=\xf2~\x1f\x88\x00\x00\u07d4\x9c{m\xc5\x19\x0f\xe2\x91)c\xfc\xd5yh>\xc79Q\x16\xb0\x89*\x11)\u0413g \x00\x00\u07d4\x9c\x80\xbc\x18\xe9\xf8\u0516\x8b\x18]\xa8\u01df\xa6\xe1\x1f\xfc>#\x89\r\x02\xabHl\xed\xc0\x00\x00\xe0\x94\x9c\x98\xfd\xf1\xfd\u034b\xa8\xf4\u0170L:\xe8X~\xfd\xf0\xf6\xe6\x8a\x01EB\xba\x12\xa37\xc0\x00\x00\xe0\x94\x9c\x99\xa1\u0691\u0552\v\xc1N\f\xb9\x14\xfd\xf6+\x94\u02c3X\x8a\x04<3\xc1\x93ud\x80\x00\x00\u07d4\x9c\x99\xb6&\x06(\x1b\\\xef\xab\xf3aV\xc8\xfeb\x83\x9e\xf5\xf3\x89\xd8\xd7&\xb7\x17z\x80\x00\x00\xe0\x94\x9c\x9a\a\xa8\xe5|1r\xa9\x19\xefdx\x94tI\x0f\r\x9fQ\x8a\x02\x1e\x19\xe0\u027a\xb2@\x00\x00\u07d4\x9c\x9d\xe4G$\xa4\x05M\xa0\xea\xa6\x05\xab\u0300&hw\x8b\xea\x89\n\xd7\xd5\xca?\xa5\xa2\x00\x00\u07d4\x9c\x9f;\x8a\x81\x1b!\xf3\xff?\xe2\x0f\xe9p\x05\x1c\xe6j\x82O\x89>\xc2\u07bc\a\u053e\x00\x00\xe0\x94\x9c\x9f\x89\xa3\x91\x0fj*\xe8\xa9\x10G\xa1z\xb7\x88\xbd\xde\xc1p\x8a\x02\x1e\x19\xe0\u027a\xb2@\x00\x00\u07d4\x9c\xa0B\x9f\x87O\x8d\xce\xe2\xe9\xc0b\xa9\x02\n\x84*Xz\xb9\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\x9c\xa4.\u7838\x98\xf6\xa5\xcc`\xb5\xa5\u05f1\xbf\xa3\xc321\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\x9c\xb2\x8a\xc1\xa2\n\x10o\u007f76\x92\xc5\xceLs\xf172\xa1\x8965\u026d\xc5\u07a0\x00\x00\u07d4\x9c\xcd\u0732\xcf\u00b2[\br\x9a\n\x98\xd9\xe6\xf0 .\xa2\xc1\x89\x05k\xc7^-c\x10\x00\x00\u07d4\x9c\xe2\u007f$^\x02\xd1\xc3\x12\xc1\xd5\x00x\x8c\x9d\xefv\x90E;\x89\n\u05ce\xbcZ\xc6 \x00\x00\u07d4\x9c\xe56;\x13\xe8#\x8a\xa4\xdd\x15\xac\u0432\xe8\xaf\xe0\x872G\x89\n\u05ce\xbcZ\xc6 \x00\x00\xe0\x94\x9c\xf2\x92\x8b\xee\xf0\x9a@\xf9\xbf\xc9S\xbe\x06\xa2Q\x11a\x82\xfb\x8a\x01EB\xba\x12\xa37\xc0\x00\x00\u07d4\x9d\x06\x91\x97\xd1\xdeP\x04Z\x18o^\xc7D\xac@\u8bd1\u0189lk\x93[\x8b\xbd@\x00\x00\u07d4\x9d\x0e}\x92\xfb0XS\u05d8&;\xf1^\x97\xc7+\xf9\xd7\xe0\x8965\u026d\xc5\u07a0\x00\x00\u07d4\x9d\x0f4~\x82k}\u03aa\xd2y\x06\n5\xc0\x06\x1e\xcf3K\x89\xd8\xd7&\xb7\x17z\x80\x00\x00\u07d4\x9d u\x17B,\xc0\xd6\r\xe7\xc27\tzMO\xce \x94\f\x89\x1b\x1a\xe4\xd6\xe2\xefP\x00\x00\xe0\x94\x9d%\n\xe4\xf1\x10\xd7\x1c\xaf\u01f0\xad\xb5.\x8d\x9a\xcbfy\xb8\x8a\x02\x15mn\x99r\x13\xc0\x00\x00\xe0\x94\x9d+\xfc6\x10o\x03\x82P\xc0\x18\x01hW\x85\xb1l\x86\xc6\r\x8aPw\xd7]\xf1\xb6u\x80\x00\x00\xe0\x94\x9d0\xcb#{\xc0\x96\xf1p6\xfc\x80\xdd!\xcah\x99,\xa2\u064a\x06n\xe71\x8f\u070f0\x00\x00\u07d4\x9d2\x96.\xa9\x97\x00\xd92(\xe9\xdb\xda\xd2\xcc7\xbb\x99\xf0~\x89\xb4c+\xed\xd4\xde\xd4\x00\x00\u07d4\x9d4\xda\xc2[\xd1X(\xfa\xef\xaa\xf2\x8fq\aS\xb3\x9e\x89\u0709;\x1cV\xfe\xd0-\xf0\x00\x00\u07d4\x9d6\x91e\xfbp\xb8\x1a:v_\x18\x8f\xd6\f\xbe^{\th\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\x9d@\xe0\x12\xf6\x04%\xa3@\xd8-\x03\xa1\xc7W\xbf\xab\xc7\x06\xfb\x89\t4o:\xdd\u020d\x80\x00\u07d4\x9dAt\xaaj\xf2\x84v\xe2)\xda\xdbF\x18\b\b\xc6u\x05\xc1\x89B\x1a\xfd\xa4.\u0597\x00\x00\u07d4\x9dB\x133\x9a\x01U\x18avL\x87\xa9<\xe8\xf8_\x87\x95\x9a\x89\n\u05ce\xbcZ\xc6 \x00\x00\u07d4\x9dF\f\x1b7\x9d\xdb\x19\xa8\xc8[LgG\x05\r\xdf\x17\xa8u\x89\xb5\x0f\u03ef\xeb\xec\xb0\x00\x00\u07d4\x9dG\xba[L\x85\x05\xad\x8d\xa4)4(\va\xa0\xe1\xe8\xb9q\x89\x05k\xc7^-c\x10\x00\x00\u07d4\x9dM2\x11w%n\xbd\x9a\xfb\xda0A5\xd5\x17\xc3\xdcV\x93\x89!d\xb7\xa0J\u0220\x00\x00\u07d4\x9dO\xf9\x89\xb7\xbe\u066b\x10\x9d\x10\xc8\xc7\xe5_\x02\xd7g4\xad\x8965\u026d\xc5\u07a0\x00\x00\xe0\x94\x9dQ\x15C\xb3\xd9\xdc`\xd4\u007f\t\u051d\x01\xb6\u0118\xd8 x\x8a\x02a\x97\xb9Qo\u00d4\x00\x00\u07d4\x9dn\u03e0:\xf2\xc6\xe1D\xb7\xc4i*\x86\x95\x1e\x90.\x9e\x1f\x89\xa2\xa5\xaa`\xad$?\x00\x00\u07d4\x9dvU\xe9\xf3\xe5\xba]n\x87\xe4\x12\xae\xbe\x9e\xe0\u0512G\ue24e\t1\x1c\x1d\x80\xfa\x00\x00\u07d4\x9dx1\xe84\xc2\v\x1b\xaaiz\xf1\xd8\xe0\xc6!\u016f\xff\x9a\x89\x04\xb0m\xbb\xb4\x0fJ\x00\x00\u07d4\x9dx\xa9u\xb7\xdb^M\x8e(\x84\\\xfb\xe7\xe3\x14\x01\xbe\r\u0649H\xa4<T`/p\x00\x00\u07d4\x9dy\x9e\x94>0k\xa2\u5e5c\x8ahX\u02f5,\f\xf75\x89\x10CV\x1a\x88)0\x00\x00\xe0\x94\x9d\u007f\xdapp\xbf>\xe9\xbb\u0664\x1fU\xca\u0505J\xe6\xc2,\x8a\x02U\u02e3\xc4o\xcf\x12\x00\x00\u07d4\x9d\x81\xae\xa6\x9a\xedj\xd0p\x89\xd6\x14E4\x8c\x17\xf3K\xfc[\x89\x10CV\x1a\x88)0\x00\x00\u07d4\x9d\x91\x1f6\x82\xf3/\xe0y.\x9f\xb6\xff<\xfcG\xf5\x89\xfc\xa5\x89\xd8\xd7&\xb7\x17z\x80\x00\x00\u07d4\x9d\x91;]3\x9c\x95\xd8wEV%c\xfe\xa9\x8b#\xc6\f\u0109\tA0,\u007fM#\x00\x00\u07d4\x9d\x93\xfa\xb6\xe2(E\xf8\xf4Z\aIo\x11\xdeqS\r\xeb\u01c9lO\xd1\xee$nx\x00\x00\u07d4\x9d\x99\xb1\x89\xbb\u0664\x8f\xc2\xe1n\x8f\u0363;\xb9\x9a1{\xbb\x89=\x16\xe1\vm\x8b\xb2\x00\x00\u07d4\x9d\x9cN\xfe\x9fC9\x89\xe2;\xe9@I!S)\xfaU\xb4\u02c9\r\u3c89\x03\u01b5\x80\x00\u07d4\x9d\x9eW\xfd\xe3\x0ePh\xc0>I\x84\x8e\xdc\xe3C\xb7\x02\x83X\x89]\u0212\xaa\x111\xc8\x00\x00\u07d4\x9d\xa30\"@\xaf\x05\x11\xc6\xfd\x18W\xe6\u07779Ow\xabk\x89\xa8\r$g~\xfe\xf0\x00\x00\u07d4\x9d\xa4\xec@pw\xf4\xb9p{-\x9d.\xde^\xa5(+\xf1\u07c9\xd8\xd7&\xb7\x17z\x80\x00\x00\u07d4\x9d\xa6\t\xfa:~l\xf2\xcc\x0ep\u036b\xe7\x8d\xc4\xe3\x82\xe1\x1e\x89A\rXj \xa4\xc0\x00\x00\xe0\x94\x9d\xa6\x1c\xcdb\xbf\x86\x06V\xe02]qW\xe2\xf1`\xd9;\xb5\x8a\x01\x0f\f\xa9V\xf8y\x9e\x00\x00\xe0\x94\x9d\xa6\xe0u\x98\x9ct\x19\tL\xc9\xf6\xd2\u44d3\xbb\x19\x96\x88\x8a\x02Y\xbbq\u056d\xf3\xf0\x00\x00\u07d4\x9d\xa8\xe2,\xa1\x0eg\xfe\xa4NR^GQ\xee\xac6\xa3\x11\x94\x89\x0e\x189\x8ev\x01\x90\x00\x00\u07d4\x9d\xb2\xe1\\\xa6\x81\xf4\xc6`H\xf6\xf9\xb7\x94\x1e\u040b\x1f\xf5\x06\x89\xd8\xd7&\xb7\x17z\x80\x00\x00\u07d4\x9d\xc1\x0f\xa3\x8f\x9f\xb0h\x10\xe1\x1f`\x17>\xc3\xd2\xfdju\x1e\x89j\xcb=\xf2~\x1f\x88\x00\x00\u07d4\x9d\xd2\x19f$\xa1\xdd\xf1J\x9d7^_\a\x15+\xaf\"\xaf\xa2\x89A\xb0^$c\xa5C\x80\x00\u07d4\x9d\xd4k\x1cm?\x05\u279co\x03~\xed\x9aYZ\xf4\xa9\xaa\x89\x1b\x1a\xe4\xd6\xe2\xefP\x00\x00\u07d4\x9d\xdd5^cN\xe9\x92~K\u007fl\x97\xe7\xbf:/\x1ehz\x89\x02\xb5\xe3\xaf\x16\xb1\x88\x00\x00\u07d4\x9d\xe2\n\xe7j\xa0\x82c\xb2\x05\xd5\x14$a\x96\x1e$\b\xd2f\x89\r\xa93\xd8\xd8\xc6p\x00\x00\u07d4\x9d\xe2\v\xc3~\u007fH\xa8\x0f\xfdz\xd8O\xfb\xf1\xa1\xab\xe1s\x8c\x89\n\u05ce\xbcZ\xc6 \x00\x00\u07d4\x9d\xe78m\xde@\x1c\xe4\xc6{q\xb6U?\x8a\xa3N\xa5\xa1}\x89\x03@\xaa\xd2\x1b;p\x00\x00\u07d4\x9d\xeb9\x02z\xf8w\x99+\x89\xf2\xecJ\x1f\x82.\xcd\xf1&\x93\x89lk\x93[\x8b\xbd@\x00\x00\xe0\x94\x9d\xef\xe5j\x0f\xf1\xa1\x94}\xba\t#\xf7\xdd%\x8d\x8f\x12\xfaE\x8a\x05\xb1*\ufbe8\x04\x00\x00\x00\u07d4\x9d\xf0W\xcd\x03\xa4\xe2~\x8e\x03/\x85y\x85\xfd\u007f\x01\xad\xc8\u05c9lk\x93[\x8b\xbd@\x00\x00\xe0\x94\x9d\xf3*P\x1c\vx\x1c\x02\x81\x02/B\xa1)?\xfd{\x89*\x8a\x01\xe7\xe4\x17\x1b\xf4\u04e0\x00\x00\u07d4\x9e\x01vZ\xff\b\xbc\"\x05P\xac\xa5\xea.\x1c\xe8\u5c19#\x8965\u026d\xc5\u07a0\x00\x00\u07d4\x9e \xe5\xfd6\x1e\xab\xcfc\x89\x1f[\x87\xb0\x92h\xb8\xeb7\x93\x89\x05k\xc7^-c\x10\x00\x00\u07d4\x9e#,\b\xc1M\xc1\xa6\xed\v\x8a;(h\x97{\xa5\xc1}\x10\x89\x01\x15\x8eF\t\x13\xd0\x00\x00\u07d4\x9e#\xc5\u4dc2\xb0\n_\xad\U0006eb47\xda\xcf[\x03g\xa1\x89\x01\x15\x8eF\t\x13\xd0\x00\x00\u07d4\x9e59\x90q\xa4\xa1\x01\xe9\x19M\xaa?\t\xf0J\v_\x98p\x89\xd8\xd7&\xb7\x17z\x80\x00\x00\u07d4\x9e>\xb5\t'\x8f\xe0\xdc\xd8\xe0\xbb\xe7\x8a\x19N\x06\xb6\x809C\x892\xf5\x1e\u06ea\xa30\x00\x00\u07d4\x9eBrrQk>g\xd4\xfc\xbf\x82\xf5\x93\x90\xd0L\x8e(\xe5\x89\xd8\xd7&\xb7\x17z\x80\x00\x00\xe0\x94\x9eL\xec5:\xc3\u3043^<\t\x91\xf8\xfa\xa5\xb7\u0428\xe6\x8a\x02\x1e\x18\xb9\xe9\xabE\xe4\x80\x00\u07d4\x9eX\x11\xb4\v\xe1\xe2\xa1\xe1\u048c;\at\xac\xde\n\t`=\x89\xa2\xa1]\tQ\x9b\xe0\x00\x00\u07d4\x9eZ1\x1d\x9fi\x89\x8a|j\x9dc`h\x048\xe6z{/\x89P\xc5\xe7a\xa4D\b\x00\x00\u07d4\x9e| P\xa2'\xbb\xfd`\x93~&\x8c\xea>h\xfe\xa8\xd1\xfe\x89\x05k\xc7^-c\x10\x00\x00\u07d4\x9e\u007fe\xa9\x0e\x85\b\x86{\xcc\xc9\x14%j\x1e\xa5t\xcf\a\xe3\x89C8t\xf62\xcc`\x00\x00\xe0\x94\x9e\x81D\xe0\x8e\x89dx\x11\xfekr\xd4E\u05a5\xf8\n\xd2D\x8a\x02\x1e\x19\xe0\u027a\xb2@\x00\x00\u07d4\x9e\x8fd\xdd\xcd\u9e34Q\xba\xfa\xa25\xa9\xbfQ\x1a%\xac\x91\x89\x90\xf54`\x8ar\x88\x00\x00\u07d4\x9e\x95\x1fm\xc5\xe3R\xaf\xb8\xd0B\x99\xd2G\x8aE\x12Y\xbfV\x89\x03\xe7A\x98\x81\xa7:\x00\x00\u07d4\x9e\x96\r\xcd\x03\u057a\x99\xcb\x11]\x17\xffL\t$\x8a\xd4\u043e\x89\n\u05ce\xbcZ\xc6 \x00\x00\u07d4\x9e\xafj2\x8a@v\x02N\xfakg\xb4\x8b!\xee\xdc\xc0\xf0\xb8\x89\b\x90\xb0\xc2\xe1O\xb8\x00\x00\u07d4\x9e\xb1\xffqy\x8f(\xd6\xe9\x89\xfa\x1e\xa0X\x8e'\xba\x86\xcb}\x89\a\xa1\xfe\x16\x02w\x00\x00\x00\u07d4\x9e\xb2\x81\xc3'\x19\xc4\x0f\xdb>!m\xb0\xf3\u007f\xbcs\xa0&\xb7\x89\x01\x15\x8eF\t\x13\xd0\x00\x00\u07d4\x9e\xb3\xa7\xcb^g&Bz:6\x1c\xfa\x8dad\xdb\u043a\x16\x89+\x95\xbd\xcc9\xb6\x10\x00\x00\u07d4\x9e\xb7\x83N\x17\x1dA\xe0i\xa7yG\xfc\xa8v\"\xf0\xbaNH\x89\x05k\xc7^-c\x10\x00\x00\xe0\x94\x9e\xc0>\x02\u51f7v\x9d\xefS\x84\x13\xe9\u007f~U\xbeq\u060a\x04+\xf0kx\xed;P\x00\x00\u07d4\x9e\u02eb\xb0\xb2'\x82\xb3uD)\xe1uz\xab\xa0K\x81\x18\x9f\x89,\xa7\xbb\x06\x1f^\x99\x80\x00\u07d4\x9e\xce\x14\x00\x80\t6\xc7\xc6H_\xcd\xd3b`\x17\u041a\xfb\xf6\x89\x10\xce\x1d=\x8c\xb3\x18\x00\x00\u07d4\x9e\xd4\xe6?ReB\xd4O\xdd\xd3MY\xcd%8\x8f\xfdk\u0689\u049b4\xa4cH\x94\x00\x00\u07d4\x9e\xd8\x0e\xda\u007fU\x05M\xb9\xfbR\x82E\x16\x88\xf2k\xb3t\xc1\x89\x10CV\x1a\x88)0\x00\x00\u07d4\x9e\u0710\xf4\xbe!\be!J\xb5\xb3^Z\x8d\xd7t\x15'\x9d\x89\xd8\xd7&\xb7\x17z\x80\x00\x00\u07d4\x9e\u07acL\x02k\x93\x05M\u0171\xd6a\fo9`\xf2\xads\x89A\rXj \xa4\xc0\x00\x00\u07d4\x9e\xe9?3\x9eg&\xece\xee\xa4O\x8aK\xfe\x10\xda=2\x82\x89lk\x93[\x8b\xbd@\x00\x00\xe0\x94\x9e\xe9v\f\xc2s\xd4pj\xa0\x83u\xc3\xe4o\xa20\xaf\xf3\u054a\x01\xe5.3l\xde\"\x18\x00\x00\u07d4\x9e\xeb\a\xbd+x\x90\x19^}F\xbd\xf2\a\x1bf\x17QM\u06c9lk\x93[\x8b\xbd@\x00\x00\u07d4\x9e\xefD-)\x1aD}t\xc5\xd2S\u011e\xf3$\xea\xc1\xd8\xf0\x89\xb9f\b\xc8\x10;\xf0\x00\x00\u07d4\x9e\xf1\x89k\x00|2\xa1Q\x14\xfb\x89\xd7=\xbdG\xf9\x12+i\x89\xd8\xd7&\xb7\x17z\x80\x00\x00\u07d4\x9f\x01w\x06\xb80\xfb\x9c0\ufc20\x9fPk\x91WEu4\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\x9f\x10\xf2\xa0F;e\xae0\xb0p\xb3\xdf\x18\xcfF\xf5\x1e\x89\xbd\x89g\x8a\x93 b\xe4\x18\x00\x00\u07d4\x9f\x19\xfa\u0223$7\xd8\n\u0183z\v\xb7\x84\x17)\xf4\x97.\x89#=\xf3)\x9far\x00\x00\u07d4\x9f\x1a\xa8\xfc\xfc\x89\xa1\xa52\x8c\xbdcD\xb7\x1f'\x8a,\xa4\xa0\x89\x1b\x1a\xe4\xd6\xe2\xefP\x00\x00\u07d4\x9f!0,\xa5\tk\xeat\x02\xb9\x1b\x0f\xd5\x06%O\x99\x9a=\x89C\x97E\x1a\x00=\xd8\x00\x00\u07d4\x9f'\x1d(U\x00\xd78F\xb1\x8fs>%\u074bO]J\x8b\x89'#\xc3F\xae\x18\b\x00\x00\u07d4\x9f4\x97\xf5\xef_\xe60\x95\x83l\x00N\xb9\xce\x02\xe9\x01;K\x89\"V\x86\x1b\xf9\xcf\b\x00\x00\xe0\x94\x9f:t\xfd^~\xdc\xc1\x16)\x93\x17\x13\x81\u02f62\xb7\xcf\xf0\x8a\x02\x1e\x19\xe0\u027a\xb2@\x00\x00\u07d4\x9fF\xe7\xc1\xe9\a\x8c\xae\x860Z\xc7\x06\v\x01F}f\x85\xee\x89$=M\x18\"\x9c\xa2\x00\x00\u07d4\x9fIl\xb2\x06\x95c\x14M\b\x11g{\xa0\xe4q:\nAC\x89<\xd2\xe0\xbfc\xa4H\x00\x00\u07d4\x9fJq\x95\xac|\x15\x1c\xa2X\xca\xfd\xa0\u02b0\x83\xe0I\xc6\x02\x89SS\x8c2\x18\\\xee\x00\x00\u07d4\x9fJ\xc9\xc9\xe7\xe2L\xb2DJ\x04T\xfa[\x9a\xd9\xd9-8S\x89-C\xf3\xeb\xfa\xfb,\x00\x00\u07d4\x9f_D\x02kWjJ\xdbA\xe9YaV\x1dA\x03\x9c\xa3\x91\x89\r\x8drkqw\xa8\x00\x00\u07d4\x9f`{?\x12F\x9fDa!\u03bf4u5kq\xb42\x8c\x89\xd8\xd7&\xb7\x17z\x80\x00\x00\u07d4\x9fa\xbe\xb4o^\x85=\n\x85!\xc7Dnh\xe3L}\ts\x89\x1e[\x8f\xa8\xfe*\xc0\x00\x00\u07d4\x9fd\xa8\xe8\xda\xcfJ\xde0\xd1\x0fMY\xb0\xa3\u056b\xfd\xbft\x8966\x9e\xd7t}&\x00\x00\u07d4\x9ff.\x95'A!\xf1wVncm#\x96L\xf1\xfdho\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\x9fj2*mF\x99\x81Bj\xe8D\x86]~\xe0\xbb\x15\u01f3\x89\x02\xb5\xeeW\x92\x9f\u06c0\x00\u07d4\x9fy\x86\x92J\xeb\x02h|\xd6A\x89\x18\x9f\xb1g\xde\xd2\xdd\\\x895e\x9e\xf9?\x0f\xc4\x00\x00\u07d4\x9fz\x03\x92\xf8Ws.0\x04\xa3u\xe6\xb1\x06\x8dI\xd801\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\x9f\x82E\u00eb}\x171d\x86\x1c\u04d9\x1b\x94\xf1\xba@\xa9:\x89\x9b\ny\x1f\x12\x110\x00\x00\u07d4\x9f\x83\xa2\x93\xc3$\xd4\x10l\x18\xfa\xa8\x88\x8fd\u0499\x05L\xa0\x89\n\u05ce\xbcZ\xc6 \x00\x00\u07d4\x9f\x86\xa0f\xed\xb6\x1f\xcbXV\u0793\xb7\\\x8cy\x18d\xb9{\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\x9f\x98\xeb4\xd4iy\xb0\xa6\u078b\x05\xaaS:\x89\xb8%\xdc\xf1\x89\x04\xb0m\xbb\xb4\x0fJ\x00\x00\xe0\x94\x9f\x9f\xe0\xc9_\x10\xfe\xe8z\xf1\xaf r6\xc8\xf3aN\xf0/\x8a\x01EB\xba\x12\xa37\xc0\x00\x00\u07d4\x9f\xae\xa1<s4\x12\xdcKI\x04\x02\xbf\xef'\xa09z\x9b\u00c9\x10\xce\x1d=\x8c\xb3\x18\x00\x00\u07d4\x9f\xbe\x06m\xe5r6\u0703\a%\xd3*\x02\xae\xf9$ll^\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\x9f\xd1\x05*`Pk\u0469\xef\x00:\xfd\x9d\x03<&}\x8e\x99\x8965\u026d\xc5\u07a0\x00\x00\u07d4\x9f\xd6Cs\xf2\xfb\u035c\x0f\xac\xa6\x05G\xca\xd6.&\u0645\x1f\x8965\u026d\xc5\u07a0\x00\x00\u07d4\x9f\xe5\x01\xaaW\xea\u05d2x\x93|\xd60\x8c\\\xfazV)\xfe\x89\x02\xb5\xeeW\x92\x9f\u06c0\x00\u07d4\x9f\xfc_\xe0o3\xf5\xa4\x80\xb7Z\xa9N\xb8Um\x99z\x16\xc0\x89\x01\x15\x8eF\t\x13\xd0\x00\x00\u07d4\x9f\xfc\xf5\xefF\xd93\xa5\x19\xd1\xd1lk\xa3\x18\x9b'Ib$\x8965\u026d\xc5\u07a0\x00\x00\u07d4\x9f\xfe\xdc\xc3k|\xc3\x12\xad*\x9e\xdeC\x1aQO\u0334\x9b\xa3\x89$OW\x9f?\\\xa4\x00\x00\u07d4\xa0\x06&\x84Fd>\xc5\xe8\x1ez\xcb?\x17\xf1\xc3Q\xee.\u0649\xd8\xd7&\xb7\x17z\x80\x00\x00\u07d4\xa0\b\x01\x98c\xc1\xa7|\x14\x99\xeb9\xbb\u05ff-\u05e3\x1c\xb9\x89\amA\xc6$\x94\x84\x00\x00\u07d4\xa0\t\xbf\ao\x1b\xa3\xfaW\u04a7!r\x18\xbe\xd5VZzz\x8965\u026d\xc5\u07a0\x00\x00\xe0\x94\xa0\x1e\x94v\u07c4C\x18%\xc86\xe8\x80:\x97\xe2/\xa5\xa0\u034a\x01EB\xba\x12\xa37\xc0\x00\x00\u0794\xa0\x1f\x12\xd7\x0fD\xaa{\x11;(\\\"\xdc\xdbE\x874T\xa7\x88\xfc\x93c\x92\x80\x1c\x00\x00\u07d4\xa0\x1f\u0450j\x90\x85\x06\xde\xda\xe1\xe2\b\x12\x88r\xb5n\u7489\xa2\xa1]\tQ\x9b\xe0\x00\x00\u07d4\xa0\"\x82@\xf9\x9e\x1d\xe9\xcb2\xd8,\x0f/\xa9\xa3\xd4K\v\xf3\x89V\xbcu\xe2\xd61\x00\x00\x00\xe0\x94\xa0+\xdedahn\x19\xace\f\x97\r\x06r\xe7m\xcbO\u008a\x01\xe0\x92\x96\xc37\x8d\xe4\x00\x00\u07d4\xa0,\x1e4\x06O\x04u\xf7\xfa\x83\x1c\xcb%\x01L:\xa3\x1c\xa2\x89\x03@\xaa\xd2\x1b;p\x00\x00\u07d4\xa0-\u01aa2\x8b\x88\r\u97acTh#\xfc\xcfw@G\xfb\x89j\xcb=\xf2~\x1f\x88\x00\x00\u07d4\xa0.?\x8fYY\xa7\xaa\xb7A\x86\x12\x12\x9bp\x1c\xa1\xb8\x00\x10\x89\x01\x15\x8eF\t\x13\xd0\x00\x00\u07d4\xa04\u007f\n\x98wc\x90\x16\\\x16m2\x96;\xf7M\xcd\n/\x8965\u026d\xc5\u07a0\x00\x00\u07d4\xa05\xa3e$x\xf8-\xbdm\x11_\xaa\x8c\xa9F\xec\x9eh\x1d\x89\x05\xf4\xe4-\u052f\xec\x00\x00\u07d4\xa0:=\xc7\xc53\xd1tB\x95\xbe\x95]a\xaf?R\xb5\x1a\xf5\x89\x02+\x1c\x8c\x12'\xa0\x00\x00\u07d4\xa0E\x9e\xf3i:\xac\xd1d|\xd5\u0612\x989 L\xefS\xbe\x8965\u026d\xc5\u07a0\x00\x00\xe0\x94\xa0O*\xe0*\xdd\x14\xc1/\xafe\xcb%\x90\"\u0403\n\x8e&\x8a\x15-\x02\xc7\xe1J\xf6\x80\x00\x00\u07d4\xa0l\xd1\xf3\x969l\ndFFQ\xd7\xc2\x05\xef\xaf8|\xa3\x89lj\xccg\u05f1\xd4\x00\x00\u07d4\xa0ri\x1c\x8d\xd7\xcdB7\xffr\xa7\\\x1a\x95\x06\xd0\xce[\x9e\x89\x14\x0e\xc8\x0f\xa7\xee\x88\x00\x00\u07d4\xa0r\u03beb\xa9\xe9\xf6\x1c\xc3\xfb\xf8\x8a\x9e\xfb\xfe>\x9a\x8dp\x89\x15\xaf\x1dx\xb5\x8c@\x00\x00\u07d4\xa0v\x82\x00\v\x1b\xcf0\x02\xf8\\\x80\xc0\xfa)I\xbd\x1e\x82\xfd\x89\xd8\xd7&\xb7\x17z\x80\x00\x00\u07d4\xa0z\xa1mt\xae\u8a63(\x8dR\xdb\x15Q\u0553\x882\x97\x89 \x86\xac5\x10R`\x00\x00\u07d4\xa0\x8d![[j\xacHa\xa2\x81\xac~@\vx\xfe\xf0L\xbf\x89\x01\x15\x8eF\t\x13\xd0\x00\x00\u07d4\xa0\x95\x19p\xdf\u0403/\xb8;\xda\x12\xc25E\xe7\x90Aul\x89 \x86\xac5\x10R`\x00\x00\u07d4\xa0\x9fM^\xaae\xa2\xf4\xcbu\nI\x924\x01\xda\u5410\xaf\x89\a\x96\xe3\xea?\x8a\xb0\x00\x00\xe0\x94\xa0\xa0\xe6R\x04T\x1f\u029b/\xb2\x82\u0355\x13\x8f\xae\x16\xf8\t\x8a\x02\x1e\x19\xe0\u027a\xb2@\x00\x00\u07d4\xa0\xaa_\x02\x01\xf0M;\xbe\xb8\x98\x13/|\x11g\x94f\xd9\x01\x89\x01\xfb\xedR\x15\xbbL\x00\x00\u07d4\xa0\xaa\xdb\xd9P\x97\"p_m#X\xa5\u01df7\x97\x0f\x00\xf6\x89\n\u05ce\xbcZ\xc6 \x00\x00\u07d4\xa0\xb7q\x95\x1c\xe1\xde\xee6:\xe2\xb7q\xb7>\a\u0135\xe8\x00\x89K\xe4\xe7&{j\xe0\x00\x00\u07d4\xa0\xde\\`\x1eif5\u0198\xb7\xae\x9c\xa4S\x9f\u01f9A\xec\x89\x12\xc3\xcb\xd7\x04\xc9w\x00\x00\u07d4\xa0\xe8\xbaf\x1bH\x15L\xf8C\xd4\u00a5\xc0\xf7\x92\xd5(\xee)\x89\x15\xaf\x1dx\xb5\x8c@\x00\x00\u07d4\xa0\xfc~S\xc5\xeb\xd2z*\xbd\xacE&\x1f\x84\xab;Q\xae\xfb\x89\xa3\x13\xda\xec\x9b\xc0\xd9\x00\x00\xe0\x94\xa0\xff[L\xf0\x16\x02~\x83#I}D(\xd3\xe5\xa8;\x87\x95\x8a\x01e\x98\xd3\xc8>\xc0B\x00\x00\u07d4\xa1\x06F[\xbd\x19\u1dbc\xe5\r\x1b\x11W\xdcY\tZ60\x89lk\x93[\x8b\xbd@\x00\x00\xe0\x94\xa1\x06\xe6\x92>\xddS\u028e\xd6P\x96\x8a\x91\b\xd6\xcc\xfd\x96p\x8a\x02\x02\xfe\x15\x05\xaf\uc240\x00\u07d4\xa1\t\u12f0\xa3\x9c\x9e\xf8/\xa1\x95\x97\xfc^\xd8\xe9\xebmX\x89X\xe7\x92n\xe8X\xa0\x00\x00\u07d4\xa1\x1a\x03\u013b&\xd2\x1e\xffg}]U\\\x80\xb2TS\xeez\x89\x03\xcb'Y\xbcA\x0f\x80\x00\u07d4\xa1\x1e\xff\xabl\xf0\xf5\x97,\xff\xe4\xd5e\x96\xe9\x89h\x14J\x8f\x89Z\x87\xe7\xd7\xf5\xf6X\x00\x00\u07d4\xa1 M\xad_V\a(\xa3\\\r\x8f\u01d4\x81\x05{\xf7s\x86\x8965\u026d\xc5\u07a0\x00\x00\xe0\x94\xa1&#\xe6)\u07d3\tg\x04\xb1`\x84\xbe,\u061dV-\xa4\x8a\x01\xcc\xc92E\x11\xe4P\x00\x00\xe0\x94\xa1*l-\x98]\xaf\x0eO_ z\xe8Q\xaa\xf7)\xb32\u034a\x15-\x02\xc7\xe1J\xf6\x80\x00\x00\xe0\x94\xa13m\xfb\x96\xb6\xbc\xbeK>\xdf2\x05\xbeW#\xc9\x0f\xadR\x8a\x01\x0f\f\xf0d\xddY \x00\x00\u07d4\xa1;\x9d\x82\xa9\x9b<\x9b\xbaZ\xe7.\xf2\x19\x9e\xdc};\xb3l\x89lj\xccg\u05f1\xd4\x00\x00\xe0\x94\xa1<\xfe\x82mm\x18A\u072eD;\xe8\u00c7Q\x816\xb5\xe8\x8a\x1d\xa5jK\b5\xbf\x80\x00\x00\xe0\x94\xa1C.\xd2\u01b7wz\x88\xe8\xd4m8\x8epG\u007f \x8c\xa5\x8a\x01\xb1\xa7\xe4\x13\xa1\x96\xc5\x00\x00\u07d4\xa1D\xf6\xb6\x0fr\xd6J!\xe30\xda\xdbb\u0619\n\xde+\t\x8965\u026d\xc5\u07a0\x00\x00\u07d4\xa1P%\xf5\x95\xac\xdb\xf3\x11\x0fw\u017f$G~eH\xf9\xe8\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\xa1X\x14\x8a.\x0f>\x92\xdc,\xe3\x8f\xeb\xc2\x01\a\xe3%<\x96\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\xa1a`\x85\x1d+\x9c4\x9b\x92\xe4o\x82\x9a\xbf\xb2\x10\x945\x95\x89a\t=|,m8\x00\x00\u07d4\xa1f\xf9\x11\xc6D\xac2\x13\u049e\x0e\x1a\xe0\x10\xf7\x94\u056d&\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\xa1m\x9e=c\x98aY\xa8\x00\xb4h7\xf4^\x8b\xb9\x80\xee\v\x89n\x11u\xdaz\xd1 \x00\x00\u07d4\xa1pp\xc2\xe9\u0169@\xa4\xec\x0eIT\xc4\xd7\xd6C\xbe\x8fI\x89lk\x17\x03;6\x1c\x80\x00\u07d4\xa1|\x9eC#\x06\x95\x18\x18\x9dR\a\xa0r\x8d\u02d20j?\x8965\u026d\xc5\u07a0\x00\x00\u07d4\xa1\x83`\xe9\x85\xf2\x06.\x8f\x8e\xfe\x02\xad,\xbc\x91\xad\x9aZ\xad\x89\xa2\xa1]\tQ\x9b\xe0\x00\x00\u07d4\xa1\x91\x14\x05\xcfn\x99\x9e\xd0\x11\xf0\xdd\xcd*O\xf7\u008f%&\x89\x02+\x1c\x8c\x12'\xa0\x00\x00\u07d4\xa1\x92i\x80\a\xcc\x11\xaa`=\"\x1d_\xee\xa0v\xbc\xf7\xc3\r\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\xa1\x92\xf0j\xb0R\xd5\xfd\u007f\x94\xee\xa81\x8e\x82x\x15\xfegz\x89\a\x1f\x8a\x93\xd0\x1eT\x00\x00\u07d4\xa1\x99\x81D\x96\x8a\\p\xa6AUT\xce\xfe\u0082F\x90\u0125\x89\x01\x15\x8eF\t\x13\xd0\x00\x00\u07d4\xa1\xa1\xf0\xfam \xb5\nyO\x02\xefR\b\\\x9d\x03j\xa6\u028965\u026d\xc5\u07a0\x00\x00\u07d4\xa1\xae\x8dE@\xd4\xdbo\xdd\xe7\x14oA[C\x1e\xb5\\y\x83\x89\n\xad\xec\x98?\xcf\xf4\x00\x00\u07d4\xa1\xb4|M\x0e\xd6\x01\x88B\xe6\xcf\xc8c\n\u00e3\x14.^k\x89\x01\x15\x8eF\t\x13\xd0\x00\x00\xe0\x94\xa1\xc4\xf4Z\x82\xe1\xc4x\xd8E\b.\xb1\x88u\xc4\xeae9\xab\x8a*Z\x05\x8f\u0095\xed\x00\x00\x00\u07d4\xa1\xdc\xd0\xe5\xb0Z\x97|\x96#\xe5\xae/Y\xb9\xad\xa2\xf3>1\x89\x05k\xc7^-c\x10\x00\x00\u07d4\xa1\xe48\n;\x1ft\x96s\xe2p\"\x99\x93\xeeU\xf3Vc\xb4\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\xa1\xf1\x93\xa0Y/\x1f\xeb\x9f\xdf\xc9\n\xa8\x13xN\xb8\x04q\u0249K\xe4\xe7&{j\xe0\x00\x00\u07d4\xa1\xf2\x85@P\xf8re\x8e\xd8.R\xb0\xad{\xbc\x1c\xb9!\xf6\x89m\x03\x17\xe2\xb3&\xf7\x00\x00\u07d4\xa1\xf5\xb8@\x14\rZ\x9a\xce\xf4\x02\xac<\u00c8jh\xca\xd2H\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\xa1\xf7e\xc4O\xe4_y\x06w\x94HD\xbeO-B\x16_\xbd\x89\xc7\xe9\xcf\xdev\x8e\xc7\x00\x00\u07d4\xa1\xf7\xdd\xe1\xd78\xd8\xcdg\x9e\xa1\xee\x96[\xee\"K\xe7\xd0M\x89=\x18DP\xe5\xe9<\x00\x00\u07d4\xa1\xf8\u063c\xf9\x0ew\u007f\x19\xb3\xa6Iu\x9a\xd9P'\xab\xdf\u00c9\n\u05ce\xbcZ\xc6 \x00\x00\u07d4\xa2\x02TrB\x80onp\xe7@X\xd6\xe5)-\xef\xc8\xc8\u0509l\x87T\xc8\xf3\f\b\x00\x00\u07d4\xa2\r\a\x1b\x1b\x000cI}y\x90\xe1$\x9d\xab\xf3l5\xf7\x8965\u026d\xc5\u07a0\x00\x00\u07d4\xa2\r\x8f\xf6\f\xaa\xe3\x1d\x02\xe0\xb6e\xfaC]v\xf7|\x94B\x89\x1a\x8a\x90\x9d\xfc\xef@\x00\x00\u07d4\xa2\x11\xda\x03\xcc\x0e1\xec\xceS\t\x99\x87\x18QU(\xa0\x90\u07c9\n\u05ce\xbcZ\xc6 \x00\x00\u07d4\xa2\x14B\xab\x054\n\xdeh\xc9\x15\xf3\xc39\x9b\x99U\xf3\xf7\xeb\x89*\x03I\x19\u07ff\xbc\x00\x00\u07d4\xa2\"\"Y\u075c>=\xed\x12p\x84\xf8\b\xe9*\x18\x870,\x89\b\xc83\x9d\xaf\xedH\x00\x00\u07d4\xa2*\xde\r\xdb\\n\xf8\xd0\u034d\xe9M\x82\xb1\x10\x82\xcb.\x91\x897KW\xf3\xce\xf2p\x00\x00\u07d4\xa2L:\xb6!\x81\xe9\xa1[x\xc4b\x1eL|X\x81'\xbe&\x89\b\xcd\xe4:\x83\xd31\x00\x00\u07d4\xa2W\xadYK\u0603(\xa7\xd9\x0f\xc0\xa9\a\u07d5\xee\xca\xe3\x16\x89\x1c7\x86\xff8F\x93\x00\x00\u07d4\xa2[\bd7\xfd!\x92\u0420\xf6On\xd0D\xf3\x8e\xf3\xda2\x89\x12)\x0f\x15\x18\v\xdc\x00\x00\u07d4\xa2v\xb0X\u02d8\u060b\xee\xdbg\xe5CPl\x9a\r\x94p\u0609\x90\xaa\xfcv\xe0/\xbe\x00\x00\u07d4\xa2\x82\xe9i\xca\xc9\xf7\xa0\xe1\xc0\u0350\xf5\xd0\xc48\xacW\r\xa3\x89\"\a\xeb\x89\xfc'8\x00\x00\xe0\x94\xa2\x91\xe9\u01d9\rU-\u046e\x16\u03bc?\xca4,\xba\xf1\u044a\x04<3\xc1\x93ud\x80\x00\x00\u07d4\xa2\x93\x19\xe8\x10i\xe5\xd6\r\xf0\x0f=\xe5\xad\xee5\x05\xec\xd5\xfb\x89lk\x93[\x8b\xbd@\x00\x00\xe0\x94\xa2\x96\x8f\xc1\xc6K\xac\vz\xe0\u058b\xa9I\x87Mm\xb2S\xf4\x8a\x04<3\xc1\x93ud\x80\x00\x00\xe0\x94\xa2\x9d[\xdat\xe0\x03GHr\xbdX\x94\xb8\x853\xffd\u00b5\x8a\x02\x1e\x19\xe0\u027a\xb2@\x00\x00\u07d4\xa2\x9df\x1acv\xf6m\vt\xe2\xfe\x9d\x8f&\xc0$~\xc8L\x89\xdf3\x04\a\x9c\x13\xd2\x00\x00\u07d4\xa2\xa45\xdeD\xa0\x1b\xd0\ucc9eD\xe4vD\xe4j\f\xdf\xfb\x89\x1b\x1dDZz\xff\xe7\x80\x00\u07d4\xa2\xac\xe4\u0253\xbb\x1eS\x83\xf8\xact\xe1y\x06n\x81O\x05\x91\x89\x05k\xc7^-c\x10\x00\x00\u07d4\xa2\xb7\x01\xf9\xf5\xcd\u041eK\xa6+\xae\xba\u3a02W\x10X\x85\x8965\u026d\xc5\u07a0\x00\x00\u07d4\xa2\u0145O\xf1Y\x9f\x98\x89,W%\xd2b\xbe\x1d\xa9\x8a\xad\xac\x89\x11\t\xff30\x10\xe7\x80\x00\u07d4\xa2\xc7\xea\xff\xdc,\x9d\x93sE l\x90\x9aR\u07f1LG\x8f\x89\a\xc0\x86\x0eZ\x80\xdc\x00\x00\u07d4\xa2\u04aabk\t\xd6\xd4\xe4\xb1?\u007f\xfcZ\x88\xbdz\xd3gB\x89\xfb\x80xPuS\x83\x00\x00\u07d4\xa2\u04cd\xe1\xc79\x06\xf6\xa7\xcan\xfe\xb9|\xf6\xf6\x9c\xc4!\xbe\x8965\u026d\xc5\u07a0\x00\x00\xe0\x94\xa2\xdce\xee%kY\xa5\xbdy)wO\x90K5\x8d\U000ed84a\x04\x83\xbc\xe2\x8b\xeb\t\xf8\x00\x00\u07d4\xa2\xe0h:\x80]\xe6\xa0^\xdb/\xfb\xb5\xe9o\x05p\xb67\u00c9\x01\x15\x8eF\t\x13\xd0\x00\x00\u07d4\xa2\u1e2a\x90\x0e\x9c\x13\x9b?\xa1\"5OaV\xd9*\x18\xb1\x89\x1b\x1a\xe4\xd6\xe2\xefP\x00\x00\u07d4\xa2\u2d54\x1e\f\x01\x94K\xfe\x1d_\xb4\xe8\xa3K\x92,\u03f1\x89\n\u05ce\xbcZ\xc6 \x00\x00\u07d4\xa2\xe4`\xa9\x89\xcb\x15V_\x9e\u0327\xd1!\xa1\x8eN\xb4\x05\xb6\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\xa2\xec\xce,I\xf7*\t\x95\xa0\xbd\xa5z\xac\xf1\xe9\xf0\x01\xe2*\x89\xd8\xd7&\xb7\x17z\x80\x00\x00\xe0\x94\xa2\xf4r\xfeO\"\xb7}\xb4\x89!\x9e\xa4\x02=\x11X*\x93)\x8a\bxg\x83&\xea\xc9\x00\x00\x00\u07d4\xa2\xf7\x98\xe0w\xb0}\x86\x12N\x14\a\xdf2\x89\r\xbbKcy\x89\n\u05ce\xbcZ\xc6 \x00\x00\u07d4\xa2\xf8k\xc0a\x88N\x9e\xef\x05d\x0e\xddQ\xa2\xf7\xc0Yli\x89llD\xfeG\xec\x05\x00\x00\u07d4\xa2\xfa\x17\xc0\xfbPl\xe4\x94\x00\x8b\x95W\x84\x1c?d\x1b\x8c\xae\x89\x01\x15\x8eF\t\x13\xd0\x00\x00\u07d4\xa3\x04X\x8f\r\x85\f\xd8\u04cfv\xe9\xe8<\x1b\xf6>3>\u0789\x02(V\x01!l\x8c\x00\x00\u07d4\xa3\x05\x8cQszN\x96\xc5_.\xf6\xbd{\xb3X\x16~\u00a7\x89 \xdb:\xe4H\x1a\u0500\x00\u07d4\xa3\t\xdfT\u02bc\xe7\f\x95\xec03\x14\x9c\xd6g\x8ao\xd4\u03c9\f\x1f\x12\xc7Q\x01X\x00\x00\u07d4\xa3\nER\x0eR\x06\xd9\x00@p\xe6\xaf>{\xb2\xe8\xddS\x13\x89\x15\xaf\x1dx\xb5\x8c@\x00\x00\u07d4\xa3\x0e\n\xcbSL\x9b0\x84\xe8P\x1d\xa0\x90\xb4\xeb\x16\xa2\xc0\u0349lk\x93[\x8b\xbd@\x00\x00\u07d4\xa3 0\x95\xed\xb7\x02\x8ehq\xce\n\x84\xf5HE\x9f\x830\n\x89\xd8\xd7&\xb7\x17z\x80\x00\x00\u07d4\xa3!\t\x1d0\x18\x06By\xdb9\x9d+*\x88\xa6\xf4@\xae$\x89\xadx\xeb\u016cb\x00\x00\x00\u07d4\xa3#-\x06\x8dP\x06I\x03\xc9\xeb\xc5c\xb5\x15\xac\u0237\xb0\x97\x89l\x87T\xc8\xf3\f\b\x00\x00\xe0\x94\xa3$\x1d\x89\n\x92\xba\xf5)\b\xdcJ\xa0Irk\xe4&\xeb\u04ca\x04<-\xa6a\xca/T\x00\x00\u07d4\xa3)F&\xec)\x84\xc4;C\xdaM]\x8eFi\xb1\x1dKY\x896\xa4\xcfcc\x19\xc0\x00\x00\u07d4\xa3,\xf7\xdd\xe2\f=\xd5g\x9f\xf5\xe3%\x84\\p\u0156&b\x89\x01\x15\x8eF\t\x13\xd0\x00\x00\u07d4\xa39\xa3\xd8\xca(\x0e'\xd2A[&\xd1\xfcy2(\xb6`C\x896\U00086577\x8f\xf0\x00\x00\u07d4\xa3<\xb4P\xf9[\xb4n%\xaf\xb5\x0f\xe0_\xee\xe6\xfb\x8c\xc8\xea\x89*\x11)\u0413g \x00\x00\u07d4\xa3?p\xdaru\xef\x05q\x04\u07e7\xdbd\xf4r\xe9\xf5\xd5S\x89\x04YF\xb0\xf9\xe9\xd6\x00\x00\u07d4\xa3@v\xf8K\xd9\x17\xf2\x0f\x83B\u024b\xa7\x9eo\xb0\x8e\xcd1\x89\u3bb5sr@\xa0\x00\x00\u07d4\xa3C\x0e\x1fd\u007f2\x1e\xd3G9V##\xc7\xd6#A\vV\x8964\xfb\x9f\x14\x89\xa7\x00\x00\u07d4\xa3O\x9dV\x8b\xf7\xaf\xd9L*[\x8a_\xf5\\f\xc4\by\x99\x89\x84}P;\"\x0e\xb0\x00\x00\u07d4\xa3V\x06\xd5\x12 \xee\u007f!F\xd4\x11X.\xe4\xeeJEYn\x89\u062a\xbe\b\v\xc9@\x00\x00\u07d4\xa3VU\x1b\xb7}OE\xa6\xd7\xe0\x9f\n\b\x9ey\u0322I\u02c9\x12nr\xa6\x9aP\xd0\x00\x00\u07d4\xa3\\\x19\x13,\xac\x195Wj\xbf\xedl\x04\x95\xfb\a\x88\x1b\xa0\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\xa3e\x91\x8b\xfe?&'\xb9\xf3\xa8gu\xd8un\x0f\u0629K\x89\x15\xaf\x1dx\xb5\x8c@\x00\x00\u07d4\xa3n\r\x94\xb9Sd\xa8&q\xb6\b\xcb-72Ea)\t\x89\b!\xd2!\xb5)\x1f\x80\x00\u07d4\xa3u\xb4\xbc$\xa2N\x1fyu\x93\xcc0+/3\x10c\xfa\\\x89\n\u05ce\xbcZ\xc6 \x00\x00\u07d4\xa3v\"\xac\x9b\xbd\xc4\xd8+u\x01]t[\x9f\x8d\xe6Z(\uc25d\xc0\\\xce(\u00b8\x00\x00\xe0\x94\xa3y\xa5\a\fP=/\xac\x89\xb8\xb3\xaf\xa0\x80\xfdE\xedK\xec\x8a\x04+\xf0kx\xed;P\x00\x00\u07d4\xa3\x80-\x8ae\x9e\x89\xa2\xc4~\x90T0\xb2\xa8'\x97\x89P\xa7\x8965\u026d\xc5\u07a0\x00\x00\u07d4\xa3\x83\x06\xcbp\xba\xa8\u4446\xbdh\xaap\xa8=$/)\a\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\xa3\x84vi\x1d4\x94.\xeak/v\x88\x92#\x04}\xb4az\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\xa3\x87\xceN\x96\x1axG\xf5`\a\\d\xe1YkVA\xd2\x1c\x89$=M\x18\"\x9c\xa2\x00\x00\u07d4\xa3\x87\xec\xde\x0e\xe4\xc8\a\x94\x99\xfd\x8e\x03G;\u060a\xd7R*\x89j\xcb=\xf2~\x1f\x88\x00\x00\u07d4\xa3\x88:$\xf7\xf1f _\x1aj\x99I\al&\xa7nqx\x89b\xa9\x92\xe5:\n\xf0\x00\x00\xe0\x94\xa3\x8b[\xd8\x1a\x9d\xb9\u04b2\x1d^\xc7\xc6\x05R\xcd\x02\xedV\x1b\x8a\x01EB\xba\x12\xa37\xc0\x00\x00\u07d4\xa3\x90\xca\x12+\x85\x01\xee>^\a\xa8\xcaKA\x9f~M\xae\x15\x89\x05k\xc7^-c\x10\x00\x00\xe0\x94\xa3\x93*1\xd6\xffu\xfb;\x12q\xac\xe7\u02a7\xd5\xe1\xff\x10Q\x8a\x04<3\xc1\x93ud\x80\x00\x00\xe0\x94\xa3\x94\xadO\xd9\xe6S\x0eo\\S\xfa\xec\xbe\u0781\xcb\x17-\xa1\x8a\x01/\x93\x9c\x99\xed\xab\x80\x00\x00\u07d4\xa3\x97\x9a\x92v\n\x13Z\xdfi\xd7/u\xe1gu_\x1c\xb8\u00c9\x05k\xc7^-c\x10\x00\x00\xe0\x94\xa3\x9b\xfe\xe4\xae\u027du\xbd\"\u01b6r\x89\x8c\xa9\xa1\xe9]2\x8a\x02\x1e\x19\xe0\u027a\xb2@\x00\x00\u07d4\xa3\xa2b\xaf\u0493h\x19#\b\x92\xfd\xe8O-ZYJ\xb2\x83\x89e\xea=\xb7UF`\x00\x00\u07d4\xa3\xa2\xe3\x19\xe7\u04e1D\x8bZ\xa2F\x89S\x16\f-\xbc\xbaq\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\xa3\xa5{\a\x16\x13(\x04\xd6\n\xac(\x11\x97\xff+=#{\x01\x89K\xe4\xe7&{j\xe0\x00\x00\u07d4\xa3\xa9>\xf9\xdb\xea&6&=\x06\xd8I/jA\u0790|\"\x89\x03@\xaa\xd2\x1b;p\x00\x00\xe0\x94\xa3\xae\x18y\x00}\x80\x1c\xb5\xf3RqjM\u063a'!\xde=\x8a*Z\x05\x8f\u0095\xed\x00\x00\x00\u07d4\xa3\xba\r:6\x17\xb1\xe3\x1bNB,\xe2i\xe8s\x82\x8d]i\x89.\x14\x1e\xa0\x81\xca\b\x00\x00\u07d4\xa3\xbc\x97\x9bp\x80\t/\xa1\xf9/n\x0f\xb3G\u2359PE\x89\x97\xc9\xceL\xf6\xd5\xc0\x00\x00\u07d4\xa3\xbf\xf1\u07e9\x97\x16h6\f\r\x82\x82\x842\xe2{\xf5Ng\x89\n\u05ce\xbcZ\xc6 \x00\x00\xe0\x94\xa3\xc1J\xce(\xb1\x92\u02f0b\x14_\u02fdXi\xc6rq\xf6\x8a\x01\xb1\xaeMn.\xf5\x00\x00\x00\u07d4\xa3\xc3:\xfc\x8c\xb4pN#\x15=\xe2\x04\x9d5\xaeq3$r\x89+X\xad\u06c9\xa2X\x00\x00\u07d4\xa3\u0430<\xff\xbb&\x9fyj\u009d\x80\xbf\xb0}\xc7\u01ad\x06\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\xa3\u0543\xa7\xb6[#\xf6\vy\x05\xf3\xe4\xaab\xaa\xc8\u007fB'\x898\xbe\xfa\x12mZ\x9f\x80\x00\u07d4\xa3\xdb6J3-\x88K\xa9;&\x17\xaeM\x85\xa1H\x9b\xeaG\x89\\(=A\x03\x94\x10\x00\x00\u07d4\xa3\xe0Q\xfbtJ\xa3A\f;\x88\xf8\x99\xf5\xd5\u007f\x16\x8d\xf1-\x89\xa00\xdc\xeb\xbd/L\x00\x00\u07d4\xa3\xe3\xa6\xeaP\x95s\xe2\x1b\xd0#\x9e\xce\x05#\xa7\xb7\u061b/\x89j\xcb=\xf2~\x1f\x88\x00\x00\u07d4\xa3\xf4\xad\x14\xe0\xbbD\xe2\xce,\x145\x9cu\xb8\xe72\xd3pT\x89\n\u05ce\xbcZ\xc6 \x00\x00\u07d4\xa3\xfa\xccP\x19\\\vI3\xc8X\x97\xfe\xcc[\xbd\x99\\4\xb8\x89\x01\x15\x8eF\t\x13\xd0\x00\x00\u07d4\xa4\x03Z\xb1\xe5\x18\b!\xf0\xf3\x80\xf1\x13\x1bs\x87\xc8\u0641\u0349\x01\x15\x8eF\t\x13\xd0\x00\x00\u07d4\xa4\n\xa2\xbb\xce\fr\xb4\xd0\xdf\xff\xccBq[+T\xb0\x1b\xfa\x8965\u026d\xc5\u07a0\x00\x00\u07d4\xa4\x19\xa9\x84\x14#c&uuV`\x894\x0e\xea\x0e\xa2\b\x19\x89lj\xccg\u05f1\xd4\x00\x00\xe0\x94\xa4!\u06f8\x9b:\aA\x90\x84\xad\x10\xc3\xc1]\xfe\x9b2\xd0\u008a\x04<3\xc1\x93ud\x80\x00\x00\u07d4\xa4\"\xe4\xbf\v\xf7AG\u0309[\xed\x8f\x16\xd3\xce\xf3BaT\x89\x12\xef?b\xee\x116\x80\x00\u07d4\xa4%\x9f\x83E\xf7\u3a37+\x0f\xec,\xf7^2\x1f\xdaM\u0089g\x8a\x93 b\xe4\x18\x00\x00\u07d4\xa4)\b\xe7\xfeS\x98\n\x9a\xbf@D\xe9W\xa5Kp\u973e\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\xa4)\xfa\x88s\x1f\xdd5\x0e\x8e\xcdn\xa5B\x96\xb6HO\u6549j\xc5\xc6-\x94\x86\a\x00\x00\xe0\x94\xa40\x99]\xdb\x18[\x98e\xdb\xe6%9\xad\x90\xd2.Ks\u008a\x02\x1e\x19\xe0\u027a\xb2@\x00\x00\u07d4\xa46\xc7TS\xcc\xcaJ\x1f\x1bb\xe5\u0123\r\x86\xdd\xe4\xbeh\x89lk\x93[\x8b\xbd@\x00\x00\xe0\x94\xa47\xfen\xc1\x03\u028d\x15\x8fc\xb34\"N\u032c[>\xa3\x8a\x01\xb1\xaeMn.\xf5\x00\x00\x00\u07d4\xa4;m\xa6\xcbz\xacW\x1d\xff'\xf0\x9d9\xf8F\xf57i\xb1\x89\x14\x99\x8f2\xacxp\x00\x00\u07d4\xa4;\x81\xf9\x93V\xc0\xaf\x14\x1a\x03\x01\rw\xbd\x04,q\xc1\xee\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\xa4>\x19G\xa9$+5Ua\xc3\n\x82\x9d\xfe\uc881Z\xf8\x89\xd2=\x99\x96\x9f\u0591\x80\x00\u07d4\xa4H\x9aP\xea\xd5\xd5DZ{\xeeM-U6\u00a7lA\xf8\x89\n\u05ce\xbcZ\xc6 \x00\x00\u07d4\xa4O\xe8\x00\xd9o\xca\xd7;qp\xd0\xf6\x10\u02cc\x06\x82\xd6\u0389\xd8\xd7&\xb7\x17z\x80\x00\x00\u07d4\xa4T2\xa6\xf2\xac\x9dVW{\x93\x8a7\xfa\xba\xc8\xcc|F\x1c\x8965\u026d\xc5\u07a0\x00\x00\u07d4\xa4f\xd7p\u0618\xd8\xc9\xd4\x05\xe4\xa0\xe5Q\xef\xaf\xcd\xe5<\xf9\x89\x1a\xb2\xcf|\x9f\x87\xe2\x00\x00\xe0\x94\xa4g\a1\x17X\x93\xbb\xcf\xf4\xfa\x85\u0397\xd9O\xc5\x1cK\xa8\x8a\x01\xb1\xaeMn.\xf5\x00\x00\x00\u07d4\xa4kC\x87\xfbM\xcc\xe0\x11\xe7nMsT}D\x81\xe0\x9b\xe5\x89Hz\x9a0E9D\x00\x00\u07d4\xa4l\xd27\xb6>\xeaC\x8c\x8e;e\x85\xf6y\xe4\x86\b2\xac\x8965\u026d\xc5\u07a0\x00\x00\u07d4\xa4wy\u063c\x1c{\xce\x0f\x01\x1c\xcb9\xefh\xb8T\xf8\u078f\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\xa4\x82kl8\x82\xfa\xd0\xed\\\x8f\xbb%\xcc@\xccO3u\x9f\x89p\x1bC\xe3D3\xd0\x00\x00\u07d4\xa4\x87Y(E\x8e\xc2\x00]\xbbW\x8c\\\xd35\x80\xf0\xcf\x14R\x8965\u026d\xc5\u07a0\x00\x00\u07d4\xa4\x9fR:\xa5\x13d\xcb\xc7\u0655\x16=4\xebY\r\xed/\b\x89\x90'B\x1b*\x9f\xbc\x00\x00\u07d4\xa4\xa4\x9f\v\xc8h\x8c\xc9\xe6\xdc\x04\xe1\xe0\x8dR\x10&\xe6Ut\x89\n\u05ce\xbcZ\xc6 \x00\x00\u07d4\xa4\xa7\xd3\x06\xf5\x10\xcdX5\x94(\xc0\xd2\xf7\xc3`\x9dVt\u05c9\xb5\x8c\xb6\x1c<\xcf4\x00\x00\u07d4\xa4\xa8:\a8y\x9b\x97\x1b\xf2\xdep\x8c.\xbf\x91\x1c\xa7\x9e\xb2\x89 \x86\xac5\x10R`\x00\x00\u07d4\xa4\xb0\x9d\xe6\xe7\x13\xdciTnv\xef\n\xcf@\xb9O\x02A\xe6\x89\x11}\xc0b~\xc8p\x00\x00\xe0\x94\xa4\u04b4)\xf1\xadSI\xe3\x17\x04\x96\x9e\xdc_%\xee\x8a\xca\x10\x8a\x02\x1e\x19\xe0\u027a\xb2@\x00\x00\xe0\x94\xa4\xd6\xc8.\u076eYG\xfb\xe9\xcd\xfb\xd5H\xae3\xd9\x1aq\x91\x8a\x01\xb1\xaeMn.\xf5\x00\x00\x00\u07d4\xa4\xda4E\r\"\xec\x0f\xfc\xed\xe0\x00K\x02\xf7\x87.\xe0\xb7:\x89\x05\x0fafs\xf0\x83\x00\x00\xe0\x94\xa4\xddY\xab^Q}9\x8eI\xfaS\u007f\x89\x9f\xedL\x15\xe9]\x8a\x04<3\xc1\x93ud\x80\x00\x00\u07d4\xa4\xe6#E\x1e~\x94\xe7\u86e5\xed\x95\u0228:b\xff\xc4\xea\x89\x01\x15\x8eF\t\x13\xd0\x00\x00\u07d4\xa4\xed\x11\xb0r\u061f\xb16u\x9f\u019bB\x8cH\xaa]L\xed\x89\x0e?\x15'\xa0<\xa8\x00\x00\u07d4\xa4\xfb\x14@\x9ag\xb4V\x88\xa8Y>\\\xc2\xcfYl\xedo\x11\x89a\t=|,m8\x00\x00\xe0\x94\xa5\x14\xd0\x0e\xddq\b\xa6\xbe\x83\x9ac\x8d\xb2AT\x18\x17A\x96\x8a\x06ZM\xa2]0\x16\xc0\x00\x00\xe0\x94\xa5\"\xde~\xb6\xae\x12PR*Q13\xa9;\xd4(IG\\\x8a\x04<3\xc1\x93ud\x80\x00\x00\u07d4\xa5$\xa8\xcc\xccIQ\x8d\x17\n2\x82p\xa2\xf8\x813\xfb\xaf]\x89\x0f\xf7\x02-\xac\x10\x8a\x00\x00\u07d4\xa59\xb4\xa4\x01\xb5\x84\xdf\xe0\xf3D\xb1\xb4\"\xc6UC\x16~.\x89\n\u05ce\xbcZ\xc6 \x00\x00\xe0\x94\xa5>\xadT\xf7\x85\n\xf2\x148\xcb\xe0z\xf6\x86'\x9a1[\x86\x8a\x02\x1e\x19\xe0\u027a\xb2@\x00\x00\u07d4\xa5C\xa0f\xfb2\xa8f\x8a\xa0sj\f\x9c\xd4\rx\t\x87'\x8965\u026d\xc5\u07a0\x00\x00\u07d4\xa5gw\vj\xe3 \xbd\xdeP\xf9\x04\xd6c\xe7F\xa6\x1d\xac\xe6\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\xa5h\xdbMW\xe4\xd6tb\xd73\u019a\x9e\x0f\xe2n!\x83'\x89;k\xff\x92f\xc0\xae\x00\x00\u07d4\xa5i\x8059\x1eg\xa4\x90\x13\xc0\x00 yY1\x14\xfe\xb3S\x89\r\x02\xabHl\xed\xc0\x00\x00\u07d4\xa5p\":\xe3\u02a8QA\x8a\x98C\xa1\xacU\xdbH$\xf4\xfd\x89\n\u05ce\xbcZ\xc6 \x00\x00\u07d4\xa5s`\xf0\x02\xe0\xd6M-tE}\x8c\xa4\x85~\xe0\v\xcd\u07c9\x123\xe22\xf6\x18\xaa\x00\x00\u07d4\xa5u\xf2\x89\x1d\xcf\u0368<\\\xf0\x14t\xaf\x11\xee\x01\xb7-\u0089\x05l\xd5_\xc6M\xfe\x00\x00\u07d4\xa5x;\xf342\xff\x82\xacI\x89\x85\xd7\xd4`\xaeg\xec6s\x89b\xa9\x92\xe5:\n\xf0\x00\x00\u07d4\xa5\x87MuF5\xa7b\xb3\x81\xa5\xc4\u01d2H:\xf8\xf2=\x1d\x89\x02\xb5\xe3\xaf\x16\xb1\x88\x00\x00\xe0\x94\xa5\xa4\"\u007fl\xf9\x88%\xc0\u057a\xffS\x15u,\xcc\x1a\x13\x91\x8a\x02\x1e\x19\xe0\u027a\xb2@\x00\x00\u07d4\xa5\xabK\xd3X\x8fF\xcb'.V\xe9=\xee\u04c6\xba\x8bu=\x89HB\xf0A\x05\x87,\x80\x00\xe0\x94\xa5\xba\xd8e\t\xfb\xe0\xe0\xe3\xc0\xe9?m8\x1f\x1a\xf6\xe9\u0501\x8a\x01EB\xba\x12\xa37\xc0\x00\x00\u07d4\xa5\xc36\b;\x04\xf9G\x1b\x8cn\xd76y\xb7Mf\xc3c\uc263e\nL\x9d \xe2\x00\x00\u07d4\xa5\xcd\x129\x92\x19K4\xc4x\x13\x140;\x03\xc5IH\xf4\xb9\x89l\xfc\xc3\xd9\x1d\xa5c\x00\x00\u07d4\xa5\u0578\xb6-\x00-\xef\x92A7\x10\xd1;o\xf8\xd4\xfc}\u04c9\x15\xaf\x1dx\xb5\x8c@\x00\x00\xe0\x94\xa5\xd9ni}F5\x8d\x11\x9a\xf7\x81\x9d\xc7\b\u007fj\xe4\u007f\xef\x8a\x03\x17\xbe\xe8\xaf3\x15\xa7\x80\x00\u07d4\xa5\xde^CO\xdc\xddh\x8f\x1c1\xb6\xfbQ,\xb1\x96rG\x01\x89+^:\xf1k\x18\x80\x00\x00\u07d4\xa5\xe0\xfc<:\xff\xed=\xb6q\tG\xd1\xd6\xfb\x01\u007f>'m\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\xa5\xe9;I\xea|P\x9d\xe7\xc4Ml\xfe\xdd\xefY\x10\u07aa\xf2\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\xa5\xe9\xcdKt%]\"\xb7\u0672z\xe8\xddC\xedn\xd0%+\x89)\x8d\xb2\xf5D\x11\u0640\x00\xe0\x94\xa5\xf0\a{5\x1flP\\\xd5\x15\u07e6\xd2\xfa\u007f\\L\u0487\x8a\bxg\x83&\xea\xc9\x00\x00\x00\u07d4\xa5\xf0u\xfd@\x135W{f\x83\u0081\xe6\xd1\x01C-\xc6\xe0\x89\x91Hx\xa8\xc0^\xe0\x00\x00\u07d4\xa5\xfe,\xe9\u007f\x0e\x8c8V\xbe\r\xe5\xf4\u0732\xce]8\x9a\x16\x89\x01=\xb0\xb8\xb6\x86>\x00\x00\u07d4\xa5\xffb\"-\x80\xc0\x13\xce\xc1\xa0\xe8\x85\x0e\xd4\xd3T\xda\xc1m\x89\vA\a\\\x16\x8b\x18\x00\x00\u07d4\xa6\t\xc2m\xd3P\xc25\xe4K+\x9c\x1d\xdd\xcc\u0429\xd9\xf87\x8965\u026d\xc5\u07a0\x00\x00\u07d4\xa6\f\x12\tuO]\x87\xb1\x81\xdaO\b\x17\xa8\x18Y\xef\x9f\u0609\x02\xb5\xe3\xaf\x16\xb1\x88\x00\x00\xe0\x94\xa6\x10\x1c\x96\x1e\x8e\x1c\x15y\x8f\xfc\xd0\xe3 \x1dw\x86\xec7:\x8a\x01EB\xba\x12\xa37\xc0\x00\x00\xe0\x94\xa6\x13Ei\x96@\x8a\xf1\xc2\xe9>\x17w\x88\xabU\x89^+2\x8a\x01Y\x19\xffG|\x88\xb8\x00\x00\u07d4\xa6\x18\x87\x81\x8f\x91J \xe3\x10w)\v\x83qZk-n\xf9\x89e\xea=\xb7UF`\x00\x00\u07d4\xa6\x1aT\xdfxJD\xd7\x1bw\x1b\x871u\t!\x13\x81\xf2\x00\x8965\u026d\xc5\u07a0\x00\x00\u07d4\xa6\x1c\u06ed\xf0K\x1eT\u0203\xde`\x05\xfc\xdf\x16\xbe\xb8\xeb/\x89lk\x93[\x8b\xbd@\x00\x00\xe0\x94\xa69\xac\xd9k1\xbaS\xb0\u0407c\"\x9e\x1f\x06\xfd\x10^\x9d\x8a\x01\xb1\xaeMn.\xf5\x00\x00\x00\u07d4\xa6BP\x10\x04\xc9\x0e\xa9\xc9\xed\x19\x98\xba\x14\nL\xd6,o_\x89\r\x94\xfb\x8b\x10\xf8\xb1\x80\x00\u07d4\xa6D\xed\x92,\xc27\xa3\xe5\u0117\x9a\x99Tw\xf3nP\xbcb\x89\x1f\xa7=\x84]~\x96\x00\x00\u07d4\xa6F\xa9\\moY\xf1\x04\xc6T\x1dw`uz\xb3\x92\xb0\x8c\x89\u3bb5sr@\xa0\x00\x00\xe0\x94\xa6HL\u0184\xc4\xc9\x1d\xb5>\xb6\x8aM\xa4Zjk\xda0g\x8a\x01EB\xba\x12\xa37\xc0\x00\x00\u07d4\xa6N_\xfbpL,\x919\xd7~\xf6\x1d\x8c\u07e3\x1dz\x88\xe9\x89\a\xc0\x86\x0eZ\x80\xdc\x00\x00\xe0\x94\xa6T&\xcf\xf3x\xed#%5\x13\xb1\x9fIm\xe4_\xa7\u13ca\x01\x86P\x12|\xc3\u0700\x00\x00\u07d4\xa6jIc\xb2\u007f\x1e\xe1\x93+\x17+\xe5\x96N\r:\xe5KQ\x89\t`\xdbwh\x1e\x94\x00\x00\u07d4\xa6\u007f8\x81\x95eB:\xa8_>:\xb6\x1b\xc7c\u02eb\x89\u0749sw\xb0\"\u01be\b\x00\x00\u07d4\xa6\x8c14E\xc2-\x91\x9e\xe4l\xc2\xd0\xcd\xff\x04:uX%\x89\x04\x13t\xfd!\xb0\u0600\x00\u07d4\xa6\x8e\f0\u02e3\xbcZ\x88>T\x03 \xf9\x99\xc7\xcdU\x8e\\\x89a\x9237b\xa5\x8c\x80\x00\u07d4\xa6\x90\xf1\xa4\xb2\n\xb7\xba4b\x86 \u079c\xa0@\xc4<\x19c\x89\xd8\xd7&\xb7\x17z\x80\x00\x00\u07d4\xa6\x9d|\xd1}HB\xfe\x03\xf6*\x90\xb2\xfb\xf8\xf6\xaf{\xb3\x80\x89\x05k\xc7^-c\x10\x00\x00\u07d4\xa6\xa0\x82R\xc8YQw\xcc.`\xfc'Y>#y\xc8\x1f\xb1\x89\x01\x16Q\xac>zu\x80\x00\u07d4\xa6\xa0\xdeB\x1a\xe5Om\x17(\x13\b\xf5dm/9\xf7w]\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\xa6\xb2\xd5s)s`\x10,\a\xa1\x8f\xc2\x1d\xf2\xe7I\x9f\xf4\xeb\x89\xd9o\u0390\u03eb\xcc\x00\x00\xe0\x94\xa6\xc9\x10\xceMIJ\x91\x9c\u036a\xa1\xfc;\x82\xaat\xba\x06\u03ca\x01\xb1\xaeMn.\xf5\x00\x00\x00\u07d4\xa6\u3ea3\x8e\x10J\x1e'\xa4\xd8(i\xaf\xb1\xc0\xaen\xff\x8d\x89\x01\x11@\ueb4bq\x00\x00\u07d4\xa6\xee\xbb\xe4d\u04d1\x87\xbf\x80\u029c\x13\xd7 '\xec[\xa8\xbe\x89\xa2\xa1]\tQ\x9b\xe0\x00\x00\u07d4\xa6\xf6+\x8a=\u007f\x11\"\a\x01\xab\x9f\xff\xfc\xb3'\x95\x9a'\x85\x89\x1bn)\x1f\x18\u06e8\x00\x00\u07d4\xa6\xf93\a\xf8\xbc\xe01\x95\xfe\u0387 C\xe8\xa0?{\xd1\x1a\x89\x9csK\xadQ\x11X\x00\x00\u07d4\xa7\x01\xdfy\xf5\x94\x90\x1a\xfe\x14DH^k \u00fd\xa2\xb9\xb3\x8965\u026d\xc5\u07a0\x00\x00\xe0\x94\xa7\x02L\xfdt,\x1e\xc1<\x01\xfe\xa1\x8d0B\xe6_\x1d]\xee\x8a\x02c\x11\x9a(\xab\u0430\x80\x00\u07d4\xa7\x18\xaa\xadY\xbf9\\\xba+#\xe0\x9b\x02\xfe\f\x89\x81bG\x8960<\x97\xe4hx\x00\x00\u07d4\xa7$|S\xd0Y\xeb|\x93\x10\xf6(\xd7\xfclj\nw?\b\x89\x1b\x1a\xe4\xd6\xe2\xefP\x00\x00\xe0\x94\xa7%7c\xcfJu\u07d2\xca\x1evm\xc4\xee\x8a'E\x14{\x8a\x02F7p\xe9\n\x8fP\x00\x00\u07d4\xa7.\xe6f\u0133^\x82\xa5\x06\x80\x8bD<\xeb\xd5\xc62\xc7\u0749+^:\xf1k\x18\x80\x00\x00\u07d4\xa7DD\xf9\x0f\xbbT\xe5o:\u0276\xcf\u032aH\x19\xe4aJ\x89\x01\x15\x8eF\t\x13\xd0\x00\x00\u07d4\xa7GC\x9a\xd0\u04d3\xb5\xa08a\xd7r\x962m\u8edd\xb9\x8965\u026d\xc5\u07a0\x00\x00\u07d4\xa7`{BW;\xb6\xf6\xb4\xd4\xf2<~*&\xb3\xa0\xf6\xb6\xf0\x89WG=\x05\u06ba\xe8\x00\x00\xe0\x94\xa7i)\x89\n{G\xfb\x85\x91\x96\x01lo\u0742\x89\u03b7U\x8a\x01\x0f\f\xf0d\xddY \x00\x00\u0794\xa7kt?\x98\x1bi0r\xa11\xb2+\xa5\x10\x96\\/\xef\u05c8\xfc\x93c\x92\x80\x1c\x00\x00\u07d4\xa7m?\x15bQ\xb7,\f\xcfKG\xa39<\xbdoI\xa9\u0149Hz\x9a0E9D\x00\x00\u07d4\xa7t(\xbc\xb2\xa0\xdbv\xfc\x8e\xf1\xe2\x0eF\x1a\n2\u016c\x15\x89\x15\xbeat\xe1\x91.\x00\x00\u07d4\xa7u\x8c\xec\xb6\x0e\x8faL\u0396\x13~\xf7+O\xbd\awJ\x89\x1b\x1a\xe4\xd6\xe2\xefP\x00\x00\u07d4\xa7w^J\xf6\xa2:\xfa \x1f\xb7\x8b\x91^Q\xa5\x15\xb7\xa7(\x89\x06\x81U\xa46v\xe0\x00\x00\u07d4\xa7\u007f>\u1793\x88\xbb\xbb\"\x15\xc6#\x97\xb9e`\x13#`\x89\n\u05ce\xbcZ\xc6 \x00\x00\xe0\x94\xa7\x85\x9f\xc0\u007fun\xa7\xdc\xeb\xbc\xcdB\xf0X\x17X-\x97?\x8a\x02\x1e\x19\xe0\u027a\xb2@\x00\x00\u07d4\xa7\x96lH\x9fLt\x8az\u902a'\xa5t%\x17g\xca\xf9\x89\xa2\xa1]\tQ\x9b\xe0\x00\x00\u07d4\xa7\xa3\xbba9\xb0\xad\xa0\f\x1f\u007f\x1f\x9fV\u0654\xbaM\x1f\xa8\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\xa7\xa3\xf1S\xcd\u00c8!\xc2\f]\x8c\x82A\xb2\x94\xa3\xf8+$\x89\x1b\x1a\xe4\xd6\xe2\xefP\x00\x00\u07d4\xa7\xa5\x17\u05ed5\x82\v\t\u0517\xfa~U@\xcd\xe9IXS\x89lk\x93[\x8b\xbd@\x00\x00\xe0\x94\xa7\xc9\u04c8\xeb\xd8s\xe6k\x17\x13D\x83\x97\xd0\xf3\u007f\x8b\u04e8\x8a\x01\x0f\f\xf0d\xddY \x00\x00\u07d4\xa7\u073b\xa9\xb9\xbfgb\xc1EAlPjq\u3d17 \x9c\x89lj\xccg\u05f1\xd4\x00\x00\u07d4\xa7\xe7O\v\xdb'\x8f\xf0\xa8\x05\xa6Ha\x8e\xc5+\x16o\xf1\xbe\x89\x05k\xc7^-c\x10\x00\x00\u07d4\xa7\xe87r\xbc \x0f\x90\x06\xaa*&\r\xba\xa8H=\xc5+0\x89\vB\xd56f7\xe5\x00\x00\xe0\x94\xa7\xef5\u0387\xed\xa6\u008d\xf2HxX\x15\x05>\xc9zPE\x8a\x01\x0f\f\xe9I\xe0\x0f\x93\x00\x00\u07d4\xa7\xf9\"\f\x80G\x82k\xd5\xd5\x18?Ngjmw\xbf\xed6\x89\bPh\x97k\xe8\x1c\x00\x00\u07d4\xa8\a\x10O'\x03\xd6y\xf8\u07af\xc4B\xbe\xfe\x84\x9eB\x95\v\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\xa8\f\xb1s\x8b\xac\b\xd4\xf9\xc0\x8bM\xef\xf5\x15T_\xa8XO\x89\x1b\x1a\xe4\xd6\xe2\xefP\x00\x00\u07d4\xa8\x19\xd2\xec\xe1\"\xe0(\xc8\xe8\xa0J\x06M\x02\xb9\x02\x9b\b\xb9\x8965\u026d\xc5\u07a0\x00\x00\u0794\xa8%\xfdZ\xbby&\xa6|\xf3k\xa2F\xa2K\xd2{\xe6\xf6\xed\x88\xf4?\xc2\xc0N\xe0\x00\x00\u07d4\xa8(U9\x86\x9d\x88\xf8\xa9aS7Uq}~\xb6Uv\xae\x89\n\u05ce\xbcZ\xc6 \x00\x00\u07d4\xa83\x82\xb6\xe1Rg\x97J\x85P\xb9\x8fqv\xc1\xa3S\xf9\xbe\x89\xbf\xfd\xaf/\xc1\xb1\xa4\x00\x00\xe0\x94\xa8DlG\x81\xa77\xacC(\xb1\xe1[\x8a\v?\xbb\x0f\xd6h\x8a\x04\x87\x94\xd1\xf2F\x19*\x00\x00\u07d4\xa8E[A\x17e\u0590\x1e1\x1erd\x03\t\x1eB\xc5f\x83\x89\xb7:\xec;\xfe\x14P\x00\x00\xe0\x94\xa8f\x13\xe6\u0124\xc9\xc5_\\\x10\xbc\xda2\x17]\u02f4\xaf`\x8a\x02C\xd6\xc2\xe3k\xe6\xae\x00\x00\u07d4\xa8m\xb0}\x9f\x81/G\x96b-@\xe0=\x13Xt\xa8\x8at\x89\x01\x15\x8eF\t\x13\xd0\x00\x00\u07d4\xa8\u007fz\xbdo\xa3\x11\x94(\x96x\xef\xb6<\xf5\x84\xee^*a\x89\xd8\xd7&\xb7\x17z\x80\x00\x00\xe0\x94\xa8\x80\u2a3f\x88\xa1\xa8&H\xb4\x01<I\xc4YLC<\u020a\x01\x00N.E\xfb~\xe0\x00\x00\u07d4\xa8\x85w\xa0s\xfb\xaf3\xc4\xcd .\x00\xeap\xefq\x1b@\x06\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\xa8\x91L\x95\xb5`\xec\x13\xf1@Ws8\xc3+\u02f7}:z\x89\t\xc2\x00vQ\xb2P\x00\x00\xe0\x94\xa8\x9a\xc9;#7\x04r\u06ac3~\x9a\xfd\xf6BT?>W\x8a\x02\x1e\x19\xe0\u027a\xb2@\x00\x00\u07d4\xa8\x9d\xf3HY\xed\xd7\xc8 \u06c8w@\xd8\xff\x9e\x15\x15|{\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\xa8\xa4<\x00\x91\x00al\xb4\xaeN\x03?\x1f\xc5\xd7\xe0\xb6\xf1R\x89\u0548\xd0x\xb4?M\x80\x00\u07d4\xa8\xa7\b\xe8O\x82\u06c6\xa3U\x02\x19;Ln\xe9\xa7n\xbe\x8f\x897\b\xba\xed=h\x90\x00\x00\xe0\x94\xa8\xa7\xb6\x8a\u06b4\xe3\xea\xdf\xf1\x9f\xfaX\xe3J?\xce\xc0\xd9j\x8a\x01EB\xba\x12\xa37\xc0\x00\x00\xe0\x94\xa8\xa8\xdb\xdd\x1a\x85\u047e\xee%i\xe9\x1c\xccM\t\xae\u007fn\xa1\x8a\x01:k+VHq\xa0\x00\x00\u07d4\xa8\xac\xa7H\xf9\xd3\x12\xect\u007f\x8bex\x14&\x94\xc7\xe9\xf3\x99\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\xa8\xb6[\xa3\x17\x1a?w\xa65\v\x9d\xaf\x1f\x8dU\xb4\xd2\x01\xeb\x89(b\xf3\xb0\xd2\"\x04\x00\x00\u07d4\xa8\xbe\xb9\x1c+\x99\u0216J\xa9[kJ\x18K\x12i\xfc4\x83\x89\x15\xaf\x1dx\xb5\x8c@\x00\x00\u0794\xa8\xc0\xb0/\xaf\x02\xcbU\x19\u0768\x84\xde{\xbc\x8c\x88\xa2\u0681\x88\xe7\xc2Q\x85\x05\x06\x00\x00\u07d4\xa8\xc1\u05aaA\xfe=e\xf6{\xd0\x1d\xe2\xa8f\xed\x1e\u066eR\x89\x01\xa0Ui\r\x9d\xb8\x00\x00\u07d4\xa8\xca\xfa\xc3\"\x80\xd0!\x02\v\xf6\xf2\xa9x(\x83\u05ea\xbe\x12\x89\x05k\xc7^-c\x10\x00\x00\u07d4\xa8\xdb\v\x9b \x14S3<u\u007fj\u067c\xb5U\xc0-\xa9;\x89wB\xb7\x83\x0f4\x1d\x00\x00\u07d4\xa8\xe4*N3\xd7Rl\xca\x19\u0663m\xcdn\x80@\xd0\xeas\x89:\x8c\x02\xc5\xea-\xe0\x00\x00\u07d4\xa8\xe7 \x1f\xf6\x19\xfa\xff\xc32\xe6\xad7\xedA\xe3\x01\xbf\x01J\x89 \x86\xac5\x10R`\x00\x00\u07d4\xa8\xee\x1d\xf5\xd4K\x12\x84i\xe9\x13V\x9e\xf6\xac\x81\xee\xdaO\u0209\x1b\x1a\xe4\xd6\xe2\xefP\x00\x00\xe0\x94\xa8\xef\x9a\xd2tC`B\x90>A<;\fb\xf5\xf5.\u0544\x8a\x02\x1e\x19\xe0\u027a\xb2@\x00\x00\u07d4\xa8\xf3\u007f\n\xb3\xa1\xd4H\xa9\xe3\xce@\x96_\x97\xa6F\b:4\x89\x11\xe0\xe4\xf8\xa5\v\xd4\x00\x00\u07d4\xa8\xf8\x9d\xd5\xccnd\u05f1\xee\xac\xe0\a\x02\x02,\xd7\xd2\xf0=\x89%\xf2s\x93=\xb5p\x00\x00\xe0\x94\xa9\x04v\xe2\xef\xdf\xeeO8{\x0f2\xa5\x06x\xb0\xef\xb5s\xb5\x8a\x02\x1e\x19\xe0\u027a\xb2@\x00\x00\u07d4\xa9\x14PF\xfa6(\xcf_\xd4\xc6\x13\x92{\xe51\xe6\xdb\x1f\u0749\x06\x12O\xee\x99;\xc0\x00\x00\u07d4\xa9\x14\u0375q\xbf\xd9=d\xdaf\xa4\xe1\b\xea\x13NP\xd0\x00\x89M\x878\x99G\x13y\x80\x00\xe0\x94\xa9\x1aZ{4\x1f\x99\xc55\x14N \xbe\x9ck;\xb4\u008eM\x8a\x01&u:\xa2$\xa7\v\x00\x00\u07d4\xa9%%Q\xa6$\xaeQ7\x19\u06beR\a\xfb\xef\xb2\xfdwI\x89\x02+\x1c\x8c\x12'\xa0\x00\x00\u07d4\xa9'\u050b\xb6\u02c1K\xc6\t\xcb\u02a9\x15\x1f]E\x9a'\xe1\x89\x0e\xb95\t\x00d\x18\x00\x00\u07d4\xa9)\u023dq\xdb\f0\x8d\xac\x06\b\n\x17G\xf2\x1b\x14e\xaa\x89\x1b\x1a\xe4\xd6\xe2\xefP\x00\x00\u07d4\xa9K\xbb\x82\x14\u03cd\xa0\xc2\xf6h\xa2\xacs\xe8bHR\x8dK\x894\n\xad!\xb3\xb7\x00\x00\x00\u07d4\xa9Q\xb2D\xffP\u03eeY\x1d^\x1a\x14\x8d\xf6\xa98\xef*\x1a\x89^\x00\x15\x84\xdf\xcfX\x00\x00\u07d4\xa9`\xb1\xca\xdd;\\\x1a\x8el\xb3\xab\xca\xf5.\xe7\xc3\xd9\xfa\x88\x89R\x8b\xc3T^Rh\x00\x00\u07d4\xa9a\x17\x1fSB\xb1s\xddp\xe7\xbf\xe5\xb5\xca#\x8b\x13\xbc\u0749\xb8'\x94\xa9$O\f\x80\x00\u07d4\xa9u\xb0w\xfc\xb4\u030e\xfc\xbf\x83\x84Y\xb6\xfa$:AY\u0589\x02+\x1c\x8c\x12'\xa0\x00\x00\xe0\x94\xa9{\xeb:H\xc4_\x15((L\xb6\xa9_}\xe4S5\x8e\u018a\x06\x90\x83l\n\xf5\xf5`\x00\x00\u07d4\xa9~\a!DI\x9f\xe5\xeb\xbd5J\xcc~~\xfbX\x98]\b\x89\x90\xf54`\x8ar\x88\x00\x00\u07d4\xa9\x86v/zO)O.\v\x172y\xad,\x81\xa2\"4X\x89\x01\x15\x8eF\t\x13\xd0\x00\x00\u07d4\xa9\x8f\x10\x985\xf5\xea\xcd\x05Cd|4\xa6\xb2i\xe3\x80/\xac\x89\x15\xaf\x1dx\xb5\x8c@\x00\x00\u07d4\xa9\x97\xdf\u01d8j'\x05\bH\xfa\x1cd\u05e7\xd6\xe0z\u0322\x89\a\xc0\x86\x0eZ\x80\xdc\x00\x00\u07d4\xa9\x99\x91\u03bd\x98\xd9\xc88\xc2_zt\x16\xd9\xe2D\xca%\r\x8965\u026d\xc5\u07a0\x00\x00\xe0\x94\xa9\xa1\xcd\xc3;\xfd7o\x1c\rv\xfbl\x84\xb6\xb4\xac'Mh\x8a\x01\x0f\f\xf0d\xddY \x00\x00\u07d4\xa9\xa8\xec\xa1\x1a#\xd6F\x89\xa2\xaa>A}\xbb=3k\xb5\x9a\x89\x0e4S\xcd;g\xba\x80\x00\u07d4\xa9\xac\xf6\x00\b\x1b\xb5[\xb6\xbf\xba\xb1\x81_\xfcN\x17\xe8Z\x95\x89\n\u05ce\xbcZ\xc6 \x00\x00\xe0\x94\xa9\xad\x19&\xbcf\xbd\xb31X\x8e\xa8\x197\x88SM\x98,\x98\x8a\x06ZM\xa2]0\x16\xc0\x00\x00\u07d4\xa9\xaf!\xac\xbeH/\x811\x89j\"\x806\xbaQ\xb1\x94S\u00c9\x02\xb5\xe0!\x98\f\xc1\x80\x00\xe0\x94\xa9\xb2\xd2\xe0IN\xab\x18\xe0}7\xbb\xb8V\xd8\x0e\x80\xf8L\u04ca\x02\x1e\x19\xe0\u027a\xb2@\x00\x00\u07d4\xa9\xbaoA;\x82\xfc\xdd\xf3\xaf\xfb\xbd\u0412\x87\xdc\xf5\x04\x15\u0289\xd8\xd7&\xb7\x17z\x80\x00\x00\u07d4\xa9\xbe\x88\xad\x1eQ\x8b\v\xbb\x02J\xb1\xd8\xf0\xe7?y\x0e\fv\x89\x97\xc9\xceL\xf6\xd5\xc0\x00\x00\u07d4\xa9\xbf\xc4\x10\xdd\xdb q\x1eE\xc0s\x87\xea\xb3\n\x05N\x19\xac\x89>\x99`\x1e\xdfNS\x00\x00\u07d4\xa9\u0522\xbc\xbe[\x9e\bi\xd7\x0f\x0f\xe2\xe1\u05aa\xcdE\xed\u0149\n\xc6\xe7z\xb6c\xa8\x00\x00\xe0\x94\xa9\xd6KO;\xb7\x85\a\"\xb5\x8bG\x8b\xa6\x917^\"NB\x8a\x01EB\xba\x12\xa37\xc0\x00\x00\u07d4\xa9\xd6\xf8q\xcax\x1au\x9a \xac:\u06d7,\xf1()\xa2\b\x892$\xf4'#\xd4T\x00\x00\xe0\x94\xa9\xdc\x04$\u0196\x9dy\x83X\xb3\x93\xb1\x93:\x1fQ\xbe\xe0\n\x8a\x04<3\xc1\x93ud\x80\x00\x00\u07d4\xa9\xe1\x94f\x1a\xacpN\xe9\u07a0C\x97N\x96\x92\xde\xd8J]\x89\x1a&\xa5\x14\"\xa0p\x00\x00\u07d4\xa9\xe2\x837\xe65q\x93\xd9\xe2\xcb#k\x01\xbeD\xb8\x14'\u07c9wC\"\x17\xe6\x83`\x00\x00\u07d4\xa9\xe6\xe2^ekv%Xa\x9f\x14z!\x98[\x88t\xed\xfe\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\xa9\xe9\xdb\xcez,\xb06\x94y\x98\x97\xbe\xd7\xc5M\x15_\u06a8\x89\n\xb5\xae\x8f\u025de\x80\x00\u07d4\xa9\xed7{}n\xc2Yq\xc1\xa5\x97\xa3\xb0\xf3\xbe\xadW\u024f\x89\x15\xaf\x1dx\xb5\x8c@\x00\x00\u07d4\xaa\x02\x00\xf1\xd1~\x9cT\xda\x06G\xbb\x969]W\xa7\x858\u06099>\xf1\xa5\x12|\x80\x00\x00\u07d4\xaa\f\xa3ss7\x17\x8a\f\xaa\xc3\t\x9cXK\x05lV0\x1c\x89/\xb4t\t\x8fg\xc0\x00\x00\u07d4\xaa\x13kG\x96+\xb8\xb4\xfbT\r\xb4\xcc\xf5\xfd\xd0B\xff\xb8\u03c9\x1b\x1bk\u05efd\xc7\x00\x00\xe0\x94\xaa\x14B-o\n\xe5\xa7X\x19N\xd1W\x80\xc88\xd6\u007f\x1e\xe1\x8a\x06\t2\x05lD\x9d\xe8\x00\x00\u07d4\xaa\x16&\x9a\xac\x9c\r\x800h\xd8/\u01d1Q\xda\xdd3Kf\x89\xd8\xd7&\xb7\x17z\x80\x00\x00\xe0\x94\xaa\x16p&\u04da\xb7\xa8V5\x94N\xd9\xed\xb2\xbf\xeb\xa1\x18P\x8a\x01\xc1\xd5\xe2\x1bO\xcfh\x00\x00\u07d4\xaa\x1b7h\xc1m\x82\x1fX\x0ev\xc8\xe4\xc8\xe8m}\u01c8S\x89\x15\xaf\x1dx\xb5\x8c@\x00\x00\u07d4\xaa\x1d\xf9.Q\xdf\xf7\v\x19s\xe0\xe9$\xc6b\x87\xb4\x94\xa1x\x89\x1c\xf8J0\xa0\xa0\xc0\x00\x00\u07d4\xaa,g\x00\x96\xd3\xf990S%B~\xb9U\xa8\xa6\r\xb3\u0149l\x95Y\x06\x99#-\x00\x00\u07d4\xaa15\xcbT\xf1\x02\xcb\xef\xe0\x9e\x96\x10:\x1ayg\x18\xffT\x89\x03\"\"\xd9\xc31\x94\x00\x00\u07d4\xaa2\x1f\xdb\xd4I\x18\r\xb8\xdd\xd3O\x0f\xe9\x06\xec\x18\xee\t\x14\x89%\"H\u07b6\xe6\x94\x00\x00\xe0\x94\xaa9%\xdc\"\v\xb4\xae!w\xb2\x880x\xb6\xdc4l\xa1\xb2\x8a\x01\xb1\xaeMn.\xf5\x00\x00\x00\u07d4\xaa?)`\x1a\x131t^\x05\xc4(0\xa1^q\x93\x8ab7\x89\\(=A\x03\x94\x10\x00\x00\xe0\x94\xaaG\xa4\xff\xc9y622\u025b\x99\xfa\xda\x0f'4\xb0\xae\xee\x8a\x01\xb8H\x9d\xf4\xdb\xff\x94\x00\x00\u07d4\xaaI=?O\xb8fI\x1c\xf8\xf8\x00\xef\xb7\xe22N\xd7\xcf\xe5\x89\\(=A\x03\x94\x10\x00\x00\u07d4\xaaV\xa6]\u012b\xb7/\x11\xba\xe3+o\xbb\aDG\x91\xd5\u0249(\x94\xe9u\xbfIl\x00\x00\xe0\x94\xaaZ\xfc\xfd\x83\t\xc2\u07dd\x15\xbe^jPN}pf$\u014a\x01<\xf4\"\xe3\x05\xa17\x80\x00\u07d4\xaa\x8e\xb0\x82;\a\xb0\xe6\xd2\n\xad\xda\x0e\x95\xcf85\xbe\x19.\x89\x01\xbc\x16\xd6t\xec\x80\x00\x00\u07d4\xaa\x91#~t\r%\xa9/\u007f\xa1F\xfa\xa1\x8c\xe5m\xc6\xe1\xf3\x892$\xf4'#\xd4T\x00\x00\u07d4\xaa\x96\x0e\x10\xc5#\x91\xc5N\x158|\xc6z\xf8'\xb51m\u0309lk\x93[\x8b\xbd@\x00\x00\u07d4\xaa\x9b\xd4X\x955\xdb'\xfa+\xc9\x03\xca\x17\xd6y\xddeH\x06\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\xaa\xa8\xde\xfe\x11\xe3a?\x11\x06\u007f\xb9\x83bZ\b\x99Z\x8d\xfc\x89\n\u05ce\xbcZ\xc6 \x00\x00\u07d4\xaa\xaa\xe6\x8b2\x14\x02\xc8\xeb\xc14h\xf3A\xc6<\f\xf0?\u0389Rf<\u02b1\xe1\xc0\x00\x00\u07d4\xaa\xad\x1b\xaa\xdeZ\xf0N+\x17C\x9e\x93Y\x87\xbf\x8c+\xb4\xb9\x89lk\x93[\x8b\xbd@\x00\x00\xe0\x94\xaa\xb0\n\xbfX(\xd7\xeb\xf2kG\u03ac\u0378\xba\x032Qf\x8a\x02\x1e\x19\xe0\u027a\xb2@\x00\x00\u07d4\xaa\xbd\xb3\\\x15\x14\x98J\x03\x92\x13y?3E\xa1h\xe8\x1f\xf1\x89\x10\xca\u0216\xd29\x00\x00\x00\u07d4\xaa\xca`\xd9\xd7\x00\u7156\xbb\xbb\xb1\xf1\xe2\xf7\x0fF'\xf9\u060965\xbbw\xcbK\x86\x00\x00\u07d4\xaa\xce\u0629V;\x1b\xc3\x11\xdb\xdf\xfc\x1a\xe7\xf5u\x19\xc4D\f\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\xaa\u04b7\xf8\x10f\x95\a\x8el\x13\x8e\xc8\x1at\x86\xaa\xca\x1e\xb2\x89\n\u05ce\xbcZ\xc6 \x00\x00\u07d4\xaa\xe6\x1eC\xcb\r\f\x96\xb3\x06\x99\xf7~\x00\xd7\x11\u0423\x97\x9b\x8965\u026d\xc5\u07a0\x00\x00\u07d4\xaa\xe72\xed\xa6Y\x88\u00e0\f\u007fG/5\x1cF;\x1c\x96\x8e\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\xaa\xf0#\xfe\U0009091b\xb7\x8b\xb7\xab\xc9]f\x9cP\xd5(\xb0\x89\n\u05ce\xbcZ\xc6 \x00\x00\xe0\x94\xaa\xf5\xb2\a\xb8\x8b\r\xe4\xac@\xd7G\xce\xe0n\x17-\xf6\xe7E\x8a\x06\xa7\xb7\x1d\u007fQ\u0410\x00\x00\u07d4\xaa\xf9\xeeK\x88lm\x1e\x95Io\xd2t#[\xf4\xec\xfc\xb0}\x89K\xe4\xe7&{j\xe0\x00\x00\u07d4\xaa\xfb{\x01:\xa1\xf8T\x1c~2{\xf6P\xad\xbd\x19L \x8f\x89I\x9e\t-\x01\xf4x\x00\x00\xe0\x94\xab\t\x863\xee\xee\f\xce\xfd\xf62\xf9WTV\xf6\u0740\xfc\x86\x8a*Z\x05\x8f\u0095\xed\x00\x00\x00\u07d4\xab\f\xedv.\x16a\xfa\xe1\xa9*\xfb\x14\b\x88\x94\x13yH%\x89g\x8a\x93 b\xe4\x18\x00\x00\xe0\x94\xab\x14\xd2!\xe3=TF)\x19\x8c\u0416\xedc\u07e2\x8d\x9fG\x8a\x01EB\xba\x12\xa37\xc0\x00\x00\xe0\x94\xab \x9f\u0729y\u0426G\x01\n\xf9\xa8\xb5/\xc7\xd2\r\x8c\u044a\x01\xee\xe2S,|-\x04\x00\x00\u07d4\xab'\xbax\xc8\xe5\xe3\xda\xef1\xad\x05\xae\xf0\xff\x03%r\x1e\b\x89\x19^\xce\x00n\x02\xd0\x00\x00\u07d4\xab(q\xe5\a\u01fe9eI\x8e\x8f\xb4b\x02Z\x1a\x1cBd\x89*\x03I\x19\u07ff\xbc\x00\x00\u07d4\xab8a\"o\xfe\xc1(\x91\x87\xfb\x84\xa0\x8e\xc3\xed\x042d\xe8\x8965\u026d\xc5\u07a0\x00\x00\u07d4\xab=\x86\xbc\x82\x92~\f\xd4!\xd1F\xe0\u007f\x91\x93'\xcd\xf6\xf9\x89g\x8a\x93 b\xe4\x18\x00\x00\xe0\x94\xab>b\xe7z\x8b\"^A\x15\x92\xb1\xaf0\aR\xfeA$c\x8a\x02\x15\xf85\xbcv\x9d\xa8\x00\x00\u07d4\xab>x)K\xa8\x86\xa0\xcf\xd5\xd3H\u007f\xb3\xa3\a\x8d3\x8dn\x89j\xcb=\xf2~\x1f\x88\x00\x00\u07d4\xab@\x04\xc0@?~\xab\xb0\xeaXo!!V\xc4 =g\xf1\x89lj\xccg\u05f1\xd4\x00\x00\u07d4\xabAo\xe3\rX\xaf\xe5\xd9EL\u007f\xce\u007f\x83\v\xccu\x03V\x89\x0657\x01\xc6\x05\u06c0\x00\u07d4\xabEr\xfb\xb1\xd7+W]i\xecj\xd1s3\x87>\x85R\xfc\x89lj\xc5L\xdahG\x00\x00\u07d4\xabZy\x01av2\ts\xe8\xcd8\xf67U0\x02%1\xc0\x8965\u026d\xc5\u07a0\x00\x00\u07d4\xab]\xfc\x1e\xa2\x1a\xdcB\u03cc?n6\x1e$?\xd0\xdaa\xe5\x89\x10CV\x1a\x88)0\x00\x00\u07d4\xabke\xea\xb8\xdf\xc9\x17\xec\x02Q\xb9\xdb\x0e\u03e0\xfa\x03(I\x89\x1b\x1a\xe4\xd6\xe2\xefP\x00\x00\u07d4\xabp\x91\x93.K\u00dd\xbbU#\x80\u0293O\xd7\x16m\x1en\x89\xb5\x0f\u03ef\xeb\xec\xb0\x00\x00\u07d4\xabt\x16\xff2%IQ\u02fcbN\xc7\xfbE\xfc~\u02a8r\x89\x12nr\xa6\x9aP\xd0\x00\x00\u07d4\xab|B\xc5\xe5-d\x1a\a\xadu\t\x9cb\x92\x8b\u007f\x86b/\x89\x126\x1a\xa2\x1d\x14\xba\x00\x00\u07d4\xab}T\xc7\xc6W\x0e\xfc\xa5\xb4\xb8\xcep\xf5*Ws\xe5\xd5;\x89\x0f(:\xbe\x9d\x9f8\x00\x00\u07d4\xab~\v\x83\xed\x9aBLm\x1ejo\x87\xa4\xdb\xf0d\t\xc7\u0589\x82\x1a\xb0\xd4AI\x80\x00\x00\u07d4\xab\x84\xa0\xf1G\xad&T\x00\x00+\x85\x02\x9aA\xfc\x9c\xe5\u007f\x85\x8965\u026d\xc5\u07a0\x00\x00\u07d4\xab\x93\xb2n\xce\n\n\xa2\x13e\xaf\xed\x1f\xa9\xae\xa3\x1c\xd5Dh\x89W+{\x98sl \x00\x00\u07d4\xab\x94\x8aJ\xe3y\\\xbc\xa11&\xe1\x92S\xbd\xc2\x1d:\x85\x14\x89\n\u05ce\xbcZ\xc6 \x00\x00\u07d4\xab\x9a\xd3n\\t\xce.\x969\x9fW\x83\x941\xd0\u77d6\xab\x89\b\xe3\xf5\v\x17<\x10\x00\x00\u07d4\xab\xb2\xe6\xa7*@\xban\xd9\b\u037c\xec<V\x12X12\xfe\x89O%\x91\xf8\x96\xa6P\x00\x00\u07d4\xab\xc0h\xb4\x97\x9b\x0e\xa6Jb\u04f7\xaa\x89}s\x81\r\xc53\x89j\xcb=\xf2~\x1f\x88\x00\x00\u07d4\xab\xc4_\x84\xdbs\x82\xdd\xe5L_}\x898\xc4/O:;\u0109\n\u05ce\xbcZ\xc6 \x00\x00\u07d4\xab\xc4\xca\xebGMF'\xcbn\xb4V\xec\xba\x0e\xcd\b\xed\x8a\xe1\x89\u0556{\xe4\xfc?\x10\x00\x00\xe0\x94\xab\xc7G\x06\x96I`\xdf\xe0\u0723\u0727\x9e\x92\x16\x05o\x1c\xf4\x8a\bxg\x83&\xea\xc9\x00\x00\x00\xe0\x94\xab\u0269\x9e\x8a!H\xa5Zm\x82\xbdQ\xb9\x8e\xb59\x1f\u06ef\x8a\x01EB\xba\x12\xa37\xc0\x00\x00\u07d4\xab\u037c\x8f\x1d\xd1:\xf5x\u0524wJb\x18+\xed\xf9\xf9\xbe\x89\x01\xfc\xc2{\xc4Y\xd2\x00\x00\u07d4\xab\xd1T\x905\x13\xb8\xdaO\x01\x9fh(K\x06V\xa1\xd0\x16\x9b\x8965\u026d\xc5\u07a0\x00\x00\u07d4\xab\xd2\x1e\xff\x95O\u01a7\xde&\x91*|\xbb0:f\a\x80N\x89R<\x9a\xa6\x96\xeb\x94\x00\x00\u07d4\xab\xd4\xd6\xc1fcX\xc0@o\xdf:\xf2H\xf7\x8e\u0383\x01\x04\x89r}\xe3J$\xf9\x00\x00\x00\u07d4\xab\xd9`[>\x91\xac\xfdwx0\xd1dcG\x8a\xe0\xfcw \x89\a?u\u0460\x85\xba\x00\x00\xe0\x94\xab\u071f\x1b\xcfM\x19\xee\x96Y\x100\xe7r\xc340/}\x83\x8a\b~^\x11\xa8\x1c\xb5\xf8\x00\x00\u07d4\xab\xde\x14{*\xf7\x89\ua946T~f\xc4\xfa&d\xd3(\xa4\x89\rk`\x81\xf3L\x12\x80\x00\xe0\x94\xab\xe0|\xedj\xc5\xdd\xf9\x91\xef\xf6\xc3\xda\"jt\x1b\xd2C\xfe\x8a\x02\x1e\x19\xe0\u027a\xb2@\x00\x00\u07d4\xab\xf1/\xa1\x9e\x82\xf7lq\x8f\x01\xbd\xca\x00\x03gE#\xef0\x89lk\x93[\x8b\xbd@\x00\x00\xe0\x94\xab\xf7(\u03d3\x12\xf2!(\x02NpF\xc2Q\xf5\xdcY\x01\xed\x8a\x06A\xe8\xa15c\xd8\xf8\x00\x00\u07d4\xab\xf8\xff\xe0p\x8a\x99\xb5(\xcc\x1e\xd4\xe9\xceK\r\x060\xbe\x8c\x89z\xb5\u00ae\xee\xe68\x00\x00\u07d4\xab\xfc\xf5\xf2P\x91\xceW\x87_\xc6t\xdc\xf1\x04\xe2\xa7=\xd2\xf2\x89\x01\x11du\x9f\xfb2\x00\x00\u07d4\xab\xfe\x93d%\xdc\u01f7K\x95P\x82\xbb\xaa\xf2\xa1\x1dx\xbc\x05\x89K\xe4\xe7&{j\xe0\x00\x00\u07d4\xac\x02OYO\x95X\xf0ICa\x8e\xb0\xe6\xb2\xeeP\x1d\xc2r\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\xac\x12*\x03\xcd\x05\x8c\x12._\xe1{\x87/Hw\xf9\u07d5r\x89j\xc5\xc6-\x94\x86\a\x00\x00\u07d4\xac\x14.\xda\x11W\xb9\xa9\xa6C\x90\xdf~j\xe6\x94\xfa\u0249\x05\x89\n\u05ce\xbcZ\xc6 \x00\x00\u07d4\xac\x1d\xfc\x98Kq\xa1\x99)\xa8\x1d\x81\xf0J|\xbb\x14\a7\x03\x89 \x86\xac5\x10R`\x00\x00\xe0\x94\xac!\xc1\xe5\xa3\xd7\xe0\xb5\x06\x81g\x9d\xd6\u01d2\xdb\u0287\xde\u02ca\x15-\x02\xc7\xe1J\xf6\x80\x00\x00\xe0\x94\xac(\x89\xb5\x96o\f\u007f\x9e\xdbB\x89\\\xb6\x9d\x1c\x04\xf9#\xa2\x8a\x01\x0f\f\xf0d\xddY \x00\x00\u07d4\xac(\xb5\xed\xea\x05\xb7o\x8c_\x97\bEA'|\x96ijL\x8965\u026d\xc5\u07a0\x00\x00\u07d4\xac,\x8e\t\xd0d\x93\xa68XC{\xd2\v\xe0\x19bE\x03e\x89g\x8a\x93 b\xe4\x18\x00\x00\u07d4\xac.vm\xac?d\x8fcz\xc6q?\u0770h\xe4\xa4\xf0M\x89\n\xad\xec\x98?\xcf\xf4\x00\x00\xe0\x94\xac9\x00)\x8d\xd1M|\xc9mJ\xbbB\x8d\xa1\xba\xe2\x13\xff\xed\x8a\x05<\xa1)t\x85\x1c\x01\x00\x00\u07d4\xac=\xa5&\xcf\u0388)s\x02\xf3LI\xcaR\r\xc2q\xf9\xb2\x89+^:\xf1k\x18\x80\x00\x00\u07d4\xacD`\xa7nm\xb2\xb9\xfc\xd1R\xd9\xc7q\x8d\x9a\xc6\xed\x8co\x89\n\u05ce\xbcZ\xc6 \x00\x00\u07d4\xacJ\xcf\xc3n\xd6\tJ'\xe1\x18\xec\xc9\x11\xcdG>\x8f\xb9\x1f\x89a\x91>\x14@<\f\x00\x00\u07d4\xacL\xc2V\xaet\xd6$\xac\xe8\r\xb0x\xb2 \u007fW\x19\x8fk\x89lyt\x12?d\xa4\x00\x00\u07d4\xacN\xe9\xd5\x02\xe7\xd2\xd2\xe9\x9eY\xd8\xca}_\x00\xc9KM\u058965\u026d\xc5\u07a0\x00\x00\u07d4\xacR\xb7~\x15fH\x14\xf3\x9eO'\x1b\xe6A0\x8d\x91\xd6\u0309\v\xed\x1d\x02c\xd9\xf0\x00\x00\u07d4\xacY\x99\xa8\x9d-\u0486\u0568\fm\xee~\x86\xaa\xd4\x0f\x9e\x12\x89\xd2U\xd1\x12\xe1\x03\xa0\x00\x00\u07d4\xac_br1H\r\r\x950.m\x89\xfc2\xcb\x1dO\xe7\xe3\x89\n\u05ce\xbcZ\xc6 \x00\x00\xe0\x94\xac`\x8e+\xac\x9d\xd2\a(\u0494~\xff\xbb\xbf\x90\n\x9c\xe9K\x8a\x01EK\r\xb3uh\xfc\x00\x00\u07d4\xacm\x02\xe9\xa4k7\x9f\xacJ\u0271\u05f5\xd4{\xc8P\xce\x16\x89_h\xe8\x13\x1e\u03c0\x00\x00\u07d4\xacoh\xe87\xcf\x19a\xcb\x14\xabGDm\xa1h\xa1m\u0789\x89Hz\x9a0E9D\x00\x00\u07d4\xacw\xbd\xf0\x0f\u0558[]\xb1+\xbe\xf8\x008\n\xbc*\x06w\x8965\u026d\xc5\u07a0\x00\x00\xe0\x94\xac~\x03p'#\xcb\x16\xee'\xe2-\u0438\x15\xdc-\\\xae\x9f\x8a\x03c\\\x9a\xdc]\xea\x00\x00\x00\u07d4\xac\x8bP\x9a\xef\xea\x1d\xbf\xaf+\xb35\x00\xd6W\vo\xd9mQ\x89b\xa9\x92\xe5:\n\xf0\x00\x00\u07d4\xac\x8e\x87\xdd\xda^x\xfc\xbc\xb9\xfa\u007f\xc3\xce\x03\x8f\x9f}.4\x89lk\x93[\x8b\xbd@\x00\x00\xe0\x94\xac\x9f\xffh\xc6\x1b\x01\x1e\xfb\xec\xf08\xedr\u06d7\xbb\x9er\x81\x8a\x02\x05\xb4\u07e1\xeetx\x00\x00\u07d4\xac\xa1\xe6\xbcd\xcc1\x80\xf6 \xe9M\u0171\xbc\xfd\x81X\xe4]\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\xac\xa2\xa883\v\x170-\xa71\xd3\r\xb4\x8a\x04\xf0\xf2\a\xc1\x89Hz\x9a0E9D\x00\x00\u07d4\xac\xaa\xdd\xcb\xf2\x86\xcb\x0e!]\xdaUY\x8f\u007f\xf0\xf4\xad\xa5\u018965\u026d\xc5\u07a0\x00\x00\u07d4\xac\xb9C8UK\u0108\u0308\xae-\x9d\x94\b\rk\u07c4\x10\x8965\u026d\xc5\u07a0\x00\x00\u07d4\xac\xbc-\x19\xe0l;\xab\xbb[o\x05+k\xf7\xfc7\xe0r)\x89\n\u05ce\xbcZ\xc6 \x00\x00\u07d4\xac\xbd\x18U\x89\xf7\xa6\x8ag\xaaK\x1b\xd6Pw\xf8\xc6NN!\x89\n\u05ce\xbcZ\xc6 \x00\x00\u07d4\xac\xc0bp,Ya]4D\xefb\x14\xb8\x86+\x00\x9a\x02\xed\x89QO\xcb$\xff\x9cP\x00\x00\u07d4\xac\xc0\x90\x9f\xda.\xa6\xb7\xb7\xa8\x8d\xb7\xa0\xaa\xc8h\t\x1d\xdb\xf6\x89\x013v_\x1e&\u01c0\x00\u07d4\xac\xc1\u01c7\x86\xabM+;'q5\xb5\xba\x12>\x04\x00Hk\x89\x04E\x91\xd6\u007f\xec\xc8\x00\x00\u07d4\xac\xc4j*U\\t\xde\u0522\xbd\tN\x82\x1b\x97\x84;@\xc0\x89i*\xe8\x89p\x81\xd0\x00\x00\u07d4\xac\u015f;0\xce\xff\xc5da\xcc[\x8d\xf4\x89\x02$\x0e\x0e{\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\xac\xce\x01\xe0\xa7\x06\x10\xdcp\xbb\x91\xe9\x92o\xa9\x95\u007f7/\xba\x89\x1d\x1c_>\xda \xc4\x00\x00\u07d4\xac\xd8\u0751\xf7\x14vLEg|c\xd8R\xe5n\xb9\xee\xce.\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\xac\u2af6;\x06\x04@\x9f\xbd\xe3\xe7\x16\u0487mD\xe8\xe5\u0749\b=lz\xabc`\x00\x00\xe0\x94\xac\xec\x91\xefiA\xcfc\v\xa9\xa3\u71e0\x12\xf4\xa2\xd9\x1d\u050a\x10\xf0\xcf\x06M\u0552\x00\x00\x00\u07d4\xad\nJ\xe4x\xe9cn\x88\xc6\x04\xf2B\xcfT9\xc6\xd4V9\x89\xbe\xd1\xd0&=\x9f\x00\x00\x00\u07d4\xad\x17\x99\xaa\xd7`+E@\u0343/\x9d\xb5\xf1\x11P\xf1hz\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\xad\x1dh\xa08\xfd%\x86\x06~\xf6\xd15\xd9b\x8ey\xc2\xc9$\x89\xfe\t\xa5'\x9e*\xbc\x00\x00\u07d4\xad*\\\x00\xf9#\xaa\xf2\x1a\xb9\xf3\xfb\x06n\xfa\n\x03\xde/\xb2\x8965\xbbw\xcbK\x86\x00\x00\u07d4\xad5e\xd5+h\x8a\xdd\xed\b\x16\x8b-8r\xd1}\n&\xae\x89\x05k\xc7^-c\x10\x00\x00\u07d4\xad7|\xd2^\xb5>\x83\xae\t\x1a\n\x1d+E\x16\xf4\x84\xaf\u0789i*\xe8\x89p\x81\xd0\x00\x00\xe0\x94\xadAM)\xcb~\xe9s\xfe\xc5N\"\xa3\x88I\x17\x86\xcfT\x02\x8a\x02\xf6\xf1\a\x80\xd2,\xc0\x00\x00\u07d4\xadD5~\x01~$OGi1\u01f8\x18\x9e\xfe\xe8\n]\n\x89\x10CV\x1a\x88)0\x00\x00\u07d4\xadW\xaa\x9d\x00\xd1\fC\x9b5\xef\xcc\v\xec\xac.9U\xc3\x13\x89\n\u05ce\xbcZ\xc6 \x00\x00\u07d4\xadY\xa7\x8e\xb9\xa7J\u007f\xbd\xae\xfa\xfa\x82\xea\u0684u\xf0\u007f\x95\x89\x1b\x1a\xe4\xd6\xe2\xefP\x00\x00\u07d4\xadZ\x8d<dx\xb6\x9fe}\xb3\x83z%u\xef\x8e\x1d\xf91\x89\x02\x01V\xe1\x04\xc1\xb3\x00\x00\u07d4\xadf\r\xec\x82U\"\xa9\xf6/\xce\xc3\u01771\x98\r\u0086\ua262\xa1]\tQ\x9b\xe0\x00\x00\u07d4\xadf(5.\xd39\v\xaf\xa8m\x92>V\x01L\xfc\xb3`\xf4\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\xadr\x81!\x87?\x04V\xd0Q\x8b\x80\xabe\x80\xa2\x03pe\x95\x89\x1b\x1a\xe4\xd6\xe2\xefP\x00\x00\u07d4\xads,\x97e\x93\xee\xc4x;N.\xcdy9yx\v\xfe\u06c9lk\x93[\x8b\xbd@\x00\x00\u07d4\xad}\xd0S\x85\x9e\xdf\xf1\xcbo\x9d*\xcb\xedm\xd5\xe32Bo\x89j\xcb=\xf2~\x1f\x88\x00\x00\u07d4\xad\x80\xd8e\xb8\\4\xd2\xe6IK.z\xef\xeak\x9a\xf1\x84\u06c9\xd8\xd7&\xb7\x17z\x80\x00\x00\xe0\x94\xad\x8b\xfe\xf8\u018aH\x16\xb3\x91o5\xcb{\xfc\xd7\xd3\x04\tv\x8a\bxg\x83&\xea\xc9\x00\x00\x00\u07d4\xad\x8eH\xa3wi]\xe0\x146:R:(\xb1\xa4\fx\xf2\b\x8965\u026d\xc5\u07a0\x00\x00\u07d4\xad\x91\n#\u0585\x06\x13eJ\xf7\x863z\u04a7\bh\xacm\x89lh\xcc\u041b\x02,\x00\x00\u07d4\xad\x92~\x03\xd1Y\x9ax\xca+\xf0\xca\u04a1\x83\xdc\xebq\xea\xc0\x89j\xcb=\xf2~\x1f\x88\x00\x00\xe0\x94\xad\x92\xca\x06n\xdb|q\x1d\xfc[\x16a\x92\xd1\xed\xf8\xe7q\x85\x8a\a\x9f\x90\\o\xd3N\x80\x00\x00\u07d4\xad\x94#_\u00f3\xf4z$\x13\xaf1\u8111I\b\xef\fE\x89\x1b\x1b\x01B\xd8\x15\x84\x00\x00\u07d4\xad\x9e\x97\xa0H/5:\x05\xc0\xf7\x92\xb9w\xb6\xc7\xe8\x11\xfa_\x89\n\u05ce\xbcZ\xc6 \x00\x00\u07d4\xad\x9fL\x89\n;Q\x1c\xeeQ\xdf\xe6\xcf\xd7\xf1\t;vA,\x89\x1bv|\xbf\xeb\f\xe4\x00\x00\u07d4\xad\xaa\x0eT\x8c\x03Z\xff\xedd\xcag\x8a\x96?\xab\xe9\xa2k\xfd\x89\x03\xcbq\xf5\x1f\xc5X\x00\x00\u07d4\xad\xb9H\xb1\xb6\xfe\xfe }\xe6^\x9b\xbc-\xe9\x8e`]\vW\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\xad\xc1\x9e\xc85\xaf\xe3\u5347\u0713\xa8\xa9!<\x90E\x13&\x89j\xdb\xe54\"\x82\x00\x00\x00\u07d4\xad\xc8\"\x8e\xf9(\xe1\x8b*\x80}\x00\xfb<ly\xcd\x1d\x9e\x96\x89\x01<i\xdf3N\xe8\x00\x00\u07d4\xad\xdb&1r'\xf4\\\x87\xa2\u02d0\xdcL\xfd\x02\xfb#\xca\xf8\x8965\u026d\xc5\u07a0\x00\x00\u07d4\xad\xe6\xf8\x16;\xf7\u01fbJ\xbe\x8e\x98\x93\xbd\f\xc1\x12\xfe\x88r\x89\x11\xc2]\x00M\x01\xf8\x00\x00\u07d4\xad\xeb J\xa0\u00ce\x17\x9e\x81\xa9N\u0633\xe7\xd50G\xc2k\x89 \xf5\xb1\uab4d\x80\x00\x00\u07d4\xad\xebR\xb6\x04\xe5\xf7\u007f\xaa\xac\x88'[\x8dkI\xe9\xf9\xf9\u007f\x89qBk\x00\x95n\xd2\x00\x00\xe0\x94\xad\xf1\xac\xfe\x99\xbc\x8c\x14\xb3\x04\xc8\xd9\x05\xba'e{\x8a{\u010a\x04<3\xc1\x93ud\x80\x00\x00\u07d4\xad\xf8R\x03\xc87j_\u0798\x158J5\f8y\xc4\u02d3\x89>1\xfcgX\x15\xaa\x00\x00\u07d4\xad\xff\r\x1d\v\x97G\x1ev\u05c9\xd2\u470at\xf9\xbdT\xff\x89e\xea=\xb7UF`\x00\x00\u07d4\xae\x06,D\x86\x18d0u\xdez\x0004-\xce\xd6=\xba\u05c9,\xc6\u034c\u0082\xb3\x00\x00\xe0\x94\xae\x10\xe2z\x01O\r0k\xaf&mH\x97\u021a\xee\xe2\xe9t\x8a\x04<3\xc1\x93ud\x80\x00\x00\u07d4\xae\x12k8,\xf2W\xfa\xd7\xf0\xbc}\x16)~T\xccrg\u0689\x10CV\x1a\x88)0\x00\x00\u07d4\xae\x13\xa0\x85\x11\x11\x0f2\xe5;\xe4\x12xE\xc8C\xa1\xa5|{\x89\x1b\x1a\xe4\xd6\xe2\xefP\x00\x00\xe0\x94\xae\x17\x9aF\r\xb6c&t=$\xe6u#\xa5{$m\xaf\u007f\x8a\x01\x00\a\xae|\xe5\xbb\xe4\x00\x00\u07d4\xae\"(ey\x90y\xaa\xf4\xf0gJ\f\u06ab\x02\xa6\xd5p\xff\x89lk\x93[\x8b\xbd@\x00\x00\xe0\x94\xae#\x9a\xcf\xfdN\xbe.\x1b\xa5\xb4\x17\x05r\xdcy\xcce3\xec\x8a\x02\x8a\x85t%Fo\x80\x00\x00\u07d4\xae/\x9c\x19\xacv\x13e\x94C#\x93\xb0G\x1d\b\x90!d\u04c9%\xdf\x05\u01a8\x97\xe4\x00\x00\u07d4\xae4\x86\x1d4\"S\x19O\xfcfR\xdf\xdeQ\xabD\xca\xd3\xfe\x89\x19F\bhc\x16\xbd\x80\x00\u07d4\xae6\xf7E!!\x91>\x80\x0e\x0f\xcd\x1ae\xa5G\x1c#\x84o\x89\b\xe3\xf5\v\x17<\x10\x00\x00\u07d4\xae?\x98\xa4C\xef\xe0\x0f>q\x1dR]\x98\x94\u071aa\x15{\x89\x10\x04\xe2\xe4_\xb7\xee\x00\x00\xe0\x94\xaeG\xe2`\x9c\xfa\xfe6\x9df\xd4\x15\xd99\xde\x05\b\x1a\x98r\x8a\x05\xba\xec\xf0%\xf9\xb6P\x00\x00\u07d4\xaeO\x12.5\xc0\xb1\xd1\xe4\x06\x92\x91E|\x83\xc0\u007f\x96_\xa3\x8965\u026d\xc5\u07a0\x00\x00\u07d4\xaePU\x81L\xb8\xbe\f\x11{\xb8\xb1\xc8\u04b6;F\x98\xb7(\x89\x01\xbc\x93.\xc5s\xa3\x80\x00\u07d4\xaeS\x8cs\u0173\x8d\x8dXM~\xbd\xad\xef\xb1\\\xab\xe4\x83W\x896'\xe8\xf7\x127<\x00\x00\u07d4\xaeW\xcc\x12\x9a\x96\xa8\x99\x81\xda\xc6\r/\xfb\x87}]\xc5\xe42\x89<:#\x94\xb3\x96U\x00\x00\u07d4\xaeZ\xa1\xe6\u00b6\x0fo\xd3\xef\xe7!\xbbJq\x9c\xbe=o]\x89+$\u01b5Z^b\x00\x00\u07d4\xae\\\x9b\xda\xd3\xc5\u0221\"\x04D\xae\xa5\xc2)\xc1\x83\x9f\x1dd\x89\x19\xe2\xa4\xc8\x18\xb9\x06\x00\x00\u07d4\xae\\\xe35Z{\xa9\xb32v\f\tP\u00bcE\xa8_\xa9\xa0\x89\x15\xaf\x1dx\xb5\x8c@\x00\x00\xe0\x94\xae]\"\x1a\xfc\xd3\u0493U\xf5\b\xea\xdf\xca@\x8c\xe3<\xa9\x03\x8a\x15-\x02\xc7\xe1J\xf6\x80\x00\x00\u07d4\xaec[\xf781\x11\x9d-)\xc0\xd0O\xf8\xf8\xd8\u0425zF\x89Hz\x9a0E9D\x00\x00\xe0\x94\xaed\x81U\xa6X7\x0f\x92\x9b\xe3\x84\xf7\xe0\x01\x04~I\xddF\x8a\x02\xdf$\xae2\xbe D\x00\x00\xe0\x94\xaeo\fs\xfd\xd7|H\x97'Q!t\u0675\x02\x96a\x1cL\x8a\x01EB\xba\x12\xa37\xc0\x00\x00\u07d4\xaep\xe6\x9d,J\n\xf8\x18\x80{\x1a'\x05\xf7\x9f\u0435\xdb\u01095e\x9e\xf9?\x0f\xc4\x00\x00\u07d4\xaew9\x12N\xd1S\x05%\x03\xfc\x10\x14\x10\xd1\xff\xd8\xcd\x13\xb7\x8964\xfb\x9f\x14\x89\xa7\x00\x00\u07d4\xaex\xbb\x84\x919\xa6\xba8\xae\x92\xa0\x9ai`\x1c\xc4\xcbb\u0449\x1b\x1a\xe4\xd6\xe2\xefP\x00\x00\u07d4\xae\x84\"\x10\xf4M\x14\u0124\u06d1\xfc\x9d;;P\x01O{\xf7\x89\xd8\xd7&\xb7\x17z\x80\x00\x00\u07d4\xae\x84.\x81\x85\x8e\xcf\xed\xf6Plhm\xc2\x04\xac\x15\xbf\x8b$\x89\x02+\x1c\x8c\x12'\xa0\x00\x00\u07d4\xae\x89T\xf8\xd6\x16m\xe5\a\xcfa)}\x0f\xc7\xcak\x9eq(\x89\x10CV\x1a\x88)0\x00\x00\u07d4\xae\x9e\xcdk\u0755.\xf4\x97\xc0\x05\n\u0aca\x82\xa9\x18\x98\u0389\x01\xa0Ui\r\x9d\xb8\x00\x00\u07d4\xae\x9f\\?\xbb\xe0\u027c\xbf\x1a\xf8\xfft\xea(\v:]\x8b\b\x89]\u0212\xaa\x111\xc8\x00\x00\u07d4\xae\xad\x88\u0589Ak\x1c\x91\xf26D!7[}<p\xfb.\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\xae\xad\xfc\u0417\x8e\xda\xd7J2\xbd\x01\xa0\xa5\x1d7\xf2F\xe6a\x89\x0e\x189\x8ev\x01\x90\x00\x00\u07d4\xae\xb9\x16\xeb\xf4\x9d\x0f\x86\xc1?s1\xce\xf1\x9e\x12\x997Q-\x89 \x85e[\x8d\x1b\n\x00\x00\u07d4\xae\xbdO ]\u7676K5d\xb2V\xd4*q\x1d7\uf649?\u03cbEt\xf8N\x00\x00\xe0\x94\xae\xc2|\xe2\x13>\x82\xd0RR\n\xfb\\Wm\x9f~\xb9>\u048a\r\xd0A \xba\t\xcf\xe6\x00\x00\u07d4\xae\xc2\u007f\xf5\xd7\xf9\xdd\u0691\x18?F\xf9\xd5%C\xb6\xcd+/\x89\x18e\x01'\xcc=\xc8\x00\x00\u07d4\xae\xe4\x9dh\xad\xed\xb0\x81\xfdCpZ_x\xc7x\xfb\x90\xdeH\x89\x01\x15\x8eF\t\x13\xd0\x00\x00\u07d4\xae\xf5\xb1\"X\xa1\x8d\xec\a\xd5\xec.1et\x91\x9dy\xd6\u0589lk\x93[\x8b\xbd@\x00\x00\u07d4\xae\xfc\xfe\x88\xc8&\xcc\xf11\xd5N\xb4\ua7b8\x0ea\xe1\xee%\x89\x12nr\xa6\x9aP\xd0\x00\x00\u07d4\xaf\x06\xf5\xfam\x12\x14\xecC\x96}\x1b\xd4\xdd\xe7J\xb8\x14\xa98\x89\x04\xc5>\xcd\xc1\x8a`\x00\x00\u07d4\xaf\x11H\xefl\x8e\x10=u0\xef\xc9\x16y\u026c'\x00\t\x93\x89\n\u05ce\xbcZ\xc6 \x00\x00\u07d4\xaf >\"\x9d~mA\x9d\xf47\x8e\xa9\x87\x15Q_c\x14\x85\x89j\xcb=\xf2~\x1f\x88\x00\x00\xe0\x94\xaf X\xc7(,\xf6|\x8c<\xf90\x13<\x89a|\xe7])\x8a\x01w\"J\xa8D\xc7 \x00\x00\u07d4\xaf&\xf7\u01bfE> x\xf0\x89S\u4c80\x04\xa2\xc1\xe2\t\x89\x05k\xc7^-c\x10\x00\x00\u07d4\xaf0\x87\xe6.\x04\xbf\x90\rZT\xdc>\x94bt\u0692B;\x89\x01\x15\x8eF\t\x13\xd0\x00\x00\u07d4\xaf6\x14\u0736\x8a6\xe4ZN\x91\x1ebybG\"-Y[\x89z\x81\x06_\x11\x03\xbc\x00\x00\u07d4\xaf6\x15\u01c9\u0431\x15*\xd4\xdb%\xfe]\xcf\"(\x04\xcfb\x8965\u026d\xc5\u07a0\x00\x00\u07d4\xaf<\xb5\x96Y3\xe7\xda\u0603i;\x9c>\x15\xbe\xb6\x8aHs\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\xafD\x93\xe8R\x1c\xa8\x9d\x95\xf5&|\x1a\xb6?\x9fEA\x1e\x1b\x89\n\u05ce\xbcZ\xc6 \x00\x00\xe0\x94\xafL\xf4\x17\x85\x16\x1fW\x1d\f\xa6\x9c\x94\xf8\x02\x1fA)N\u028a\x02\x15\xf85\xbcv\x9d\xa8\x00\x00\u07d4\xafR\x9b\xdbE\x9c\xc1\x85\xbe\xe5\xa1\u014b\xf7\xe8\xcc\xe2\\\x15\r\x89\n\xad\xec\x98?\xcf\xf4\x00\x00\u07d4\xafg\xfd>\x12\u007f\xd9\xdc6\xeb?\xcdj\x80\u01feOu2\xb2\x89Z\x87\xe7\xd7\xf5\xf6X\x00\x00\u07d4\xafw\x1094Z40\x01\xbc\x0f\x8aY#\xb1&\xb6\rP\x9c\x895e\x9e\xf9?\x0f\xc4\x00\x00\xe0\x94\xaf\u007fy\xcbAZ\x1f\xb8\u06fd\tF\a\xee\x8dA\xfb|Z;\x8a\x02\x1e\x19\xe0\u027a\xb2@\x00\x00\u07d4\xaf\x87\xd27\x1e\xf3x\x95\u007f\xbd\x05\xba/\x1df\x93\x1b\x01\u2e09%\xf2s\x93=\xb5p\x00\x00\u07d4\xaf\x88\x0f\xc7V}U\x95\xca\xcc\xe1\\?\xc1L\x87B\xc2l\x9e\x89\a?u\u0460\x85\xba\x00\x00\u07d4\xaf\x8e\x1d\xcb1L\x95\r6\x87CM0\x98X\xe1\xa8s\x9c\u0509\x0e~\xeb\xa3A\vt\x00\x00\u07d4\xaf\x99-\xd6i\xc0\x88>U\x15\xd3\xf3\x11*\x13\xf6\x17\xa4\xc3g\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\xaf\xa1\u056d8\xfe\xd4GY\xc0[\x89\x93\xc1\xaa\r\xac\xe1\x9f@\x89\x04V9\x18$O@\x00\x00\xe0\x94\xaf\xa59XnG\x19\x17J;F\xb9\xb3\xe6c\xa7\u0475\xb9\x87\x8a\x01\x0f\f\xf0d\xddY \x00\x00\u07d4\xaf\xa6\x94n\xff\xd5\xffS\x15O\x82\x01\x02S\xdfG\xae(\f\u0309j\xcb=\xf2~\x1f\x88\x00\x00\u07d4\xaf\xc8\xeb\u860b\xd4\x10Z\xccL\x01\x8eTj\x1e\x8f\x9cx\x88\x89\x1b\x1a\xe4\xd6\xe2\xefP\x00\x00\xe0\x94\xaf\xcc}\xbb\x83V\xd8B\xd4:\xe7\xe2<\x84\"\xb0\"\xa3\b\x03\x8a\x06o\xfc\xbf\xd5\xe5\xa3\x00\x00\x00\u07d4\xaf\xd0\x19\xff6\xa0\x91U4ki\x97H\x15\xa1\xc9\x12\xc9\n\xa4\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\xaf\xda\xc5\xc1\xcbV\xe2E\xbfp3\x00f\xa8\x17\uabecL\u0449\x01\x15\x8eF\t\x13\xd0\x00\x00\u07d4\xaf\xdd\x1bxab\xb81~ \xf0\xe9y\xf4\xb2\xceHmv]\x89\x01\x15\x8eF\t\x13\xd0\x00\x00\u07d4\xaf\xf1\x04Z\xdf'\xa1\xaa2\x94a\xb2M\xe1\xba\u950ai\x8b\x89\x01\u03c4\xa3\n\n\f\x00\x00\u07d4\xaf\xf1\a\x96\v~\xc3N\u0590\xb6e\x02M`\x83\x8c\x19\x0fp\x89\x1b\x1a\xe4\xd6\xe2\xefP\x00\x00\u07d4\xaf\xf1\x1c\xcfi\x93\x04\xd5\xf5\x86*\xf8`\x83E\x1c&\xe7\x9a\xe5\x89l]\xb2\xa4\xd8\x15\xdc\x00\x00\u07d4\xaf\xf1at\nm\x90\x9f\xe9\x9cY\xa9\xb7yE\xc9\x1c\xc9\x14H\x89\x03@\xaa\xd2\x1b;p\x00\x00\xe0\x94\xaf\xfc\x99\xd5\ubd28O\xe7x\x8d\x97\xdc\xe2t\xb08$\x048\x8a\x01\x0f\f\xf0d\xddY \x00\x00\u07d4\xaf\xfe\xa0G7\"\xcb\u007f\x0e\x0e\x86\xb9\xe1\x18\x83\xbfB\x8d\x8dT\x89i*\xe8\x89p\x81\xd0\x00\x00\xe0\x94\xb0\t\x96\xb0Vn\xcb>rC\xb8\"y\x88\u0733R\xc2\x18\x99\x8a\x02\x8a\x85t%Fo\x80\x00\x00\u07d4\xb0\x1e8\x9b(\xa3\x1d\x8eI\x95\xbd\xd7\xd7\xc8\x1b\xee\xab\x1eA\x19\x8965\u026d\xc5\u07a0\x00\x00\u07d4\xb0-\x06(s3EE\u03a2\x92\x18\xe4\x05w`Y\x0ft#\x89\xac\xb6\xa1\xc7\xd9:\x88\x00\x00\u07d4\xb0/\xa2\x93\x87\xec\x12\xe3\u007fi\"\xacL\xe9\x8c[\t\xe0\xb0\x0f\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\xb06\x91k\xda\u03d4\xb6\x9eZ\x8ae`)u\xeb\x02a\x04\u0749\x01\x15\x8eF\t\x13\xd0\x00\x00\xe0\x94\xb0A1\x0f\xe9\xee\u0586L\xed\u053e\xe5\x8d\xf8\x8e\xb4\xed<\xac\x8a\x02\x1e\x19\xe0\u027a\xb2@\x00\x00\u07d4\xb0U\xafL\xad\xfc\xfd\xb4%\xcfe\xbad1\a\x8f\a\xec\u056b\x89\x05k\xc7^-c\x10\x00\x00\xe0\x94\xb0W\x11S\xdb\x1cN\u05ec\xae\xfe\x13\xec\xdf\xdbr\xe7\xe4\xf0j\x8a\x11\f\xffyj\xc1\x95 \x00\x00\u07d4\xb0n\xab\t\xa6\x10\u01a5=V\xa9F\xb2\xc44\x87\xac\x1d[-\x8965\u026d\xc5\u07a0\x00\x00\u07d4\xb0rI\xe0U\x04J\x91U5\x9a@)7\xbb\xd9T\xfeH\xb6\x89\x05k\xc7^-c\x10\x00\x00\xe0\x94\xb0v\x182\x8a\x90\x13\a\xa1\xb7\xa0\xd0X\xfc\xd5xn\x9er\xfe\x8a\x06gI]JC0\xce\x00\x00\u07d4\xb0y\xbbM\x98f\x14:m\xa7*\xe7\xac\x00\"\x06)\x811\\\x89)3\x1eeX\xf0\xe0\x00\x00\u07d4\xb0{\xcc\bZ\xb3\xf7)\xf2D\x00Ah7\xb6\x996\xba\x88s\x89lm\x84\xbc\xcd\xd9\xce\x00\x00\u07d4\xb0{\xcf\x1c\xc5\xd4F.Q$\xc9e\xec\xf0\xd7\r\xc2z\xcau\x89V\xbcu\xe2\xd61\x00\x00\x00\u07d4\xb0|\xb9\xc1$\x05\xb7\x11\x80uC\u0113De\xf8\u007f\x98\xbd-\x89lk\x93[\x8b\xbd@\x00\x00\xe0\x94\xb0\u007f\u07af\xf9\x1dD`\xfel\xd0\u8870\xbd\x8d\"\xa6.\x87\x8a\x01\x1d%)\xf3SZ\xb0\x00\x00\xe0\x94\xb0\x9f\xe6\xd44\x9b\x99\xbc7\x93\x80T\x02-T\xfc\xa3f\xf7\xaf\x8a*Z\x05\x8f\u0095\xed\x00\x00\x00\xe0\x94\xb0\xaa\x00\x95\f\x0e\x81\xfa2\x10\x17>r\x9a\xaf\x16:'\xcdq\x8a\bxg\x83&\xea\xc9\x00\x00\x00\u07d4\xb0\xacN\xfff\x80\xee\x14\x16\x9c\xda\xdb\xff\xdb0\x80Om%\xf5\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\xb0\xb3j\xf9\xae\xee\u07d7\xb6\xb0\"\x80\xf1\x14\xf19\x84\xea2`\x895e\x9e\xf9?\x0f\xc4\x00\x00\u07d4\xb0\xb7y\xb9K\xfa<.\x1fX{\u031c~!x\x92\"7\x8f\x89T\x06\x923\xbf\u007fx\x00\x00\u07d4\xb0\xba\xeb0\xe3\x13wlLm$t\x02\xbaAg\xaf\u0361\u0309j\xcb=\xf2~\x1f\x88\x00\x00\u07d4\xb0\xbb)\xa8a\xea\x1dBME\xac\u053f\u0112\xfb\x8e\xd8\t\xb7\x89\x04V9\x18$O@\x00\x00\xe0\x94\xb0\xc1\xb1w\xa2 \xe4\x1f|t\xd0|\u0785i\xc2\x1cu\xc2\xf9\x8a\x01/\x93\x9c\x99\xed\xab\x80\x00\x00\u07d4\xb0\xc7\xceL\r\xc3\u00bb\xb9\x9c\xc1\x85{\x8aE_a\x17\x11\u0389\xd8\xd7&\xb7\x17z\x80\x00\x00\u07d4\xb0\xce\xf8\xe8\xfb\x89\x84\xa6\x01\x9f\x01\xc6y\xf2r\xbb\xe6\x8f\\w\x89\b=lz\xabc`\x00\x00\xe0\x94\xb0\xd3+\xd7\xe4\u6577\xb0\x1a\xa3\xd0Ao\x80U}\xba\x99\x03\x8a\x03s\x9f\xf0\xf6\xe6\x130\x00\x00\xe0\x94\xb0\xd3\u0247+\x85\x05n\xa0\xc0\xe6\xd1\xec\xf7\xa7~<\u6ac5\x8a\x01\x0f\b\xed\xa8\xe5U\t\x80\x00\u07d4\xb0\xe4i\u0206Y8\x15\xb3IV8Y]\xae\xf0f_\xaeb\x89i*\xe8\x89p\x81\xd0\x00\x00\u07d4\xb0\xe7`\xbb\a\xc0\x81wsE\xe0W\x8e\x8b\u0218\"mN;\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\xb1\x040\x04\xec\x19A\xa8\xcfO+\x00\xb1W\x00\u076co\xf1~\x8965\u026d\xc5\u07a0\x00\x00\u07d4\xb1\x05\xdd=\x98|\xff\xd8\x13\xe9\xc8P\n\x80\xa1\xad%}V\u0189lj\xccg\u05f1\xd4\x00\x00\u07d4\xb1\x0f\u04a6G\x10/\x88\x1ft\xc9\xfb\xc3}\xa62\x94\x9f#u\x89\x02+\x1c\x8c\x12'\xa0\x00\x00\xe0\x94\xb1\x15\xee:\xb7d\x1e\x1a\xa6\xd0\x00\xe4\x1b\xfc\x1e\xc7!\f/2\x8a\x02\xc0\xbb=\xd3\fN \x00\x00\u07d4\xb1\x17\x8a\xd4s\x83\xc3\x1c\x814\xa1\x94\x1c\xbc\xd4t\xd0bD\xe2\x8965\u026d\xc5\u07a0\x00\x00\xe0\x94\xb1\x17\x95\x89\u1779\xd4\x15W\xbb\xec\x1c\xb2L\xcc-\xec\x1c\u007f\x8a\x15-\x02\xc7\xe1J\xf6\x80\x00\x00\u07d4\xb1\x19\u76a9\xb9\x16Re\x81\xcb\xf5!\xefGJ\xe8M\xcf\xf4\x89O\xba\x10\x01\xe5\xbe\xfe\x00\x00\u07d4\xb1\x1f\xa7\xfb'\n\xbc\xdfZ.\xab\x95\xaa0\u013566\uffc9+^:\xf1k\x18\x80\x00\x00\u07d4\xb1$\xbc\xb6\xff\xa40\xfc\xae.\x86\xb4_'\xe3\xf2\x1e\x81\xee\b\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\xb1)\xa5\xcbq\x05\xfe\x81\v\u0615\xdcr\x06\xa9\x91\xa4TT\x88\x89\x01\xa0Ui\r\x9d\xb8\x00\x00\xe0\x94\xb1.\xd0{\x8a8\xadU\x066?\xc0z\vmy\x996\xbd\xaf\x8a\x02\x1e\x19\xe0\u027a\xb2@\x00\x00\u07d4\xb14\xc0\x049\x1a\xb4\x99(x3zQ\xec$/B(WB\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\xb1?\x93\xaf0\xe8\xd7fs\x81\xb2\xb9[\xc1\xa6\x99\xd5\xe3\xe1)\x89\x16\u012b\xbe\xbe\xa0\x10\x00\x00\u07d4\xb1E\x92\x85\x86>\xa2\xdb7Y\xe5F\u03b3\xfb7a\xf5\x90\x9c\x89<\xd7*\x89@\x87\xe0\x80\x00\u07d4\xb1F\xa0\xb9%U<\xf0o\xca\xf5J\x1bM\xfe\xa6!)\aW\x89lnY\xe6|xT\x00\x00\xe0\x94\xb1Jz\xaa\x8fI\xf2\xfb\x9a\x81\x02\u05bb\xe4\u010a\xe7\xc0o\xb2\x8a\x01\xb1\xaeMn.\xf5\x00\x00\x00\u07d4\xb1K\xbe\xffpr\tu\xdca\x91\xb2\xa4O\xf4\x9f&r\x87<\x89\a\xc0\x86\x0eZ\x80\xdc\x00\x00\xe0\x94\xb1L\xc8\xde3\xd63\x826S\x9aH\x90 \xceFU\xa3+\u018a\x01\xb1\xaeMn.\xf5\x00\x00\x00\u07d4\xb1M\xdb\x03\x86\xfb`c\x98\xb8\xccGVZ\xfa\xe0\x0f\xf1\xd6j\x89\xa1*\xff\b>f\xf0\x00\x00\u07d4\xb1S\xf8(\xdd\amJ|\x1c%t\xbb-\xee\x1aD\xa3\x18\xa8\x89\x15\xaf\x1dx\xb5\x8c@\x00\x00\u07d4\xb1T\x0e\x94\xcf\xf3F\\\xc3\u0447\xe7\xc8\u3f6f\x98FY\u2262\x15\xe4C\x90\xe33\x00\x00\u07d4\xb1X\xdbC\xfab\xd3\x0ee\xf3\u041b\xf7\x81\u01f6sr\uba89l]\xb2\xa4\xd8\x15\xdc\x00\x00\u07d4\xb1ar_\xdc\xed\xd1yR\xd5{#\xef([~K\x11i\xe8\x89\x02\xb6\xdf\xed6d\x95\x80\x00\u07d4\xb1dy\xba\x8e}\xf8\xf6>\x1b\x95\xd1I\u0345)\xd75\xc2\u0689-\xe3:j\xac2T\x80\x00\u07d4\xb1f\xe3}.P\x1a\xe7<\x84\x14+_\xfbZ\xa6U\xddZ\x99\x89l]\xb2\xa4\xd8\x15\xdc\x00\x00\u07d4\xb1\x83\xeb\xeeO\xcbB\xc2 \xe4wt\xf5\x9dlT\xd5\xe3*\xb1\x89V\xf7\xa9\xc3<\x04\xd1\x00\x00\u07d4\xb1\x88\a\x84D\x02~8g\x98\xa8\xaehi\x89\x19\xd5\xcc#\r\x89\x0e~\xeb\xa3A\vt\x00\x00\u07d4\xb1\x89j7\xe5\u0602Z-\x01vZ\xe5\xdeb\x99w\u0783R\x89\n\u05ce\xbcZ\xc6 \x00\x00\u07d4\xb1\x8eg\xa5\x05\n\x1d\xc9\xfb\x19\t\x19\xa3=\xa88\xefDP\x14\x89\x01\x15\x8eF\t\x13\xd0\x00\x00\u07d4\xb1\xa2\xb4:t3\xdd\x15\v\xb8\"'\xedQ\x9c\u05b1B\u04c2\x89\x94mb\rtK\x88\x00\x00\u07d4\xb1\xc0\u040b6\xe1\x84\xf9\x95*@7\xe3\xe5:f}\a\nN\x8965\u026d\xc5\u07a0\x00\x00\u07d4\xb1\xc3(\xfb\x98\xf2\xf1\x9a\xb6do\n|\x8cVo\xdaZ\x85@\x89\x87\x86x2n\xac\x90\x00\x00\xe0\x94\xb1\xc7Qxi9\xbb\xa0\xd6q\xa6w\xa1X\u01ab\xe7&^F\x8a\x02\x1e\x19\xe0\u027a\xb2@\x00\x00\xe0\x94\xb1\xcdK\xdf\xd1\x04H\x9a\x02n\u025dYs\a\xa0By\xf1s\x8a\x04<3\xc1\x93ud\x80\x00\x00\u07d4\xb1\u03d4\xf8\t\x15\x05\x05_\x01\n\xb4\xba\u0196\xe0\xca\x0fg\xa1\x89U\xa6\xe7\x9c\xcd\x1d0\x00\x00\u07d4\xb1\u05b0\x1b\x94\xd8T\xfe\x8b7J\xa6^\x89\\\xf2*\xa2V\x0e\x892\xf5\x1e\u06ea\xa30\x00\x00\xe0\x94\xb1\u06e5%\v\xa9bWU$n\x06yg\xf2\xad/\a\x91\u078a\x10\xf0\xcf\x06M\u0552\x00\x00\x00\u07d4\xb1\xe2\u0755\xe3\x9a\xe9w\\U\xae\xb1?\x12\xc2\xfa#0S\xba\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\xb1\xe6\xe8\x10\xc2J\xb0H\x8d\xe9\xe0\x1eWH7\x82\x9f|w\u0409\x15\xaf\x1dx\xb5\x8c@\x00\x00\u07d4\xb1\xe9\xc5\xf1\xd2\x1eauzk.\xe7Y\x13\xfcZ\x1aA\x01\u00c9lk\x93[\x8b\xbd@\x00\x00\u07d4\xb2\x03\u049elV\xb9&\x99\u0139-\x1fo\x84d\x8d\xc4\u03fc\x89\x15\xaf\x1dx\xb5\x8c@\x00\x00\u07d4\xb2\x16\xdcY\xe2|=ry\xf5\xcd[\xb2\xbe\u03f2`n\x14\u0649\x15\xaf\x1dx\xb5\x8c@\x00\x00\u07d4\xb2\x1byy\xbf|\\\xa0\x1f\xa8-\xd6@\xb4\x1c9\xe6\u01bcu\x89lj\xccg\u05f1\xd4\x00\x00\u07d4\xb2#\xbf\x1f\xbf\x80H\\\xa2\xb5V}\x98\xdb{\xc3SM\xd6i\x89\xd8\xd7&\xb7\x17z\x80\x00\x00\u07d4\xb2-PU\xd9b15\x96\x1ej\xbd'<\x90\xde\xea\x16\xa3\xe7\x89K\xe4\xe7&{j\xe0\x00\x00\u07d4\xb2-\xad\xd7\xe1\xe0R2\xa927\xba\xed\x98\xe0\u07d2\xb1\x86\x9e\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\xb24\x03_uDF<\xe1\xe2+\xc5S\x06F\x84\xc5\x13\xcdQ\x89\r\x89\xfa=\u010d\xcf\x00\x00\u07d4\xb2G\u03dcr\xecH*\xf3\xea\xa7Ye\x8fy=g\nW\f\x891p\x8a\xe0\x04T@\x00\x00\u07d4\xb2ghA\xee\x9f-1\xc1r\xe8#\x03\xb0\xfe\x9b\xbf\x9f\x1e\t\x89\n\u05ce\xbcZ\xc6 \x00\x00\u07d4\xb2y\xc7\xd3U\u0088\x03\x92\xaa\u046a!\xee\x86|;5\a\u07c9D[\xe3\xf2\uf1d4\x00\x00\u07d4\xb2|\x1a$ L\x1e\x11\x8du\x14\x9d\xd1\t1\x1e\a\xc0s\xab\x89\xa8\r$g~\xfe\xf0\x00\x00\u07d4\xb2\x81\x81\xa4X\xa4@\xf1\u01bb\x1d\xe8@\x02\x81\xa3\x14\x8fL5\x89\x14b\fW\xdd\xda\xe0\x00\x00\xe0\x94\xb2\x82E\x03|\xb1\x92\xf7W\x85\u02c6\xcb\xfe|\x93\r\xa2X\xb0\x8a\x03c\\\x9a\xdc]\xea\x00\x00\x00\u07d4\xb2\x87\xf7\xf8\xd8\u00c7,\x1bXk\xcd}\n\xed\xbf~s'2\x89\x01\x15\x8eF\t\x13\xd0\x00\x00\u07d4\xb2\x8b\xb3\x9f4fQ|\xd4o\x97\x9c\xf5\x96S\xee}\x8f\x15.\x89\x18e\x01'\xcc=\xc8\x00\x00\u07d4\xb2\x8d\xbf\xc6I\x98\x94\xf7:q\xfa\xa0\n\xbe\x0fK\xc9\u045f*\x89\x05k\xc7^-c\x10\x00\x00\u07d4\xb2\x96\x8f}5\xf2\b\x87\x161\xc6h{?=\xae\xab\xc6al\x89\bu\xc4\u007f(\x9fv\x00\x00\u07d4\xb2\x9f[|\x190\xd9\xf9z\x11^\x06pf\xf0\xb5M\xb4K;\x8965\u026d\xc5\u07a0\x00\x00\u07d4\xb2\xa1D\xb1\xeag\xb9Q\x0f\"g\xf9\xda9\xd3\xf9=\xe2fB\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\xb2\xa2\xc2\x11\x16\x12\xfb\x8b\xbb\x8e}\xd97\x8dg\xf1\xa3\x84\xf0P\x89\x01\x15\x8eF\t\x13\xd0\x00\x00\xe0\x94\xb2\xa4\x98\xf0;\xd7\x17\x8b\u0627\x89\xa0\x0fR7\xafy\xa3\xe3\xf8\x8a\x04\x1b\xad\x15^e\x12 \x00\x00\u07d4\xb2\xaa/\x1f\x8e\x93\xe7\x97\x13\xd9,\xea\x9f\xfc\xe9\xa4\n\xf9\xc8-\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\xb2\xb5\x16\xfd\u045e\u007f8d\xb6\xd2\xcf\x1b%*AV\xf1\xb0;\x89\x02\xe9\x83\xc7a\x15\xfc\x00\x00\u07d4\xb2\xb7\u0374\xffKa\u0577\xce\v\"p\xbb\xb5&\x97C\xec\x04\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\xb2\xbd\xbe\u07d5\x90\x84v\xd7\x14\x8a7\f\u0193t6(\x05\u007f\x89\xd8\xd7&\xb7\x17z\x80\x00\x00\u07d4\xb2\xbf\xaaX\xb5\x19l\\\xb7\xf8\x9d\xe1_G\x9d\x188\xdeq=\x89\x01#n\xfc\xbc\xbb4\x00\x00\u07d4\xb2\xc5>\xfa3\xfeJ:\x1a\x80 \\s\xec;\x1d\xbc\xad\x06\x02\x89h\x01\u06b3Y\x18\x93\x80\x00\xe0\x94\xb2\xd06\x05\x15\xf1}\xab\xa9\x0f\u02ec\x82\x05\xd5i\xb9\x15\u05ac\x8a\x01EB\xba\x12\xa37\xc0\x00\x00\xe0\x94\xb2\xd1\xe9\x9a\xf9\x121\x85\x8epe\xdd\x19\x183\r\xc4\xc7G\u054a\x03\x89O\x0eo\x9b\x9fp\x00\x00\u07d4\xb2\u066b\x96d\xbc\xf6\xdf <4o\u0192\xfd\x9c\xba\xb9 ^\x89\x17\xbex\x97`e\x18\x00\x00\u07d4\xb2\u0777\x86\xd3yN'\x01\x87\xd0E\x1a\xd6\u0237\x9e\x0e\x87E\x89\x15\xaf\x1dx\xb5\x8c@\x00\x00\u07d4\xb2\xe0\x85\xfd\xdd\x14h\xba\aA['NsN\x11#\u007f\xb2\xa9\x89\x05k\xc7^-c\x10\x00\x00\u07d4\xb2\xe9\xd7k\xf5\x0f\xc3k\xf7\u04d4Kc\xe9\u0288\x9bi\x99h\x89\x902\xeab\xb7K\x10\x00\x00\xe0\x94\xb2\xf9\xc9r\xc1\xe9swU\xb3\xff\x1b0\x88s\x83\x969[&\x8a\x04<3\xc1\x93ud\x80\x00\x00\xe0\x94\xb2\xfc\x84\xa3\xe5\nP\xaf\x02\xf9M\xa08>\u055fq\xff\x01\u05ca\x06ZM\xa2]0\x16\xc0\x00\x00\u07d4\xb3\x05\v\xef\xf9\xde3\xc8\x0e\x1f\xa1R%\xe2\x8f,A:\xe3\x13\x89%\xf2s\x93=\xb5p\x00\x00\u07d4\xb3\x11\x96qJH\xdf\xf7&\xea\x943\xcd)\x12\xf1\xa4\x14\xb3\xb3\x89\x91Hx\xa8\xc0^\xe0\x00\x00\xe0\x94\xb3\x14[tPm\x1a\x8d\x04|\xdc\xdcU9*{SPy\x9a\x8a\x1bb)t\x1c\r=]\x80\x00\u07d4\xb3 \x83H6\xd1\xdb\xfd\xa9\xe7\xa3\x18M\x1a\xd1\xfdC \xcc\xc0\x8965\u026d\xc5\u07a0\x00\x00\u07d4\xb3#\u073f.\xdd\xc58.\u4efb \x1c\xa3\x93\x1b\xe8\xb48\x89lk\x93[\x8b\xbd@\x00\x00\xe0\x94\xb3$\x00\xfd\x13\xc5P\t\x17\xcb\x03{)\xfe\"\xe7\xd5\"\x8f-\x8a\bxg\x83&\xea\xc9\x00\x00\x00\u07d4\xb3%gL\x01\xe3\xf7)\rR&3\x9f\xbe\xacg\xd2!'\x9f\x89\x97\xc9\xceL\xf6\xd5\xc0\x00\x00\u07d4\xb3(%\xd5\xf3\xdb$\x9e\xf4\xe8\\\xc4\xf31S\x95\x89v\u8f09\x1b-\xf9\xd2\x19\xf5y\x80\x00\u07d4\xb3*\xf3\xd3\xe8\xd0u4I&To.2\x88{\xf9;\x16\xbd\x89\n\u05ce\xbcZ\xc6 \x00\x00\u07d4\xb3/\x1c&\x89\xa5\xcey\xf1\xbc\x97\v1XO\x1b\xcf\"\x83\xe7\x89\x01\x15\x8eF\t\x13\xd0\x00\x00\u07d4\xb3<\x03#\xfb\xf9\xc2l\x1d\x8a\xc4N\xf7C\x91\u0400F\x96\u0689\x01\x15\x8eF\t\x13\xd0\x00\x00\xe0\x94\xb3O\x04\xb8\xdbe\xbb\xa9\xc2n\xfcL\xe6\xef\xc5\x04\x81\xf3\xd6]\x8a\x04<3\xc1\x93ud\x80\x00\x00\u07d4\xb3U}9\xb5A\x1b\x84D__T\xf3\x8fb\xd2qM\x00\x87\x89 \x86\xac5\x10R`\x00\x00\xe0\x94\xb3X\xe9|p\xb6\x05\xb1\xd7\xd7)\u07f6@\xb4<^\xaf\xd1\xe7\x8a\x04<3\xc1\x93ud\x80\x00\x00\u0794\xb3^\x8a\x1c\r\xac~\x0ef\u06ecsjY*\xbdD\x01%a\x88\xcf\xceU\xaa\x12\xb3\x00\x00\xe0\x94\xb3fx\x94\xb7\x86<\x06\x8a\xd3D\x87?\xcf\xf4\xb5g\x1e\x06\x89\x8a\x04<3\xc1\x93ud\x80\x00\x00\u07d4\xb3qw1\xda\xd6Q2\xday-\x87`0\xe4j\xc2'\xbb\x8a\x8965\u026d\xc5\u07a0\x00\x00\u07d4\xb3s\x1b\x04l\x8a\u0195\xa1'\xfdy\u0425\xd5\xfaj\xe6\xd1.\x89lO\xd1\xee$nx\x00\x00\u07d4\xb3|+\x9fPc{\xec\xe0\u0295\x92\b\xae\xfe\xe6F;\xa7 \x89\x15\xaf\x1dx\xb5\x8c@\x00\x00\u07d4\xb3\x88\xb5\xdf\xec\xd2\xc5\u4d56W|d%V\xdb\xfe'xU\x89\x01\x15\x8eF\t\x13\xd0\x00\x00\u07d4\xb3\x8cNS{]\xf90\xd6Zt\xd0C\x83\x1dkH[\xbd\xe4\x89\x15\xaf\x1dx\xb5\x8c@\x00\x00\xe0\x94\xb3\x919Wa\x94\xa0\x86a\x95\x15\x1f3\xf2\x14\n\xd1\u0306\u03ca\x15-\x02\xc7\xe1J\xf6\x80\x00\x00\u07d4\xb3\x9fL\x00\xb2c\f\xab}\xb7)^\xf4=G\xd5\x01\xe1\u007f\u05c9\xd8\xd7&\xb7\x17z\x80\x00\x00\u07d4\xb3\xa6K\x11vrOT\t\xe1AJ5#f\x1b\xae\xe7KJ\x89\x01ch\xffO\xf9\xc1\x00\x00\u07d4\xb3\xa6\xbdA\xf9\xd9\xc3 \x1e\x05\v\x87\x19\x8f\xbd\xa3\x994\"\x10\x89\xc4a\xe1\xdd\x10)\xb5\x80\x00\u07d4\xb3\xa8\xc2\xcb}5\x8eW9\x94\x1d\x94[\xa9\x04Z\x02:\x8b\xbb\x8965\u026d\xc5\u07a0\x00\x00\u07d4\xb3\xaeT\xfb\xa0\x9d>\xe1\u05bd\xd1\xe9W\x929\x19\x02L5\xfa\x89\x03\x8d,\xeee\xb2*\x80\x00\u07d4\xb3\xb7\xf4\x93\xb4J,\x8d\x80\xecx\xb1\xcd\xc7Ze+s\xb0l\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\xb3\xc2(s\x1d\x18m-\xed[_\xbe\x00Lfl\x8eF\x9b\x86\x89\x01\x92t\xb2Y\xf6T\x00\x00\u07d4\xb3\xc2``\x9b\x9d\xf4\t^l]\xff9\x8e\xeb^-\xf4\x99\x85\x89\r\xc5_\xdb\x17d{\x00\x00\u07d4\xb3\xc6[\x84Z\xbal\xd8\x16\xfb\xaa\xe9\x83\xe0\xe4l\x82\xaa\x86\"\x8965\u026d\xc5\u07a0\x00\x00\u07d4\xb3\xc9H\x11\xe7\x17[\x14\x8b(\x1c\x1a\x84[\xfc\x9b\xb6\xfb\xc1\x15\x89\n\u05ce\xbcZ\xc6 \x00\x00\u07d4\xb3\xe2\x0e\xb4\xde\x18\xbd\x06\x02!h\x98\x94\xbe\u5bb2SQ\xee\x89\x03\xfc\x80\xcc\xe5\x16Y\x80\x00\u07d4\xb3\xe3\xc49\x06\x98\x80\x15f\x00\u0089.D\x8dA6\xc9-\x9b\x89.\x14\x1e\xa0\x81\xca\b\x00\x00\xe0\x94\xb3\xf8*\x87\xe5\x9a9\xd0\u0480\x8f\aQ\xebr\xc22\x9c\xdc\u014a\x01\x0f\f\xf0d\xddY \x00\x00\u07d4\xb3\xfc\x1dh\x81\xab\xfc\xb8\xbe\xcc\v\xb0!\xb8\xb7;r3\u0751\x89\x02\xb5\xe3\xaf\x16\xb1\x88\x00\x00\u07d4\xb4\x05\x94\xc4\xf3fN\xf8I\u0326\"{\x8a%\xaai\t%\xee\x89\xd8\xd7&\xb7\x17z\x80\x00\x00\u07d4\xb4\x1e\xaf]Q\xa5\xba\x1b\xa3\x9b\xb4\x18\u06f5O\xabu\x0e\xfb\x1f\x8965\u026d\xc5\u07a0\x00\x00\u07d4\xb4$\u058d\x9d\r\x00\xce\xc1\x93\x8c\x85N\x15\xff\xb8\x80\xba\x01p\x89\n\u05ce\xbcZ\xc6 \x00\x00\u07d4\xb4%bs\x96+\xf61\xd0\x14U\\\xc1\xda\r\xcc1akI\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\xb40g\xfep\u0675Ys\xbaX\xdcd\xdd\u007f1\x1eUBY\x89\n\u05ce\xbcZ\xc6 \x00\x00\u07d4\xb46W\xa5\x0e\xec\xbc0w\xe0\x05\xd8\xf8\xd9O7xv\xba\u0509\x01\xec\x1b:\x1f\xf7Z\x00\x00\u07d4\xb4<'\xf7\xa0\xa1\"\bK\x98\xf4\x83\x92%A\u0203l\xee,\x89&\u009eG\u0104L\x00\x00\xe0\x94\xb4A5v\x86\x9c\b\xf9Q*\xd3\x11\xfe\x92Y\x88\xa5-4\x14\x8a\x02\x1e\x19\xe0\u027a\xb2@\x00\x00\u07d4\xb4F\x05U$q\xa6\xee\xe4\u06abq\xff;\xb4\x13&\xd4s\xe0\x89-~=Q\xbaS\xd0\x00\x00\u07d4\xb4GW\x1d\xac\xbb>\u02f6\xd1\xcf\v\f\x8f88\xe5#$\xe2\x89\x01\xa3\x18f\u007f\xb4\x05\x80\x00\u07d4\xb4G\x83\xc8\xe5{H\a\x93\xcb\u059aE\xd9\f{O\fH\xac\x89\x01\x15\x8eF\t\x13\xd0\x00\x00\u07d4\xb4H\x15\xa0\xf2\x8eV\x9d\x0e\x92\x1aJ\u078f\xb2d%&Iz\x89\x03\x027\x9b\xf2\xca.\x00\x00\u07d4\xb4Im\xdb'y\x9a\"$W\xd79y\x11g(\u8844[\x89\x8d\x81\x9e\xa6_\xa6/\x80\x00\xe0\x94\xb4RL\x95\xa7\x86\x0e!\x84\x02\x96\xa6\x16$@\x19B\x1cJ\xba\x8a\x01\xb1\xaeMn.\xf5\x00\x00\x00\u07d4\xb4\\\xca\r6\x82fbh<\xf7\u0432\xfd\xach\u007f\x02\xd0\u010965\u026d\xc5\u07a0\x00\x00\u0794\xb4d@\u01d7\xa5V\xe0L}\x91\x04f\x04\x91\xf9k\xb0v\xbf\x88\xce\xc7o\x0eqR\x00\x00\u07d4\xb4j\u0386^,P\xeaF\x98\xd2\x16\xabE]\xffZ\x11\xcdr\x8965\u026d\xc5\u07a0\x00\x00\u07d4\xb4m\x11\x82\xe5\xaa\xca\xff\r&\xb2\xfc\xf7/<\x9f\xfb\xcd\xd9}\x89\xaa*`<\xdd\u007f,\x00\x00\u07d4\xb4\x89!\xc9h}U\x10tE\x84\x93n\x88\x86\xbd\xbf-\xf6\x9b\x8965\u026d\xc5\u07a0\x00\x00\u07d4\xb4\x98\xbb\x0fR\x00\x05\xb6!jD%\xb7Z\xa9\xad\xc5-b+\x89\xd8\xd7&\xb7\x17z\x80\x00\x00\xe0\x94\xb4\xb1\x1d\x10\x9f`\x8f\xa8\xed\xd3\xfe\xa9\xf8\xc3\x15d\x9a\xeb=\x11\x8a\x01\x0f\f\xf0d\xddY \x00\x00\u07d4\xb4\xb1K\xf4TU\u042b\b\x035\x8bu$\xa7+\xe1\xa2\x04[\x89\x1b\x1a\xe4\xd6\xe2\xefP\x00\x00\u07d4\xb4\xb1\x85\xd9C\xee+Xc\x1e3\xdf\xf5\xafhT\xc1y\x93\xac\x8965\u026d\xc5\u07a0\x00\x00\u07d4\xb4\xbf$\u02c3hk\xc4i\x86\x9f\xef\xb0D\xb9\tqi\x93\xe2\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\xb4\xc2\x00@\xcc\u0661\xa3(=\xa4\u0522\xf3e\x82\bC\xd7\xe2\x8965\u026d\xc5\u07a0\x00\x00\u07d4\xb4\xc8\x17\x0f{*\xb56\xd1\u0662[\xdd :\xe1(\x8d\xc3\u0549\n\u05ce\xbcZ\xc6 \x00\x00\u07d4\xb4\xd8/.i\x94?}\xe0\xf5\xf7t8y@o\xac.\x9c\xec\x89\x02+\x1c\x8c\x12'\xa0\x00\x00\xe0\x94\xb4\xddF\f\xd0\x16rZd\xb2.\xa4\xf8\xe0n\x06gN\x03>\x8a\x01#\x1b\xb8t\x85G\xa8\x00\x00\u07d4\xb4\xddT\x99\xda\xeb%\a\xfb-\xe1\"\x97s\x1dLr\xb1k\xb0\x89\x01\x15\x8eF\t\x13\xd0\x00\x00\xe0\x94\xb5\x04l\xb3\xdc\x1d\xed\xbd6E\x14\xa2\x84\x8eD\xc1\xdeN\xd1G\x8a\x03{}\x9b\xb8 @^\x00\x00\xe0\x94\xb5\b\xf9\x87\xb2\xde4\xaeL\xf1\x93\u0785\xbf\xf6\x13\x89b\x1f\x88\x8a\x01EB\xba\x12\xa37\xc0\x00\x00\u07d4\xb5\tU\xaan4\x15q\x98f\b\xbd\u0211\xc2\x13\x9fT\f\u07c9j\xcb=\xf2~\x1f\x88\x00\x00\u07d4\xb5\f\x14\x9a\x19\x06\xfa\xd2xo\xfb\x13Z\xabP\x177\xe9\xe5o\x89\x15\b\x94\xe8I\xb3\x90\x00\x00\u07d4\xb5\f\x9fW\x89\xaeD\xe2\xdc\xe0\x17\xc7\x14\xca\xf0\f\x83\x00\x84\u0089\x15[\xd90\u007f\x9f\xe8\x00\x00\u07d4\xb5\x14\x88,\x97\x9b\xb6B\xa8\r\u04c7T\u0578\xc8)m\x9a\a\x893\xc5I\x901r\f\x00\x00\u07d4\xb5\x1d\u0734\xddN\x8a\xe6\xbe3m\xd9eIq\xd9\xfe\xc8kA\x89\x16\xd4d\xf8=\u2500\x00\u07d4\xb5\x1eU\x8e\xb5Q/\xbc\xfa\x81\xf8\u043d\x93\x8cy\xeb\xb5$+\x89&\u009eG\u0104L\x00\x00\u07d4\xb5#\xff\xf9t\x98q\xb3S\x88C\x887\xf7\xe6\xe0\u07a9\xcbk\x89lk\x93[\x8b\xbd@\x00\x00\xe0\x94\xb5-\xfbE\xde]t\xe3\xdf \x832\xbcW\x1c\x80\x9b\x8d\xcf2\x8a\x01EB\xba\x12\xa37\xc0\x00\x00\u07d4\xb55\xf8\u06c7\x9f\xc6\u007f\xecX\x82J\\\xbenT\x98\xab\xa6\x92\x89g\x8a\x93 b\xe4\x18\x00\x00\u07d4\xb57\xd3jp\xee\xb8\xd3\xe5\xc8\r\xe8\x15\"\\\x11X\u02d2\u0109QP\xae\x84\xa8\xcd\xf0\x00\x00\u07d4\xb5;\xcb\x17L%\x184\x8b\x81\x8a\xec\xe0 6E\x96Fk\xa3\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\xb5I>\xf1srDE\xcf4\\\x03]'\x9b\xa7Y\xf2\x8dQ\x89\x01\x15\x8eF\t\x13\xd0\x00\x00\u07d4\xb5S\xd2]kT!\xe8\x1c*\xd0^\v\x8b\xa7Q\xf8\xf0\x10\xe3\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\xb5Tt\xbaX\xf0\xf2\xf4\x0el\xba\xbe\xd4\xea\x17n\x01\x1f\xca\u0589j\xcb=\xf2~\x1f\x88\x00\x00\u07d4\xb5U\xd0\x0f\x91\x90\xcc6w\xae\xf3\x14\xac\xd7?\xdc99\x92Y\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\xb5W\xab\x949\xefP\xd27\xb5S\xf0%\b6JFj\\\x03\x89\n\u05ce\xbcZ\xc6 \x00\x00\u07d4\xb5jx\x00(\x03\x9c\x81\xca\xf3{gu\xc6 \u7195Gd\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\xb5j\u04ae\xc6\xc8\xc3\xf1\x9e\x15\x15\xbb\xb7\u0751(RV\xb69\x8965\u026d\xc5\u07a0\x00\x00\u07d4\xb5t\x13\x06\n\xf3\xf1N\xb4y\x06_\x1e\x9d\x19\xb3uz\xe8\u0309\x02+\x1c\x8c\x12'\xa0\x00\x00\u07d4\xb5uI\xbf\xbc\x9b\xdd\x18\xf76\xb2&P\xe4\x8as`\x1f\xa6\\\x89\x18-~L\xfd\xa08\x00\x00\xe0\x94\xb5w\xb6\xbe\xfa\x05N\x9c\x04\x04a\x85P\x94\xb0\x02\xd7\xf5{\u05ca\x18#\xf3\xcfb\x1d#@\x00\x00\u07d4\xb5{\x04\xfa#\xd1 ?\xae\x06\x1e\xacEB\xcb`\xf3\xa5v7\x89\nZ\xa8P\t\xe3\x9c\x00\x00\u07d4\xb5\x87\f\xe3B\xd43C36s\x03\x8bGd\xa4n\x92_>\x8965\u026d\xc5\u07a0\x00\x00\u07d4\xb5\x87\xb4J,\xa7\x9eK\xc1\u074b\xfd\xd4: qP\xf2\xe7\xe0\x89\",\x8e\xb3\xfff@\x00\x00\u07d4\xb5\x89gm\x15\xa0DH4B0\xd4\xff'\xc9^\xdf\x12,I\x8965\u026d\xc5\u07a0\x00\x00\u0794\xb5\x8bR\x86^\xa5]\x806\xf2\xfa\xb2`\x98\xb3R\u0283~\x18\x88\xfc\x93c\x92\x80\x1c\x00\x00\u07d4\xb5\x90k\n\u9881X\xe8\xacU\x0e9\xda\bn\xe3\x15v#\x89\n\u05ce\xbcZ\xc6 \x00\x00\u07d4\xb5\xa4g\x96\x85\xfa\x14\x19l.\x920\xc8\xc4\xe3;\xff\xbc\x10\xe2\x89K\xe4\xe7&{j\xe0\x00\x00\u07d4\xb5\xa5\x89\u075f@q\u06f6\xfb\xa8\x9b?]]\xae}\x96\xc1c\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\xb5\xa6\x06\xf4\xdd\u02f9G\x1e\xc6\u007fe\x8c\xaf+\x00\xees\x02^\x89\xeaun\xa9*\xfct\x00\x00\u07d4\xb5\xadQW\u0769!\xe6\xba\xfa\u0350\x86\xaes\xae\x1fa\x1d?\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\xb5\xad\xd1\u701f}\x03\x06\x9b\xfe\x88;\n\x93\"\x10\xbe\x87\x12\x8965\u026d\xc5\u07a0\x00\x00\u07d4\xb5\xba)\x91|x\xa1\xd9\xe5\xc5\xc7\x13fl\x1eA\x1d\u007fi:\x89\xa8\r$g~\xfe\xf0\x00\x00\u07d4\xb5\xc8\x16\xa8(<\xa4\xdfh\xa1\xa7=c\xbd\x80&\x04\x88\xdf\b\x89\n\u05ce\xbcZ\xc6 \x00\x00\u07d4\xb5\xca\xc5\xed\x03G}9\v\xb2g\xd4\xeb\xd4a\x01\xfb\xc2\xc3\u0689\n\xad\xec\x98?\xcf\xf4\x00\x00\u07d4\xb5\u037cA\x15@oR\u5a85\xd0\xfe\xa1p\u0497\x9c\u01fa\x89Hz\x9a0E9D\x00\x00\u0794\xb5\u0653M{)+\xcf`;(\x80t\x1e\xb7`(\x83\x83\xa0\x88\xe7\xc2Q\x85\x05\x06\x00\x00\u07d4\xb5\xddP\xa1]\xa3Ih\x89\nS\xb4\xf1?\xe1\xaf\b\x1b\xaa\xaa\x89\xd8\xd7&\xb7\x17z\x80\x00\x00\u07d4\xb5\xfa\x81\x84\xe4>\xd3\u0e2b\x91!da\xb3R\x8d\x84\xfd\t\x89\x91Hx\xa8\xc0^\xe0\x00\x00\u07d4\xb5\xfb~\xa2\xdd\xc1Y\x8bfz\x9dW\xdd9\xe8Z8\xf3]V\x89\x1b\x1a\xe4\xd6\xe2\xefP\x00\x00\u07d4\xb6\x00B\x97R\xf3\x99\xc8\r\a4tK\xae\n\x02.\xcag\u0189\x01\x15\x8eF\t\x13\xd0\x00\x00\u07d4\xb6\x00\xfe\xabJ\xa9lSu\x04\xd9`W\"1Ai,\x19:\x89\x15\xaf\x1dx\xb5\x8c@\x00\x00\u07d4\xb6\x04|\u07d3-\xb3\xe4\x04_Iv\x12#AS~\u0556\x1e\x89\x01\x15\x8eF\t\x13\xd0\x00\x00\u07d4\xb6\x15\xe9@\x14>\xb5\u007f\x87X\x93\xbc\x98\xa6\x1b=a\x8c\x1e\x8c\x89\x01\x15\x8eF\t\x13\xd0\x00\x00\xe0\x94\xb6\x1c4\xfc\xac\xdap\x1aZ\xa8p$Y\u07b0\u4b83\x8d\xf8\x8a\aiZ\x92\xc2\ro\xe0\x00\x00\xe0\x94\xb60d\xbd3U\xe6\xe0~-7p$\x12Z3wlJ\xfa\x8a\b7Z*\xbc\xca$@\x00\x00\u07d4\xb65\xa4\xbcq\xfb(\xfd\xd5\xd2\xc3\"\x98:V\u0084Bni\x89\t79SM(h\x00\x00\u07d4\xb6F\u07d8\xb4\x94BtkaR\\\x81\xa3\xb0K\xa3\x10bP\x89j\xcb=\xf2~\x1f\x88\x00\x00\u07d4\xb6YA\xd4LP\xd2Ffg\r6Gf\xe9\x91\xc0.\x11\u0089 \x86\xac5\x10R`\x00\x00\xe0\x94\xb6[\u05c0\xc7CA\x15\x16 'VR#\xf4NT\x98\xff\x8c\x8a\x04<0\xfb\b\x84\xa9l\x00\x00\u07d4\xb6d\x11\xe3\xa0-\xed\xb7&\xfay\x10}\xc9\v\xc1\xca\xe6MH\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\xb6fu\x14.1\x11\xa1\xc2\xea\x1e\xb2A\x9c\xfaB\xaa\xf7\xa24\x8965\u026d\xc5\u07a0\x00\x00\xe0\x94\xb6o\x92\x12K^c\x03XY\xe3\x90b\x88i\xdb\u07a9H^\x8a\x02\x15\xf85\xbcv\x9d\xa8\x00\x00\u07d4\xb6rsJ\xfc\xc2$\xe2\xe6\t\xfcQ\xd4\xf0Ys'D\xc9H\x89\x10\x04\xe2\xe4_\xb7\xee\x00\x00\xe0\x94\xb6w\x1b\v\xf3B\u007f\x9a\xe7\xa9>|.a\xeec\x94\x1f\xdb\b\x8a\x03\xfb&i)T\xbf\xc0\x00\x00\u07d4\xb6z\x80\xf1p\x19}\x96\xcd\xccJ\xb6\u02e6'\xb4\xaf\xa6\xe1,\x89\x82\x1a\xb0\xd4AI\x80\x00\x00\u07d4\xb6\x88\x99\xe7a\rL\x93\xa255\xbc\xc4H\x94[\xa1fo\x1c\x89\n\u05ce\xbcZ\xc6 \x00\x00\u07d4\xb6\xa8)3\xc9\xea\u06bd\x98\x1e]m`\xa6\x81\x8f\xf8\x06\xe3k\x89\x15\xaf\x1dx\xb5\x8c@\x00\x00\xe0\x94\xb6\xaa\u02cc\xb3\v\xab*\xe4\xa2BF&\xe6\xe1+\x02\xd0F\x05\x8a\x01\xb1\xaeMn.\xf5\x00\x00\x00\u07d4\xb6\xb3J&?\x10\xc3\xd2\xec\xeb\n\xccU\x9a{*\xb8\\\xe5e\x89\xd8\xd7&\xb7\x17z\x80\x00\x00\u07d4\xb6\xbf\xe1\xc3\xef\x94\xe1\x84o\xb9\xe3\xac\xfe\x9bP\xc3\xe9\x06\x923\x89lj\xccg\u05f1\xd4\x00\x00\u07d4\xb6\xcdt2\xd5\x16\x1b\xe7\x97h\xadE\xde>Dz\a\x98 c\x89\xd8\xd7&\xb7\x17z\x80\x00\x00\u07d4\xb6\xceM\xc5`\xfcs\xdci\xfbzb\xe3\x88\xdb~r\xeavO\x894]\xf1i\xe9\xa3X\x00\x00\u07d4\xb6\xde\u03c2\x96\x98\x19\xba\x02\xde)\xb9\xb5\x93\xf2\x1bd\xee\xda\x0f\x89(\x1d\x90\x1fO\xdd\x10\x00\x00\xe0\x94\xb6\xe6\xc3\"+ko\x9b\xe2\x87]*\x89\xf1'\xfbd\x10\x0f\xe2\x8a\x01\xb2\x1dS#\xcc0 \x00\x00\u07d4\xb6\xe8\xaf\xd9=\xfa\x9a\xf2\u007f9\xb4\xdf\x06\ag\x10\xbe\xe3\u07eb\x89\x01Z\xf1\u05cbX\xc4\x00\x00\xe0\x94\xb6\xf7\x8d\xa4\xf4\xd0A\xb3\xbc\x14\xbc[\xa5\x19\xa5\xba\f2\xf1(\x8a$}\xd3,?\xe1\x95\x04\x80\x00\xe0\x94\xb6\xfb9xbP\b\x14&\xa3B\xc7\rG\xeeR\x1e[\xc5c\x8a\x03-&\xd1.\x98\v`\x00\x00\u07d4\xb7\r\xba\x93\x91h+J6Nw\xfe\x99%c\x01\xa6\xc0\xbf\x1f\x89\n\u05ce\xbcZ\xc6 \x00\x00\u07d4\xb7\x16#\xf3Q\a\xcft1\xa8?\xb3\xd2\x04\xb2\x9e\u0c67\xf4\x89\x01\x11du\x9f\xfb2\x00\x00\u07d4\xb7\x1a\x13\xba\x8e\x95\x16{\x803\x1bR\u059e7\x05O\xe7\xa8&\x89\n\u05ce\xbcZ\xc6 \x00\x00\u07d4\xb7\x1bb\xf4\xb4H\xc0+\x12\x01\xcb^9J\xe6'\xb0\xa5`\xee\x89\x1b\x1a\xe4\xd6\xe2\xefP\x00\x00\u07d4\xb7\" \xad\xe3d\xd06\x9f--\xa7\x83\xcaGM{\x9b4\u0389\x1b\x1a\xb3\x19\xf5\xecu\x00\x00\xe0\x94\xb7#\r\x1d\x1f\xf2\xac\xa3f\x969\x14\xa7\x9d\xf9\xf7\xc5\xea,\x98\x8a\x01\xb1\xaeMn.\xf5\x00\x00\x00\xe0\x94\xb7$\n\U000af433<\b\xae\x97d\x10>5\xdc\xe3c\x84(\x8a\x01\xca\xdd/\xe9hnc\x80\x00\u07d4\xb7'\xa9\xfc\x82\xe1\xcf\xfc\\\x17_\xa1HZ\x9b\xef\xa2\u037d\u04496'\xe8\xf7\x127<\x00\x00\u07d4\xb7,*\x01\x1c\r\xf5\x0f\xbbn(\xb2\n\xe1\xaa\xd2\x17\x88g\x90\x89\xd8\xd7&\xb7\x17z\x80\x00\x00\u07d4\xb78-7\xdb\x03\x98\xacrA\f\xf9\x81=\xe9\xf8\xe1\uc36d\x8966\xc2^f\xec\xe7\x00\x00\u07d4\xb7;O\xf9\x9e\xb8\x8f\u061b\vmW\xa9\xbc3\x8e\x88o\xa0j\x89\x01\xbc\x16\xd6t\xec\x80\x00\x00\u07d4\xb7=jwU\x9c\x86\xcfet$)\x039K\xac\xf9n5p\x89\x04\xf1\xa7|\xcd;\xa0\x00\x00\u07d4\xb7Cr\xdb\xfa\x18\x1d\xc9$/9\xbf\x1d71\xdf\xfe+\xda\u03c9lk\x93[\x8b\xbd@\x00\x00\u07d4\xb7G\x9d\xabP\"\xc4\xd5\u06ea\xf8\xde\x17\x1bN\x95\x1d\u0464W\x89\x04V9\x18$O@\x00\x00\u07d4\xb7I\xb5N\x04\u0571\x9b\xdc\xed\xfb\x84\xdaw\x01\xabG\x8c'\xae\x89\x91Hx\xa8\xc0^\xe0\x00\x00\u07d4\xb7N\xd2f`\x01\xc1c3\xcfz\xf5\x9eJ=H`6;\x9c\x89\n~\xbd^Cc\xa0\x00\x00\u07d4\xb7QI\xe1\x85\xf6\xe3\x92pWs\x90s\xa1\x82*\xe1\xcf\r\xf2\x89\xd8\xd8X?\xa2\xd5/\x00\x00\u07d4\xb7S\xa7_\x9e\xd1\v!d:\n=\xc0Qz\xc9k\x1a@h\x89\x15\xc8\x18[,\x1f\xf4\x00\x00\xe0\x94\xb7V\xadR\xf3\xbft\xa7\xd2LgG\x1e\b\x87Ci6PL\x8a\x04<3\xc1\x93ud\x80\x00\x00\u07d4\xb7Wn\x9d1M\xf4\x1e\xc5Pd\x94):\xfb\x1b\xd5\xd3\xf6]\x89\x01\x15\x8eF\t\x13\xd0\x00\x00\u07d4\xb7X\x89o\x1b\xaa\x86O\x17\xeb\xed\x16\xd9S\x88o\xeeh\xaa\xe6\x8965\u026d\xc5\u07a0\x00\x00\u0794\xb7h\xb5#N\xba:\x99h\xb3Mm\xdbH\x1c\x84\x19\xb3e]\x88\xcf\xceU\xaa\x12\xb3\x00\x00\u07d4\xb7\x82\xbf\xd1\xe2\xdep\xf4gdo\x9b\xc0\x9e\xa5\xb1\xfc\xf4P\xaf\x89\x0e~\xeb\xa3A\vt\x00\x00\xe0\x94\xb7\xa2\xc1\x03r\x8bs\x05\xb5\xaen\x96\x1c\x94\xee\x99\xc9\xfe\x8e+\x8a\n\x96\x81c\xf0\xa5{@\x00\x00\u07d4\xb7\xa3\x1a|8\xf3\xdb\t2.\xae\x11\xd2'!A\xea\"\x99\x02\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\xb7\xa6y\x1c\x16\xebN!b\xf1Ke7\xa0+=c\xbf\xc6\x02\x89*Rc\x91\xac\x93v\x00\x00\u07d4\xb7\xa7\xf7|4\x8f\x92\xa9\xf1\x10\fk\xd8)\xa8\xacm\u007f\u03d1\x89b\xa9\x92\xe5:\n\xf0\x00\x00\u07d4\xb7\xc0w\x94ft\xba\x93A\xfbLtz]P\xf5\xd2\xdad\x15\x8965\u026d\xc5\u07a0\x00\x00\u07d4\xb7\xc0\xd0\xcc\vM4-@b\xba\xc6$\xcc\xc3\xc7\f\xc6\xda?\x89\xd8\xd7&\xb7\x17z\x80\x00\x00\u07d4\xb7\xc9\xf1+\x03\x8esCm\x17\xe1\xc1/\xfe\x1a\xec\u0373\xf5\x8c\x89\x1dF\x01b\xf5\x16\xf0\x00\x00\u07d4\xb7\xcck\x1a\xcc2\u0632\x95\xdfh\xed\x9d^`\xb8\xf6L\xb6{\x89\x10CV\x1a\x88)0\x00\x00\u07d4\xb7\xcehK\t\xab\xdaS8\x9a\x87Si\xf7\x19X\xae\xac;\u0749lk\x93[\x8b\xbd@\x00\x00\u07d4\xb7\xd1.\x84\xa2\xe4\u01264Z\xf1\xdd\x1d\xa9\xf2PJ*\x99n\x89\n\u05ce\xbcZ\xc6 \x00\x00\u07d4\xb7\xd2R\xee\x94\x02\xb0\xee\xf1D)_\x0ei\xf0\xdbXl\bq\x89#\xc7W\a+\x8d\xd0\x00\x00\xe0\x94\xb7\u0541\xfe\n\xf1\xec8?;<Ag\x83\xf3\x85\x14jv\x12\x8a\x04<3\xc1\x93ud\x80\x00\x00\u07d4\xb7\xf6s\x14\u02c3.2\xe6;\x15\xa4\f\xe0\xd7\xff\xbd\xb2i\x85\x899\x82y&J\x81\x8d\x00\x00\xe0\x94\xb8\x04\x056\x95\x8dY\x98\xceK\xec\f\xfc\x9c\"\x04\x98\x98H\xe9\x8a\x05.\xa7\rI\x8f\xd5\n\x00\x00\u07d4\xb81\n\x16\xccj\xbcFP\aiK\x93\x0f\x97\x8e\xce\x190\xbd\x89(\x1d\x90\x1fO\xdd\x10\x00\x00\xe0\x94\xb84\xac\xf3\x01S\"\u0143\x82\uecb7\x968\x90n\x88\xb6\u078a\x05\x15\n\xe8J\x8c\xdf\x00\x00\x00\xe0\x94\xb8KS\u043b\x12VV\xcd\xdcR\xeb\x85*\xb7\x1drY\xf3\u054a\x03c\\\x9a\xdc]\xea\x00\x00\x00\u07d4\xb8L\x8b\x9f\xd3>\xce\x00\xaf\x91\x99\xf3\xcf_\xe0\xcc\xe2\x8c\xd1J\x89\xcf\x15&@\xc5\xc80\x00\x00\u07d4\xb8R\x18\xf3B\xf8\x01.\u069f'Nc\xce!R\xb2\xdc\xfd\xab\x89\xa8\r$g~\xfe\xf0\x00\x00\u07d4\xb8UP\x10wn<\\\xb3\x11\xa5\xad\xee\xfe\x9e\x92\xbb\x9ad\xb9\x89\xd8\xd7&\xb7\x17z\x80\x00\x00\xe0\x94\xb8_&\xdd\x0er\xd9\u009e\xba\xf6\x97\xa8\xafwG,+X\xb5\x8a\x02\x85\x19\xac\xc7\x19\fp\x00\x00\u07d4\xb8_\xf0>{_\xc4\"\x98\x1f\xae^\x99A\xda\xcb\u06bau\x84\x89Hz\x9a0E9D\x00\x00\xe0\x94\xb8f\a\x02\x1bb\xd3@\xcf&R\xf3\xf9_\xd2\xdcgi\x8b\u07ca\x01\x0f\f\xf0d\xddY \x00\x00\u07d4\xb8}\xe1\xbc\u0492i\xd5!\xb8v\x1c\u00dc\xfbC\x19\xd2\xea\u054965\u026d\xc5\u07a0\x00\x00\u07d4\xb8\u007fSv\xc2\xde\vl\xc3\xc1y\xc0`\x87\xaaG=kFt\x89Hz\x9a0E9D\x00\x00\u07d4\xb8\x84\xad\u060d\x83\xdcVJ\xb8\xe0\xe0,\xbd\xb69\x19\xae\xa8D\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\xb8\x8a7\xc2\u007fx\xa6\x17\xd5\xc0\x91\xb7\u0577:7a\xe6_*\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\xb8\x94x\"\u056c\u79ad\x83&\xe9T\x96\"\x1e\v\xe6\xb7=\x89\x01\x15\x8eF\t\x13\xd0\x00\x00\u07d4\xb8\x9c\x03n\xd7\u0112\x87\x99!\xbeA\xe1\f\xa1i\x81\x98\xa7L\x89b\xa9\x92\xe5:\n\xf0\x00\x00\xe0\x94\xb8\x9fF2\xdfY\t\xe5\x8b*\x99d\xf7O\xeb\x9a;\x01\xe0\u014a\x04\x88u\xbc\xc6\xe7\xcb\xeb\x80\x00\u07d4\xb8\xa7\x9c\x84\x94^G\xa9\xc3C\x86\x83\u05b5\x84,\xffv\x84\xb1\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\xb8\xa9y5'Y\xba\t\xe3Z\xa5\x93]\xf1u\xbf\xf6x\xa1\b\x89\x01\x15\x8eF\t\x13\xd0\x00\x00\u07d4\xb8\xab9\x80[\xd8!\x18Ol\xbd=$s4{\x12\xbf\x17\\\x89\x06hZ\xc1\xbf\xe3,\x00\x00\xe0\x94\xb8\xac\x11}\x9f\r\xba\x80\x90\x14E\x82<L\x9dO\xa3\xfe\xdcn\x8a\x03VLD'\xa8\xfc}\x80\x00\u07d4\xb8\xbc\x9b\xca\u007fq\xb4\xed\x12\xe6 C\x8db\x0fS\xc1\x144/\x89\x1b\x1a\xe4\xd6\xe2\xefP\x00\x00\u07d4\xb8\xbe\xddWjKL '\xdasZ[\xc3\xf53%*\x18\b\x89lk\x93[\x8b\xbd@\x00\x00\xe0\x94\xb8\xc2p=\x8c?/D\u0144\xbc\x10\xe7\xc0\xa6\xb6L\x1c\t~\x8a\x01,\u0778\xea\xd6\xf9\xf8\x00\x00\xe0\x94\xb8\xcc\x0f\x06\n\xad\x92\xd4\xeb\x8b6\xb3\xb9\\\xe9\xe9\x0e\xb3\x83\u05ca\x1f\u00c4+\xd1\xf0q\xc0\x00\x00\u07d4\xb8\xd2\xdd\xc6o0\x8c\x01X\xae<\xcb{\x86\x9f}\x19\x9d{2\x89-\xcb\xf4\x84\x0e\xca\x00\x00\x00\u07d4\xb8\u04c9\xe6$\xa3\xa7\xae\xbc\xe4\xd3\xe5\xdb\xdfl\xdc)\x93*\xed\x89\n\u05ce\xbcZ\xc6 \x00\x00\u07d4\xb8\xd51\xa9d\xbc\xea\x13\x82\x96 \xc0\xce\xd7$\"\xda\xdbL\u0289\t7\x15\xccZ\xb8\xa7\x00\x00\xe0\x94\xb8\xd5\xc3$\xa8 \x9d|\x80I\xd0\u052e\xde\x02\xba\x80\xabW\x8b\x8a\x03\x93\x92\x86)\xff\xf7^\x80\x00\xe0\x94\xb8\xf2\x00\x05\xb6\x13R\xff\xa7i\x9a\x1bR\xf0\x1fZ\xb3\x91g\xf1\x8a\x02\x1e\x19\xe0\u027a\xb2@\x00\x00\u07d4\xb8\xf3\aX\xfa\xa8\b\xdb\xc9\x19\xaa{B^\xc9\"\xb9;\x81)\x8966\u05ef^\u024e\x00\x00\u07d4\xb9\x01<Q\xbd\a\x8a\t\x8f\xae\x05\xbf*\xce\bI\u01be\x17\xa5\x89\x04V9\x18$O@\x00\x00\u07d4\xb9\x14Kg|-\xc6\x14\xce\xef\xdfP\x98_\x11\x83 \x8e\xa6L\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\xb9\x16\xb1\xa0\x1c\xdcNV\xe7ew\x15\xea7\xe2\xa0\xf0\x87\xd1\x06\x89\x82n1\x81\xe0'\x06\x80\x00\u07d4\xb9\x1d\x9e\x91l\xd4\r\x19=\xb6\x0ey 'x\xa0\bw\x16\xfc\x89\x15\xf1\xba\u007fG\x16 \x00\x00\xe0\x94\xb9#\x1e\xb2n_\x9eKM(\x8f\x03\x90g\x04\xfa\xb9l\x87\u058a\x04+\xf0kx\xed;P\x00\x00\u07d4\xb9$'\xadux\xb4\xbf\xe2\n\x9fc\xa7\xc5Pm\\\xa1-\u0209lk\x93[\x8b\xbd@\x00\x00\u07d4\xb9'\xab\xd2\u048a\xaa\xa2M\xb3\x17x\xd2t\x19\u07ce\x1b\x04\xbb\x89\x01~\x11\u00a2oG\x80\x00\u07d4\xb9MG\xb3\xc0R\xa5\xe5\x0eBa\xae\x06\xa2\x0fE\xd8\xee\u25c9lk\x93[\x8b\xbd@\x00\x00\u07d4\xb9S\x96\u06aaI\r\xf2V\x93$\xfc\xc6b;\xe0R\xf12\u0289lk\x93[\x8b\xbd@\x00\x00\xe0\x94\xb9Y\xdc\xe0.\x91\xd9\xdb\x02\xb1\xbd\x8b}\x17\xa9\xc4\x1a\x97\xaf\t\x8a\x01\xb1\xaeMn.\xf5\x00\x00\x00\u07d4\xb9\\\x9b\x10\xaa\x98\x1c\xf4\xa6zq\xccR\xc5\x04\xde\xe8\xcfX\xbd\x89\xd8\xd7&\xb7\x17z\x80\x00\x00\u07d4\xb9\\\xfd\xa8F[\xa9\xc2f\x1b$\x9f\u00ebf\x1b\u07e3_\xf0\x89\x11JNy\xa2\xc2\x10\x80\x00\xe0\x94\xb9hA\u02bb\xc7\xdb\u059e\xf0\u03cf\x81\xdf\xf3\u0225\xe2\x15p\x8a\x02\x8a\x85t%Fo\x80\x00\x00\u07d4\xb9zg3\xcd_\xe9\x98d\xb3\xb34`\xd1g$4\xd5\xca\xfd\x89le\xbb\xaaF\xc2\u03c0\x00\xe0\x94\xb9\x81\xad^kw\x93\xa2?\xc6\xc1\xe8i.\xb2\x96]\x18\xd0\u068a\x02\x1e\x18\xd2\xc8!\xc7R\x00\x00\u07d4\xb9\x8c\xa3\x17\x85\xef\x06\xbeI\xa1\xe4~\x86O`\xd0v\xcaG.\x89\xd8\xd7&\xb7\x17z\x80\x00\x00\u07d4\xb9\x92\x0f\xd0\xe2\xc75\xc2VF<\xaa$\x0f\xb7\xac\x86\xa9=\xfa\x89_h\xe8\x13\x1e\u03c0\x00\x00\u07d4\xb9\x92\xa9g0\x8c\x02\xb9\x8a\xf9\x1e\xe7`\xfd;kH$\xab\x0e\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\xb9\xa9\x85P\x1e\xe9P\x82\x9b\x17\xfa\xe1\xc9\xcf4\x8c1VT,\x89\x0f\xf1u\x17\u029ab\x00\x00\xe0\x94\xb9\xb0\xa3!\x9a2\x88\u0673[\t\x1b\x14e\v\x8f\xe2=\xce+\x8a\x02\xf6\xf1\a\x80\xd2,\xc0\x00\x00\xe0\x94\xb9\xcfq\xb2&X>:\x92\x11\x03\xa51o\x85Zew\x9d\x1b\x8a\x05\x15\n\xe8J\x8c\xdf\x00\x00\x00\u07d4\xb9\xe9\f\x11\x92\xb3\xd5\xd3\xe3\xab\a\x00\xf1\xbfe_]\xd44z\x89\x1b\x19\xe5\vD\x97|\x00\x00\u07d4\xb9\xfd83\xe8\x8e|\xf1\xfa\x98y\xbd\xf5Z\xf4\xb9\x9c\xd5\xce?\x8965\u026d\xc5\u07a0\x00\x00\u07d4\xba\x02I\xe0\x1d\x94[\xef\x93\xee^\xc6\x19%\xe0<\\\xa5\t\xfd\x89\xd8\xd7&\xb7\x17z\x80\x00\x00\u07d4\xba\x0f9\x02;\xdb)\xeb\x18b\xa9\xf9\x05\x9c\xab]0nf/\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\xba\x10\xf2vB\x90\xf8uCCr\xf7\x9d\xbfq8\x01\u02ac\x01\x893\xc5I\x901r\f\x00\x00\u07d4\xba\x151\xfb\x9ey\x18\x96\xbc\xf3\xa8\x05X\xa3Y\xf6\xe7\xc1D\xbd\x89\u0556{\xe4\xfc?\x10\x00\x00\u07d4\xba\x17m\xbe2I\xe3E\xcdO\xa9g\xc0\xed\x13\xb2LG\u5189\x15\xae\xf9\xf1\xc3\x1c\u007f\x00\x00\xe0\x94\xba\x1f\x0e\x03\u02da\xa0!\xf4\xdc\xeb\xfa\x94\xe5\u0209\xc9\u01fc\x9e\x8a\x06\u0450\xc4u\x16\x9a \x00\x00\u07d4\xba\x1f\xca\xf2#\x93~\xf8\x9e\x85gU\x03\xbd\xb7\xcaj\x92\x8bx\x89\"\xb1\xc8\xc1\"z\x00\x00\x00\xe0\x94\xba$\xfcCgS\xa79\xdb,\x8d@\xe6\xd4\xd0LR\x8e\x86\xfa\x8a\x02\xc0\xbb=\xd3\fN \x00\x00\u07d4\xbaB\xf9\xaa\xceL\x18E\x04\xab\xf5BWb\xac\xa2oq\xfb\u0709\x02\a\a}\u0627\x9c\x00\x00\u07d4\xbaF\x9a\xa5\u00c6\xb1\x92\x95\u0521\xb5G;T\x03S9\f\x85\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\xbad@\xae\xb3s{\x8e\xf0\xf1\xaf\x9b\f\x15\xf4\xc2\x14\xff\xc7\u03c965\u026d\xc5\u07a0\x00\x00\xe0\x94\xbam1\xb9\xa2a\xd6@\xb5\u07a5\x1e\xf2\x16,1\t\xf1\uba0a\x01\x0f\f\xf0d\xddY \x00\x00\u07d4\xbap\xe8\xb4u\x9c\f<\x82\xcc\x00\xacN\x9a\x94\xdd[\xaf\xb2\xb8\x890C\xfa3\xc4\x12\xd7\x00\x00\u07d4\xba\x8ac\xf3\xf4\r\u4a03\x88\xbcP!/\xea\x8e\x06O\xbb\x86\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\xba\x8eF\u059d.#C\xd8l`\xd8,\xf4, A\xa0\xc1\u0089\x05k\xc7^-c\x10\x00\x00\u07d4\xba\xa4\xb6L+\x15\xb7\x9f_ BF\xfdp\xbc\xbd\x86\xe4\xa9*\x89\x1b\x1a\xe4\xd6\xe2\xefP\x00\x00\u07d4\xba\u0212,J\xcc},\xb6\xfdY\xa1N\xb4\\\xf3\xe7\x02!K\x89+^:\xf1k\x18\x80\x00\x00\u07d4\xba\xd25\xd5\b]\u01f0h\xa6|A&w\xb0>\x186\x88L\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\xba\xd4B^\x17\x1c>r\x97^\xb4j\xc0\xa0\x15\xdb1Z]\x8f\x89lk\x93[\x8b\xbd@\x00\x00\xe0\x94\xba\xdc*\xef\x9fYQ\xa8\u05cak5\xc3\u0433\xa4\xe6\xe2\xe79\x8a\x01EB\xba\x12\xa37\xc0\x00\x00\u07d4\xba\xdeCY\x9e\x02\xf8OL0\x14W\x1c\x97k\x13\xa3le\xab\x89\xd8\xd7&\xb7\x17z\x80\x00\x00\u07d4\xba\xe9\xb8/r\x99c\x14\be\x9d\xd7N\x89\x1c\xb8\xf3\x86\x0f\xe5\x89j\xcb=\xf2~\x1f\x88\x00\x00\xe0\x94\xbb\x03f\xa7\u03fd4E\xa7\r\xb7\xfeZ\xe3H\x85uO\xd4h\x8a\x01M\xef,B\xeb\xd6@\x00\x00\u07d4\xbb\aj\xac\x92 \x80i\xea1\x8a1\xff\x8e\xeb\x14\xb7\xe9\x96\xe3\x89\b\x13\xcaV\x90m4\x00\x00\u07d4\xbb\bW\xf1\xc9\x11\xb2K\x86\u0227\x06\x81G?\u6aa1\xcc\xe2\x89\x05k\xc7^-c\x10\x00\x00\u0794\xbb\x19\xbf\x91\u02edt\xcc\xeb_\x81\x1d\xb2~A\x1b\xc2\xea\x06V\x88\xf4?\xc2\xc0N\xe0\x00\x00\xe0\x94\xbb'\u01a7\xf9\x10uGZ\xb2)a\x90@\xf8\x04\xc8\xeczj\x8a\x02\x1e\x19\xe0\u027a\xb2@\x00\x00\u07d4\xbb7\x1cr\xc9\xf01l\xea+\xd9\xc6\xfb\xb4\a\x9ewT)\xef\x89_h\xe8\x13\x1e\u03c0\x00\x00\xe0\x94\xbb;\x01\v\x18\xe6\xe2\xbe\x115\x87\x10&\xb7\xba\x15\xea\x0f\xde$\x8a\x02 |\x800\x9bwp\x00\x00\xe0\x94\xbb;\x90\x05\xf4o\xd2\xca;0\x16%\x99\x92\x8cw\xd9\xf6\xb6\x01\x8a\x01\xb1\xae\u007f+\x1b\xf7\xdb\x00\x00\u07d4\xbb?\xc0\xa2\x9c\x03Mq\b\x12\xdc\xc7u\xc8\u02b9\u048diu\x899\xd4\xe8D\xd1\xcf_\x00\x00\u07d4\xbbH\xea\xf5\x16\xce-\xec>A\xfe\xb4\xc6y\xe4\x95vA\x16O\x89\xcf\x15&@\xc5\xc80\x00\x00\u07d4\xbbKJKT\x80p\xffAC,\x9e\b\xa0\xcao\xa7\xbc\x9fv\x89.\x14\x1e\xa0\x81\xca\b\x00\x00\u07d4\xbbV\xa4\x04r<\xff \xd0hT\x88\xb0Z\x02\xcd\xc3Z\xac\xaa\x89\x01\x15\x8eF\t\x13\xd0\x00\x00\u07d4\xbba\x8e%\"\x1a\u0667@\xb2\x99\xed\x14\x06\xbc94\xb0\xb1m\x8965\u026d\xc5\u07a0\x00\x00\u07d4\xbba\xa0K\xff\xd5|\x10G\rE\u00d1\x03\xf6FP4v\x16\x8965\u026d\xc5\u07a0\x00\x00\u07d4\xbbh#\xa1\xbd\x81\x9f\x13QU8&J-\xe0R\xb4D\"\b\x89\x01ch\xffO\xf9\xc1\x00\x00\u07d4\xbbl(J\xac\x8ai\xb7\\\u0770\x0f(\xe1EX;V\xbe\u0389lk\x93[\x8b\xbd@\x00\x00\u07d4\xbbu\xcbPQ\xa0\xb0\x94KFs\xcau*\x97\x03\u007f|\x8c\x15\x89\n\u05ce\xbcZ\xc6 \x00\x00\u07d4\xbb\x99;\x96\xee\x92Z\xda}\x99\u05c6W=?\x89\x18\f\u3a89lk\x93[\x8b\xbd@\x00\x00\u07d4\xbb\xa3\u0180\x04$\x8eH\x95s\xab\xb2t6w\x06k$\u0227\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\xbb\xa4\xfa\xc3\xc4 9\xd8(\xe7B\xcd\xe0\xef\xff\xe7t\x94\x1b9\x89lj\u04c2\xd4\xfba\x00\x00\u07d4\xbb\xa8\xab\"\xd2\xfe\xdb\xcf\xc6?hL\b\xaf\xdf\x1c\x17P\x90\xb5\x89\x05_)\xf3~N;\x80\x00\u07d4\xbb\xa9v\xf1\xa1!_u\x12\x87\x18\x92\xd4_pH\xac\xd3V\u0209lk\x93[\x8b\xbd@\x00\x00\xe0\x94\xbb\xab\x00\v\x04\b\xed\x01Z7\xc0GG\xbcF\x1a\xb1N\x15\x1b\x8a\x01EB\xba\x12\xa37\xc0\x00\x00\u07d4\xbb\xab\xf6d;\xebK\xd0\x1c\x12\v\xd0Y\x8a\t\x87\xd8)g\u0449\xb52\x81x\xad\x0f*\x00\x00\u07d4\xbb\xb4\xee\x1d\x82\xf2\xe1VD,\xc938\xa2\xfc(o\xa2\x88d\x89JD\x91\xbdm\xcd(\x00\x00\u07d4\xbb\xb5\xa0\xf4\x80,\x86H\x00\x9e\x8ai\x98\xaf5,\u0787TO\x89\x05-T(\x04\xf1\xce\x00\x00\u07d4\xbb\xb6C\xd2\x18{6J\xfc\x10\xa6\xfd6\x8d}U\xf5\r\x1a<\x8965\u026d\xc5\u07a0\x00\x00\u07d4\xbb\xb8\xff\xe4?\x98\u078e\xae\x18F#\xaeRd\xe4$\u0438\u05c9\x05\xd5?\xfd\xe9(\b\x00\x00\u07d4\xbb\xbdn\u02f5u(\x91\xb4\u03b3\xcc\xe7:\x8fGpY7o\x89\x01\xf3\x99\xb1C\x8a\x10\x00\x00\u07d4\xbb\xbf9\xb1\xb6y\x95\xa4\"APO\x97\x03\u04a1JQV\x96\x89U\xa6\xe7\x9c\xcd\x1d0\x00\x00\u07d4\xbb\xc8\xea\xffc~\x94\xfc\u014d\x91<wp\u020f\x9bG\x92w\x89\n\u05ce\xbcZ\xc6 \x00\x00\u07d4\xbb\xc9\xd8\x11.[\xeb\x02\xdd)\xa2%{\x1f\xe6\x9b56\xa9E\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\xbb\xcae\xb3&n\xa2\xfbs\xa0?\x92\x165\xf9\x12\u01fe\xde\x00\x89j\xcb=\xf2~\x1f\x88\x00\x00\u07d4\xbb\xf8B\x92\xd9T\xac\xd9\xe4\a/\xb8`\xb1PA\x06\xe0w\xae\x89QP\xae\x84\xa8\xcd\xf0\x00\x00\u07d4\xbb\xf8Z\xaa\xa6\x83s\x8f\a;\xae\xf4J\xc9\xdc4\xc4\xc7y\xea\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\xbb\xf8am\x97rJ\xf3\xde\xf1e\xd0\xe2\x8c\u0689\xb8\x00\x00\x9a\x89\x06.\xf1.+\x17a\x80\x00\xe0\x94\xbb\xfe\n\x83\f\xac\xe8{r\x93\x99:~\x94\x96\xced\xf8\u350a\x01EB\xba\x12\xa37\xc0\x00\x00\u07d4\xbc\f\xa4\xf2\x17\xe0Ru6\x14\u05b0\x19\x94\x88$\xd0\xd8h\x8b\x89\x15\xaf\x1dx\xb5\x8c@\x00\x00\xe0\x94\xbc\x0e\x87E\u00e5ID\\+\xe9\x00\xf5#\x00\x80J\xb5b\x89\x8a\a\x02\x9b\xf5\xddLS\xb2\x80\x00\u07d4\xbc\x0f\x98Y\x8f\x88\x05j&3\x96 \x92;\x8f\x1e\xb0t\xa9\xfd\x89\n\u05ce\xbcZ\xc6 \x00\x00\u07d4\xbc\x16\t\u0585\xb7kH\uc41a\xa0\x99!\x90\"\xf8\x9b,\u0349@\x13\x8b\x91~\u07f8\x00\x00\xe0\x94\xbc\x17\x1eS\xd1z\u0276\x12A\xaeCm\xee\u01efE.t\x96\x8a\x01!\xeah\xc1\x14\xe5\x10\x00\x00\u07d4\xbc\x1b\x02\x1ax\xfd\xe4-\x9bR&\xd6\xec&\xe0j\xa3g\x00\x90\x89\x04V9\x18$O@\x00\x00\u07d4\xbc\x1e\x80\xc1\x81acB\xeb\xb3\xfb9\x92\a/\x1b(\xb8\x02\u0189\xd8\xd7&\xb7\x17z\x80\x00\x00\u07d4\xbc#qH\xd3\f\x13\x83o\xfa,\xadR\x0e\xe4\xd2\xe5\xc4\xee\xff\x89j\xcb=\xf2~\x1f\x88\x00\x00\xe0\x94\xbcF\xd57\xcf.\xdd@5e\xbd\xe73\xb2\xe3K!P\x01\xbd\x8a\x04<3\xc1\x93ud\x80\x00\x00\xe0\x94\xbcNG\x15`\u025c\x8a*K\x1b\x1a\xd0\xc3j\xa6P+|K\x8a\x02\x8a\x85t%Fo\x80\x00\x00\u07d4\xbcb\xb3\tj\x91\xe7\xdc\x11\xa1Y*)=\xd2T!P\xd7Q\x8965\u026d\xc5\u07a0\x00\x00\u07d4\xbci\xa0\u04a3\x1c=\xbfz\x91\"\x11i\x01\xb2\xbd\xfe\x98\x02\xa0\x89\xa2\xa1]\tQ\x9b\xe0\x00\x00\u07d4\xbckX6K\xf7\xf1\x95\x1c0\x9e\f\xba\x05\x95 \x1c\xd7?\x9a\x89b@\x1aE~E\xf8\x00\x00\u07d4\xbcs\xf7\xb1\xca;w;4$\x9a\xda.,\x8a\x92t\xcc\x17\u0089lk\x93[\x8b\xbd@\x00\x00\u07d4\xbcz\xfc\x84wA\"t\xfc&]\xf1<\x05DsB}C\u0189\a\f\x95\x92\f\xe3%\x00\x00\xe0\x94\xbc\x96\u007f\xe4A\x8c\x18\xb9\x98X\x96m\x87\x06x\u0722\xb8\x88y\x8a\x01\xd9\xcb\u074d~\xd2\x10\x00\x00\u07d4\xbc\x99\x9e8\\Z\xeb\xca\xc8\xd6\xf3\xf0\xd6\rZ\xa7%3m\r\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\xbc\x9c\x95\u07eb\x97\xa5t\u03a2\xaa\x80;\\\xaa\x19|\xef\f\xff\x89\x16\u012b\xbe\xbe\xa0\x10\x00\x00\u07d4\xbc\x9e\x0e\xc6x\x8f}\xf4\xc7\xfc!\n\xac\xd2 \xc2~E\xc9\x10\x89\x1b\x1a\xe4\xd6\xe2\xefP\x00\x00\u07d4\xbc\xa3\xff\xd4h?\xba\n\u04fb\xc9\a4\xb6\x11\u069c\xfbE~\x89\n\u05ce\xbcZ\xc6 \x00\x00\u07d4\xbc\xae\u042c\xb6\xa7o\x11?|a5U\xa2\u00f0\xf5\xbf4\xa5\x89\n~\xbd^Cc\xa0\x00\x00\u07d4\xbc\xaf4y\x18\xef\xb2\xd6=\xde\x03\xe3\x92u\xbb\xe9}&\xdfP\x89\x05k\xc7^-c\x10\x00\x00\u07d4\xbc\xb4\"\xdcM\u04aa\xe9J\xba\xe9^\xa4]\xd1s\x1b\xb6\xb0\xba\x89\x18BO_\v\x1bN\x00\x00\u07d4\xbc\xbd1%.\u0088\xf9\x1e)\x8c\xd8\x12\xc9!`\xe783\x1a\x89k\x1b\xc2\xca\xc0\x9aY\x00\x00\u07d4\xbc\xbfk\xa1f\xe24\r\xb0R\xea#\u0480)\xb0\xdej\xa3\x80\x89\xd2U\xd1\x12\xe1\x03\xa0\x00\x00\u07d4\xbc\xc8E\x97\xb9\x1es\xd5\u0174\u059c\x80\xec\xf1F\x86\x0fw\x9a\x89\xedp\xb5\xe9\xc3\xf2\xf0\x00\x00\u07d4\xbc\xc9Y;-\xa6\xdfj4\xd7\x1b\x1a\xa3\x8d\xac\xf8v\xf9[\x88\x89\x01\x15\x8eF\t\x13\xd0\x00\x00\u07d4\xbc\xd9^\xf9bF+n\u07e1\x0f\u0687\xd7\"B\xfe>\xdb\\\x89\x12\x1d\x06\xe1/\xff\x98\x80\x00\u07d4\xbc\u065e\xdc!`\xf2\x10\xa0^:\x1f\xa0\xb0CL\xed\x00C\x9b\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\xbc\u07ec\xb9\xd9\x02<4\x17\x18.\x91\x00\xe8\xea\x1d73\x93\xa3\x89\x034-`\xdf\xf1\x96\x00\x00\u07d4\xbc\xe1>\"2*\u03f3U\xcd!\xfd\r\xf6\f\xf9:\xdd&\u0189\n\u05ce\xbcZ\xc6 \x00\x00\xe0\x94\xbc\xe4\x04u\xd3E\xb0q-\xeep=\x87\xcdvW\xfc\u007f;b\x8a\x01\xa4 \xdb\x02\xbd}X\x00\x00\u07d4\xbc\xed\xc4&|\u02c9\xb3\x1b\xb7d\xd7!\x11q\x00\x8d\x94\xd4M\x89\n\u05ce\xbcZ\xc6 \x00\x00\u07d4\xbc\xfc\x98\xe5\xc8+j\xdb\x18\n?\xcb\x12\v\x9av\x90\xc8j?\x89j\xcb=\xf2~\x1f\x88\x00\x00\u07d4\xbd\x04;g\xc6>`\xf8A\xcc\xca\x15\xb1)\xcd\xfee\x90\xc8\xe3\x89\n\u05ce\xbcZ\xc6 \x00\x00\u07d4\xbd\x04\u007f\xf1\xe6\x9c\u01b2\x9a\xd2d\x97\xa9\xa6\xf2z\x90?\xc4\u0749.\xe4IU\b\x98\xe4\x00\x00\u07d4\xbd\b\xe0\xcd\xde\xc0\x97\xdby\x01\ua05a=\x1f\xd9\u0789Q\xa2\x89\x01\x15\x8eF\t\x13\xd0\x00\x00\u07d4\xbd\t\x12l\x89\x1cJ\x83\x06\x80Y\xfe\x0e\x15ylFa\xa9\xf4\x89+^:\xf1k\x18\x80\x00\x00\u07d4\xbd\f\\\u05d9\xeb\u0106B\xef\x97\xd7N\x8eB\x90d\xfe\u4489\x11\xac(\xa8\xc7)X\x00\x00\u07d4\xbd\x17\xee\xd8+\x9a%\x92\x01\x9a\x1b\x1b<\x0f\xba\xd4\\@\x8d\"\x89\r\x8drkqw\xa8\x00\x00\u07d4\xbd\x18\x037\v\u0771)\xd29\xfd\x16\xea\x85&\xa6\x18\x8a\u5389\x1b\x1a\xe4\xd6\xe2\xefP\x00\x00\u07d4\xbd+p\xfe\xcc7d\x0fiQO\xc7\xf3@IF\xaa\xd8k\x11\x89A\rXj \xa4\xc0\x00\x00\u07d4\xbd0\x97\xa7\x9b<\r.\xbf\xf0\xe6\xe8j\xb0\xed\xad\xbe\xd4p\x96\x89Z\x87\xe7\xd7\xf5\xf6X\x00\x00\u07d4\xbd2]@)\xe0\xd8r\x9fm9\x9cG\x82$\xae\x9ez\xe4\x1e\x89\xd2U\xd1\x12\xe1\x03\xa0\x00\x00\u07d4\xbdC*9\x16$\x9bG$):\xf9\x14nI\xb8(\n\u007f*\x89\xd8\xd7&\xb7\x17z\x80\x00\x00\u07d4\xbdG\xf5\xf7n;\x93\x0f\xd9HR\t\xef\xa0\xd4v=\xa0uh\x8965\u026d\xc5\u07a0\x00\x00\u07d4\xbdK`\xfa\xect\n!\xe3\a\x13\x91\xf9j\xa54\xf7\xc1\xf4N\x89\t\xdd\xc1\xe3\xb9\x01\x18\x00\x00\u07d4\xbdK\u0571\"\xd8\xef{|\x8f\x06gE\x03 \xdb!\x16\x14.\x89 \x86\xac5\x10R`\x00\x00\u07d4\xbdQ\xee.\xa1C\u05f1\u05b7~~D\xbd\xd7\xda\x12\U00105b09G~\x06\u0332\xb9(\x00\x00\u07d4\xbdY\tN\aO\x8dy\x14*\xb1H\x9f\x14\x8e2\x15\x1f \x89\x89\x01\x15\x8eF\t\x13\xd0\x00\x00\u07d4\xbdZ\x8c\x94\xbd\x8b\xe6G\x06D\xf7\f\x8f\x8a3\xa8\xa5\\cA\x89\n\u05ce\xbcZ\xc6 \x00\x00\u07d4\xbd^G:\xbc\xe8\xf9zi2\xf7|/\xac\xaf\x9c\xc0\xa0\x05\x14\x89<\x92X\xa1\x06\xa6\xb7\x00\x00\u07d4\xbd_F\u02ab,=K(\x93\x96\xbb\xb0\u007f <M\xa8%0\x89\x04V9\x18$O@\x00\x00\u07d4\xbdf\xff\xed\xb50\xea\v.\x85m\xd1*\xc2)l1\xfe)\xe0\x89\n\u05ce\xbcZ\xc6 \x00\x00\u07d4\xbdg\xd2\xe2\xf8-\xa8\x86\x13A\xbc\x96\xa2\xc0y\x1f\xdd\xf3\x9e@\x89\n\xd7\xc0yG\xc8\xfb\x00\x00\u07d4\xbdjGMf4[\xcd\xd7\aYJ\xdbc\xb3\fx\"\xafT\x89\xd8\xd7&\xb7\x17z\x80\x00\x00\xe0\x94\xbdr;(\x9asg\xb6\xec\xe2E^\xd6\x1e\xdbIg\n\xb9\u010a\x01\x0f\f\u07a1d!?\x80\x00\u07d4\xbds\xc3\xcb\xc2j\x17Pb\xea\x03 \u0744\xb2S\xbc\xe6CX\x89\x15[\xd90\u007f\x9f\xe8\x00\x00\xe0\x94\xbdt\x19\xdc*\t\nF\xe2\x87=}\xe6\xea\xaa\u055e\x19\xc4y\x8a\x01p\xbc\xb6qu\x9f\b\x00\x00\u07d4\xbd\x87e\xf4\x12\x99\xc7\xf4y\x92<O\u044f\x12mr)\x04}\x89\xd8\xd7&\xb7\x17z\x80\x00\x00\u07d4\xbd\x93\xe5P@>*\x06\x11>\xd4\xc3\xfb\xa1\xa8\x91;\x19@~\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\xbd\x9eV\xe9\x02\xf4\xbe\x1f\xc8v\x8d\x808\xba\xc6>*\u02ff\x8e\x8965f3\xeb\xd8\xea\x00\x00\u07d4\xbd\xa4\xbe1~~K\xed\x84\xc0I^\xee2\xd6\a\xec8\xcaR\x89}2'yx\xefN\x80\x00\u07d4\xbd\xb6\v\x82:\x11s\xd4Z\a\x92$_\xb4\x96\xf1\xfd3\x01\u03c9lk\x93[\x8b\xbd@\x00\x00\u07d4\xbd\xba\xf6CM@\xd65[\x1e\x80\xe4\f\u012b\x9ch\xd9a\x16\x89\x05k\xc7^-c\x10\x00\x00\u07d4\xbd\xc0,\xd43\f\x93\xd6\xfb\xdaOm\xb2\xa8]\xf2/C\xc23\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\xbd\xc4aF+c\"\xb4b\xbd\xb3?\"y\x9e\x81\b\xe2A}\x89$=M\x18\"\x9c\xa2\x00\x00\u07d4\xbd\xc79\xa6\x99p\v.\x8e,JL{\x05\x8a\x0eQ=\u07be\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\xbd\xc7Hs\xaf\x92+\x9d\xf4t\x85;\x0f\xa7\xff\v\xf8\xc8&\x95\x89\xd8\xc9F\x00c\xd3\x1c\x00\x00\u07d4\xbd\xca*\x0f\xf3E\x88\xafb_\xa8\xe2\x8f\xc3\x01Z\xb5\xa3\xaa\x00\x89~\xd7?w5R\xfc\x00\x00\u07d4\xbd\xd3%N\x1b:m\xc6\xcc,i}Eq\x1a\xca!\xd5\x16\xb2\x89lk\x93[\x8b\xbd@\x00\x00\xe0\x94\xbd\u07e3M\x0e\xbf\x1b\x04\xafS\xb9\x9b\x82IJ\x9e=\x8a\xa1\x00\x8a\x02\x8a\x85t%Fo\x80\x00\x00\u07d4\xbd\xe4\xc7?\x96\x9b\x89\xe9\u03aef\xa2\xb5\x18DH\x0e\x03\x8e\x9a\x8965\u026d\xc5\u07a0\x00\x00\xe0\x94\xbd\xe9xj\x84\xe7[H\xf1\x8erm\u05cdp\xe4\xaf>\xd8\x02\x8a\x016\x9f\xb9a(\xacH\x00\x00\u07d4\xbd\xed\x11a/\xb5\xc6\u0699\xd1\xe3\x0e2\v\xc0\x99Tf\x14\x1e\x89\x15\xaf\x1dx\xb5\x8c@\x00\x00\u07d4\xbd\xed~\a\xd0q\x1ehM\xe6Z\u0232\xabW\xc5\\\x1a\x86E\x89 \t\xc5\u023fo\xdc\x00\x00\u07d4\xbd\xf6\x93\xf83\xc3\xfeG\x17S\x18G\x88\xebK\xfeJ\xdc?\x96\x89j\xcb=\xf2~\x1f\x88\x00\x00\u07d4\xbd\xf6\xe6\x8c\f\xd7X@\x80\xe8G\xd7,\xbb#\xaa\xd4j\xeb\x1d\x89j\xcb=\xf2~\x1f\x88\x00\x00\u07d4\xbe\n/8_\t\xdb\xfc\xe9g2\xe1+\xb4\n\xc3I\x87\x1b\xa8\x89WL\x11^\x02\xb8\xbe\x00\x00\u07d4\xbe\f*\x80\xb9\xde\bK\x17(\x94\xa7l\xf4szOR\x9e\x1a\x89lj\xccg\u05f1\xd4\x00\x00\u07d4\xbe\x1c\xd7\xf4\xc4r\a\th\xf3\xbd\xe2h6k!\xee\xea\x83!\x89\xe9\x1a|\u045f\xa3\xb0\x00\x00\u07d4\xbe#F\xa2\u007f\xf9\xb7\x02\x04OP\r\xef\xf2\xe7\xff\xe6\x82EA\x89\x01\x15\x8eF\t\x13\xd0\x00\x00\u07d4\xbe$q\xa6\u007f`G\x91\x87r\xd0\xe3h9%^\xd9\u0591\xae\x89\xd8\xd7&\xb7\x17z\x80\x00\x00\u07d4\xbe+\"\x80R7h\xea\x8a\xc3\\\xd9\xe8\x88\xd6\nq\x93\x00\u0509lk\x93[\x8b\xbd@\x00\x00\xe0\x94\xbe+2nx\xed\x10\xe5P\xfe\xe8\xef\xa8\xf8\a\x03\x96R/Z\x8a\bW\xe0\xd6\xf1\xdav\xa0\x00\x00\xe0\x94\xbe0Zyn3\xbb\xf7\xf9\xae\xaee\x12\x95\x90f\xef\xda\x10\x10\x8a\x02M\xceT\xd3J\x1a\x00\x00\x00\u07d4\xbeG\x8e\x8e=\xdek\xd4\x03\xbb-\x1ce|C\x10\xee\x19'#\x89\x1a\xb2\xcf|\x9f\x87\xe2\x00\x00\u07d4\xbeN}\x98?.*ck\x11\x02\xecp9\xef\xeb\xc8B\u9349\x03\x93\xef\x1aQ'\xc8\x00\x00\u07d4\xbeO\xd0sap\"\xb6\u007f\\\x13I\x9b\x82\u007fv69\xe4\xe3\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\xbeRZ3\xea\x91aw\xf1r\x83\xfc\xa2\x9e\x8b5\v\u007fS\v\x89\x8f\x01\x9a\xafF\xe8x\x00\x00\u07d4\xbeS2/C\xfb\xb5\x84\x94\xd7\xcc\xe1\x9d\xda'+$P\xe8'\x89\n\xd7\u03afB\\\x15\x00\x00\u07d4\xbeS\x82F\xddNo\f \xbfZ\xd17<;F:\x13\x1e\x86\x89\n\u05ce\xbcZ\xc6 \x00\x00\u07d4\xbeZ`h\x99\x98c\x9a\xd7[\xc1\x05\xa3qt>\xef\x0fy@\x89\x1b2|s\xe1%z\x00\x00\u07d4\xbe\\\xba\x8d7By\x86\xe8\xca&\x00\xe8X\xbb\x03\xc3YR\x0f\x89\xa00\xdc\xeb\xbd/L\x00\x00\u07d4\xbe`\x03~\x90qJK\x91~a\xf1\x93\xd84\x90g\x03\xb1:\x89\\(=A\x03\x94\x10\x00\x00\u07d4\xbec:77\xf6\x849\xba\xc7\xc9\nR\x14 X\ue38ao\x894\n\xad!\xb3\xb7\x00\x00\x00\xe0\x94\xbee\x9d\x85\xe7\xc3O\x883\xea\u007fH\x8d\xe1\xfb\xb5\xd4\x14\x9b\xef\x8a\x01\xeb\xd2:\xd9\u057br\x00\x00\u07d4\xbes'M\x8cZ\xa4J<\xbe\xfc\x82c\xc3{\xa1!\xb2\n\u04c9\x1b\x1a\xe4\xd6\xe2\xefP\x00\x00\u07d4\xbe\x86\u0430C\x84\x19\u03b1\xa081\x927\xbaR\x06\xd7.F\x8964\xfb\x9f\x14\x89\xa7\x00\x00\u07d4\xbe\x8d\u007f\x18\xad\xfe]l\xc7u9I\x89\xe1\x93\f\x97\x9d\x00}\x8965\u026d\xc5\u07a0\x00\x00\u07d4\xbe\x91\x86\xc3JRQJ\xbb\x91\a\x86\x0fgO\x97\xb8!\xbd[\x89\x1b\xa0\x1e\xe4\x06\x03\x10\x00\x00\u07d4\xbe\x93W\x93\xf4[p\xd8\x04]&T\xd8\xdd:\xd2K[a7\x89/\xb4t\t\x8fg\xc0\x00\x00\u07d4\xbe\x98\xa7\u007f\xd4\x10\x97\xb3OY\xd7X\x9b\xaa\xd0!e\x9f\xf7\x12\x890\xca\x02O\x98{\x90\x00\x00\u07d4\xbe\x9b\x8c4\xb7\x8e\xe9G\xff\x81G.\xdaz\xf9\xd2\x04\xbc\x84f\x89\b!\xab\rD\x14\x98\x00\x00\u07d4\xbe\xa0\r\xf1pg\xa4:\x82\xbc\x1d\xae\xca\xfbl\x140\x0e\x89\xe6\x89b\xa9\x92\xe5:\n\xf0\x00\x00\u07d4\xbe\xa0\xaf\xc9:\xae!\b\xa3\xfa\xc0Yb;\xf8o\xa5\x82\xa7^\x89\\(=A\x03\x94\x10\x00\x00\u07d4\xbe\xb35\x8cP\u03dfu\xff\xc7mD<,\u007fU\aZ\x05\x89\x89\x90\xf54`\x8ar\x88\x00\x00\u07d4\xbe\xb4\xfd1UYC`E\u0739\x9dI\xdc\xec\x03\xf4\fB\u0709lk\x93[\x8b\xbd@\x00\x00\u07d4\xbe\xc2\xe6\xde9\xc0|+\xaeUj\u03fe\xe2\xc4r\x8b\x99\x82\xe3\x89\x1f\x0f\xf8\xf0\x1d\xaa\xd4\x00\x00\u07d4\xbe\xc6d\x0fI\t\xb5\x8c\xbf\x1e\x80cB\x96\x1d`u\x95\tl\x89lj\xccg\u05f1\xd4\x00\x00\u07d4\xbe\xc8\xca\xf7\xeeIF\x8f\xeeU.\xff:\xc5#N\xb9\xb1}B\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\xbe\xce\xf6\x1c\x1cD+\xef|\xe0Ks\xad\xb2I\xa8\xba\x04~\x00\x896;V\u00e7T\xc8\x00\x00\u0794\xbe\xd4d\x9d\xf6F\u2052)\x03-\x88hUo\xe1\xe0S\u04c8\xfc\x93c\x92\x80\x1c\x00\x00\xe0\x94\xbe\xd4\xc8\xf0\x06\xa2|\x1e_|\xe2\x05\xdeu\xf5\x16\xbf\xb9\xf7d\x8a\x03c\\\x9a\xdc]\xea\x00\x00\x00\u07d4\xbe\xe8\u0430\bB\x19T\xf9-\x00\r9\x0f\xb8\xf8\xe6X\xea\xee\x8965\u026d\xc5\u07a0\x00\x00\u07d4\xbe\xec\u05af\x90\f\x8b\x06J\xfc\xc6\a?-\x85\u055a\xf1\x19V\x89lk\x93[\x8b\xbd@\x00\x00\xe0\x94\xbe\xef\x94!8y\xe0&\"\x14+\xeaa)\tx\x93\x9a`\u05ca\x016\x85{2\xad\x86\x04\x80\x00\xe0\x94\xbe\xf0}\x97\xc3H\x1f\x9dj\xee\x1c\x98\xf9\xd9\x1a\x18\n2D+\x8a\x15-\x02\xc7\xe1J\xf6\x80\x00\x00\u07d4\xbe\xfbD\x8c\f_h?\xb6~\xe5p\xba\xf0\xdbV\x86Y\x97Q\x89j\xcb=\xf2~\x1f\x88\x00\x00\u07d4\xbf\x05\a\f,4!\x93\x11\xc4T\x8b&\x14\xa48\x81\r\xedm\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\xbf\x05\xff^\xcf\r\xf2\u07c8wY\xfb\x82t\xd928\xac&}\x89+^:\xf1k\x18\x80\x00\x00\xe0\x94\xbf\t\xd7pH\xe2p\xb6b3\x0e\x94\x86\xb3\x8bC\xcdx\x14\x95\x8a\\S\x9b{\xf4\xff(\x80\x00\x00\u07d4\xbf\x17\xf3\x97\xf8\xf4o\x1b\xaeE\u0447\x14\x8c\x06\xee\xb9Y\xfaM\x896I\u0156$\xbb0\x00\x00\u07d4\xbf\x186A\xed\xb8\x86\xce`\xb8\x19\x02a\xe1OB\xd9<\xce\x01\x89\x01[5W\xf1\x93\u007f\x80\x00\u07d4\xbf*\xeaZ\x1d\xcfn\u04f5\xe829D\xe9\x83\xfe\xdf\u046c\xfb\x89U\xa6\xe7\x9c\xcd\x1d0\x00\x00\u07d4\xbf@\x96\xbcT}\xbf\xc4\xe7H\t\xa3\x1c\x03\x9e{8\x9d^\x17\x89\u0556{\xe4\xfc?\x10\x00\x00\u07d4\xbfI\xc1H\x981eg\u0637\t\xc2\xe5\x05\x94\xb3f\xc6\u04cc\x89'\xbf8\xc6TM\xf5\x00\x00\u07d4\xbfLs\xa7\xed\xe7\xb1d\xfe\a!\x14\x846T\xe4\xd8x\x1d\u0789lk\x93[\x8b\xbd@\x00\x00\u07d4\xbfP\xce.&K\x9f\xe2\xb0h0az\xed\xf5\x02\xb25\x1bE\x8965\u026d\xc5\u07a0\x00\x00\u07d4\xbfY\xae\xe2\x81\xfaC\xfe\x97\x19CQ\xa9\x85~\x01\xa3\xb8\x97\xb2\x89 \x86\xac5\x10R`\x00\x00\u07d4\xbfh\u048a\xaf\x1e\xee\xfe\xf6F\xb6^\x8c\xc8\u0450\xf6\xc6\u069c\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\xbfi%\xc0\aQ\x00\x84@\xa6s\x9a\x02\xbf+l\u06ab^:\x8965\u026d\xc5\u07a0\x00\x00\u07d4\xbfw\x01\xfcb%\u0561x\x15C\x8a\x89A\xd2\x1e\xbc]\x05\x9d\x89e\xea=\xb7UF`\x00\x00\u07d4\xbf\x8b\x80\x05\xd66\xa4\x96d\xf7Bu\xefBC\x8a\xcde\xac\x91\x89\n\u05ce\xbcZ\xc6 \x00\x00\u07d4\xbf\x92A\x8a\fl1$M\"\x02`\xcb>\x86}\u05f4\xefI\x89\x05i\x00\xd3<\xa7\xfc\x00\x00\u07d4\xbf\x9a\xcdDE\xd9\xc9UF\x89\u02bb\xba\xb1\x88\x00\xff\x17A\u008965\u026d\xc5\u07a0\x00\x00\u07d4\xbf\x9f'\x1fz~\x12\xe3m\xd2\xfe\x9f\xac\xeb\xf3\x85\xfeaB\xbd\x89\x03f\xf8O{\xb7\x84\x00\x00\u07d4\xbf\xa8\xc8X\xdf\x10,\xb1$!\x00\x8b\n1\xc4\xc7\x19\n\xd5`\x89\n\u05ce\xbcZ\xc6 \x00\x00\u07d4\xbf\xae\xb9\x10ga}\u03cbD\x17+\x02\xafaVt\x83]\xba\x89\b\xb5\x9e\x88H\x13\b\x80\x00\xe0\x94\xbf\xb0\xea\x02\xfe\xb6\x1d\xec\x9e\"\xa5\a\tY3\x02\x99\xc40r\x8a\x04<3\xc1\x93ud\x80\x00\x00\xe0\x94\xbf\xbc\xa4\x18\xd3R\x9c\xb3\x93\b\x10b\x03*n\x11\x83\u01b2\u070a\x01\xb1\xaeMn.\xf5\x00\x00\x00\u07d4\xbf\xbe\x05\u831c\xbb\xcc\x0e\x92\xa4\x05\xfa\xc1\xd8]\xe2H\xee$\x89\x05k\xc7^-c\x10\x00\x00\xe0\x94\xbf\xbf\xbc\xb6V\u0099+\xe8\xfc\u0782\x19\xfb\xc5J\xad\u055f)\x8a\x02\x1e\x18\xd2\xc8!\xc7R\x00\x00\u07d4\xbf\xc5z\xa6f\xfa\u239f\x10zI\xcbP\x89\xa4\xe2!Q\u074965\u026d\xc5\u07a0\x00\x00\u07d4\xbf\u02d70$c\x04p\r\xa9\vAS\xe7\x11Ab.\x1cA\x8965\u026d\xc5\u07a0\x00\x00\xe0\x94\xbf\xd9<\x90\u009c\a\xbc_\xb5\xfcI\xae\xeaU\xa4\x0e\x13O5\x8a\x05\xed\xe2\x0f\x01\xa4Y\x80\x00\x00\xe0\x94\xbf\xe3\xa1\xfcn$\xc8\xf7\xb3%\x05`\x99\x1f\x93\u02e2\u03c0G\x8a\x10\xf0\xcf\x06M\u0552\x00\x00\x00\u07d4\xbf\u6f30\xf0\xc0xRd3$\xaa]\xf5\xfdb%\xab\xc3\u0289\x04\t\xe5+H6\x9a\x00\x00\u07d4\xbf\xf5\xdfv\x994\xb8\x94<\xa9\x13}\x0e\xfe\xf2\xfen\xbb\xb3N\x89\x05k\xc7^-c\x10\x00\x00\u07d4\xbf\xfbi)$\x1fx\x86\x93'>p\"\xe6\x0e>\xab\x1f\xe8O\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\xc0\x06O\x1d\x94t\xab\x91]V\x90l\x9f\xb3 \xa2\xc7\t\x8c\x9b\x89\x13h?\u007f<\x15\xd8\x00\x00\u07d4\xc0\a\xf0\xbd\xb6\xe7\x00\x92\x02\xb7\xaf>\xa9\t\x02i|r\x14\x13\x89\xa2\xa0\xe4>\u007f\xb9\x83\x00\x00\u07d4\xc0\n\xb0\x80\xb6C\xe1\u00ba\xe3c\xe0\u0455\xde.\xff\xfc\x1cD\x89\x1b\x1a\xe4\xd6\xe2\xefP\x00\x00\u0794\xc0 wD\x9a\x13Jz\xd1\xef~M\x92z\xff\xec\ueb75\xae\x88\xfc\x93c\x92\x80\x1c\x00\x00\u07d4\xc0$q\xe3\xfc.\xa0S&\x15\xa7W\x1dI2\x89\xc1<6\xef\x89\x01\x15\x8eF\t\x13\xd0\x00\x00\u07d4\xc0-n\xad\xea\xcf\x1bx\xb3\u0285\x03\\c{\xb1\xce\x01\xf4\x90\x89\xd8\xd7&\xb7\x17z\x80\x00\x00\u07d4\xc03\xb12Z\n\xf4Tr\xc2U'\x85;\x1f\x1c!\xfa5\u0789lk\x93[\x8b\xbd@\x00\x00\u07d4\xc03\xbe\x10\xcbHa;\xd5\xeb\xcb3\xedI\x02\xf3\x8bX0\x03\x89\xa2\xa1]\tQ\x9b\xe0\x00\x00\u07d4\xc04[3\xf4\x9c\xe2\u007f\xe8,\xf7\xc8M\x14\x1ch\xf5\x90\xcev\x8965\u026d\xc5\u07a0\x00\x00\u07d4\xc0=\xe4*\x10\x9bezd\xe9\"$\xc0\x8d\xc1'^\x80\u0672\x89\x01\x15\x8eF\t\x13\xd0\x00\x00\u07d4\xc0@i\u07f1\x8b\tlxg\xf8\xbe\xe7zm\xc7Gz\xd0b\x89\x90\xf54`\x8ar\x88\x00\x00\xe0\x94\xc0A?Z|-\x9aK\x81\b(\x9e\xf6\xec\xd2qx\x15$\xf4\x8a\n\x96\x81c\xf0\xa5{@\x00\x00\u07d4\xc0C\xf2E-\u02d6\x02\xefb\xbd6\x0e\x03=\xd29q\xfe\x84\x89lk\x93[\x8b\xbd@\x00\x00\xe0\x94\xc0OK\xd4\x04\x9f\x04F\x85\xb8\x83\xb6)Y\xaec\x1df~5\x8a\x01;\x80\xb9\x9cQ\x85p\x00\x00\u07d4\xc0V\u053dk\xf3\u02ec\xace\xf8\xf5\xa0\xe3\x98\v\x85'@\xae\x89\x05k\xc7^-c\x10\x00\x00\u07d4\xc0[t\x06 \xf1s\xf1nRG\x1d\u00cb\x9cQJ\v\x15&\x89\a\x96\xe3\xea?\x8a\xb0\x00\x00\u07d4\xc0i\xef\x0e\xb3B\x99\xab\xd2\xe3-\xab\xc4yD\xb2r3H$\x89\x06\x81U\xa46v\xe0\x00\x00\u07d4\xc0l\xeb\xbb\xf7\xf5\x14\x9af\xf7\xeb\x97k>G\xd5e\x16\xda/\x89lk\x93[\x8b\xbd@\x00\x00\xe0\x94\xc0r^\u00bd\xc3:\x1d\x82`q\u07a2\x9db\xd48Z\x8c%\x8a\b\xa0\x85\x13F:\xa6\x10\x00\x00\u07d4\xc0~8g\xad\xa0\x96\x80z\x05\x1al\x9c4\xcc;?J\xd3J\x89`\xf0f \xa8IE\x00\x00\u07d4\xc0\x89^\xfd\x05m\x9a:\x81\xc3\xdaW\x8a\xda1\x1b\xfb\x93V\u03c9\n\u05ce\xbcZ\xc6 \x00\x00\u07d4\xc0\x90\xfe#\xdc\xd8k5\x8c2\xe4\x8d*\xf9\x10$%\x9fef\x89\n\u05ce\xbcZ\xc6 \x00\x00\u07d4\xc0\x9af\x17*\xea7\r\x9ac\xda\x04\xffq\xff\xbb\xfc\xff\u007f\x94\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\xc0\x9e<\xfc\x19\xf6\x05\xff>\xc9\xc9\xc7\x0e%@\xd7\xee\x97Cf\x89\x1b\x1a\xe4\xd6\xe2\xefP\x00\x00\u07d4\xc0\xa0*\xb9N\xbeV\xd0E\xb4\x1bb\x9b\x98F.:\x02J\x93\x89\x05k\xc7^-c\x10\x00\x00\u07d4\xc0\xa3\x93\b\xa8\x0e\x9e\x84\xaa\xaf\x16\xac\x01\xe3\xb0\x1dt\xbdk-\x89\afM\xddL\x1c\v\x80\x00\u07d4\xc0\xa6\u02edwi*=\x88\xd1A\xefv\x9a\x99\xbb\x9e<\x99Q\x89\x05k\xc7^-c\x10\x00\x00\xe0\x94\xc0\xa7\xe8C]\xff\x14\xc2Uws\x9d\xb5\\$\u057fW\xa3\u064a\nm\xd9\f\xaeQ\x14H\x00\x00\u07d4\xc0\xae\x14\xd7$\x83./\xce'x\xde\u007f{\x8d\xaf{\x12\xa9>\x89\x01\x15\x8eF\t\x13\xd0\x00\x00\u07d4\xc0\xaf\xb7\u0637\x93p\xcf\xd6c\u018c\u01b9p*7\u035e\xff\x8965\u026d\xc5\u07a0\x00\x00\u07d4\xc0\xb0\xb7\xa8\xa6\xe1\xac\xdd\x05\xe4\u007f\x94\xc0\x96\x88\xaa\x16\u01ed\x8d\x89\x03{m\x02\xacvq\x00\x00\xe0\x94\xc0\xb3\xf2D\xbc\xa7\xb7\xde[H\xa5>\u06dc\xbe\xab\vm\x88\xc0\x8a\x01;\x80\xb9\x9cQ\x85p\x00\x00\u07d4\xc0\xc0M\x01\x06\x81\x0e>\xc0\xe5J\x19\U000ab157\xe6\x9aW=\x89\x02\xb5\xe3\xaf\x16\xb1\x88\x00\x00\u07d4\xc0\xca2w\x94.tE\x87K\xe3\x1c\xeb\x90)rqO\x18#\x89\r\x8drkqw\xa8\x00\x00\u07d4\xc0\u02ed<\xcd\xf6T\xda\"\xcb\xcf\\xe\x97\xca\x19U\xc1\x15\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\xc0\xcb\xf6\x03/\xa3\x9e|F\xffw\x8a\x94\xf7\xd4E\xfe\"\xcf0\x89\x10\xce\x1d=\x8c\xb3\x18\x00\x00\u07d4\xc0\xe0\xb9\x03\b\x8e\fc\xf5=\xd0iWTR\xaf\xf5$\x10\u00c9\xa2\xa1]\tQ\x9b\xe0\x00\x00\u07d4\xc0\xe4W\xbdV\xec6\xa1$k\xfa20\xff\xf3\x8eY&\xef\"\x89i*\xe8\x89p\x81\xd0\x00\x00\u07d4\xc0\xed\rJ\xd1\r\xe045\xb1S\xa0\xfc%\xde;\x93\xf4R\x04\x89\xabM\xcf9\x9a:`\x00\x00\u07d4\xc0\xf2\x9e\xd0\af\x11\xb5\xe5^\x13\x05G\xe6\x8aH\xe2m\xf5\u4262\xa1]\tQ\x9b\xe0\x00\x00\u07d4\xc1\x13(x#\\]\u06e5\xd9\xf3\"\x8bR6\xe4p \xdco\x8965\u026d\xc5\u07a0\x00\x00\u07d4\xc1\x17\r\xba\xad\xb3\xde\xe6\x19\x8e\xa5D\xba\xec\x93%\x18`\xfd\xa5\x89A\rXj \xa4\xc0\x00\x00\xe0\x94\xc1&W=\x87\xb0\x17ZR\x95\xf1\xdd\a\xc5u\u03cc\xfa\x15\xf2\x8a\x02\x1e\x19\xe0\u027a\xb2@\x00\x00\u07d4\xc1'\xaa\xb5\x90e\xa2\x86D\xa5k\xa3\xf1^.\xac\x13\xda)\x95\x89 \x86\xac5\x10R`\x00\x00\xe0\x94\xc1+\u007f@\u07da/{\xf9\x83f\x14\"\xab\x84\xc9\xc1\xf5\bX\x8a\x01\xb1\xaeMn.\xf5\x00\x00\x00\u07d4\xc1,\xfb{=\xf7\x0f\xce\xca\x0e\xde&5\x00\xe2xs\xf8\xed\x16\x8965\u026d\xc5\u07a0\x00\x00\u07d4\xc1/\x88\x1f\xa1\x12\xb8\x19\x9e\xcb\xc7>\xc4\x18W\x90\xe6\x14\xa2\x0f\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\xc18Lnq~\xbeK#\x01NQ\xf3\x1c\x9d\xf7\xe4\xe2[1\x89\x1b\x1a\xe4\xd6\xe2\xefP\x00\x00\u07d4\xc1C\x8c\x99\xddQ\xef\x1c\xa88j\xf0\xa3\x17\xe9\xb0AEx\x88\x89\f\x1d\xaf\x81\u0623\xce\x00\x00\u07d4\xc1c\x12(\xef\xbf*.:@\x92\xee\x89\x00\xc69\xed4\xfb\u02093\xc5I\x901r\f\x00\x00\u07d4\xc1u\xbe1\x94\xe6iB-\x15\xfe\xe8\x1e\xb9\xf2\xc5lg\xd9\u0249\n\u05ce\xbcZ\xc6 \x00\x00\u07d4\xc1\x82v\x86\xc0\x16\x94\x85\xec\x15\xb3\xa7\xc8\xc0\x15\x17\xa2\x87M\xe1\x89\x02+\x1c\x8c\x12'\xa0\x00\x00\u07d4\xc1\x8a\xb4g\xfe\xb5\xa0\xaa\xdf\xff\x91#\x0f\xf0VFMx\xd8\x00\x89lk\x93[\x8b\xbd@\x00\x00\u0794\xc1\x95\x05CUM\x8aq0\x03\xf6b\xbba,\x10\xadL\xdf!\x88\xfc\x93c\x92\x80\x1c\x00\x00\u07d4\xc1\xa4\x1aZ'\x19\x92&\xe4\xc7\xeb\x19\x8b\x03\x1bY\x19o\x98B\x89\nZ\xa8P\t\xe3\x9c\x00\x00\u07d4\xc1\xb2\xa0\xfb\x9c\xadE\xcdi\x91\x92\xcd'T\v\x88\xd38By\x89\x1b\x1a\xe4\xd6\xe2\xefP\x00\x00\u07d4\xc1\xb2\xaa\x8c\xb2\xbfb\xcd\xc1:G\xec\xc4e\u007f\xac\xaa\x99_\x98\x8967\x93\xfa\x96\u6980\x00\u07d4\xc1\xb5\x00\x01\x1c\xfb\xa9]|\xd66\xe9^l\xbfagFK%\x89\n\u05ce\xbcZ\xc6 \x00\x00\u07d4\xc1\xb9\xa5pM5\x1c\xfe\x98?y\xab\xee\xc3\u06fb\xae;\xb6)\x89\x01\x15\x8eF\t\x13\xd0\x00\x00\u07d4\xc1\xcb\xd2\xe23*RL\xf2\x19\xb1\r\x87\x1c\xcc \xaf\x1f\xb0\xfa\x8965\u026d\xc5\u07a0\x00\x00\xe0\x94\xc1\xcd\xc6\x01\xf8\x9c\x04(\xb3\x13\x02\u0447\xe0\xdc\b\xad}\x1cW\x8a\x01EB\xba\x12\xa37\xc0\x00\x00\xe0\x94\xc1\u052f8\xe9\xbay\x90@\x89HI\xb8\xa8!\x93u\xf1\xacx\x8a\x04<3\xc1\x93ud\x80\x00\x00\u07d4\xc1\xe1@\x9c\xa5,%CQ4\xd0\x06\u00a6\xa8T-\xfbrs\x89\x01\xdd\x1eK\xd8\xd1\xee\x00\x00\u07d4\xc1\xeb\xa5hJ\xa1\xb2L\xbac\x15\x02c\xb7\xa9\x13\x1a\xee\u008d\x89\x01\x15\x8eF\t\x13\xd0\x00\x00\u07d4\xc1\xec\x81\xdd\x12=K|-\u0674\xd48\xa7\a,\x11\u0707L\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\xc1\xf3\x9b\xd3]\xd9\xce\xc37\xb9oG\xc6w\x81\x81`\xdf7\xb7\x89\x01\x15\x8eF\t\x13\xd0\x00\x00\u0794\xc1\xff\xad\a\u06d6\x13\x8cK*S\x0e\xc1\xc7\xde)\xb8\xa0Y,\x88\xf4?\xc2\xc0N\xe0\x00\x00\xe0\x94\xc2\x1f\xa6d:\x1f\x14\xc0)\x96\xadqD\xb7Y&\xe8~\xcbK\x8a\x04<3\xc1\x93ud\x80\x00\x00\u07d4\xc24\nL\xa9L\x96x\xb7IL<\x85%(\xed\xe5\xeeR\x9f\x89\x02\xa3k\x05\xa3\xfd|\x80\x00\u07d4\xc29\xab\u07ee>\x9a\xf5E\u007fR\xed+\x91\xfd\n\xb4\xd9\xc7\x00\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\xc2;/\x92\x1c\xe4\xa3z%\x9e\u4b4b!X\xd1]fOY\x89\x01`\x89\x95\xe8\xbd?\x80\x00\u07d4\xc2C\x99\xb4\xbf\x86\xf73\x8f\xbfd^;\"\xb0\u0dd79\x12\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\xc2L\u03bc#D\xcc\xe5d\x17\xfbhL\xf8\x16\x13\xf0\xf4\xb9\xbd\x89T\x06\x923\xbf\u007fx\x00\x00\u07d4\xc2Rf\xc7gf2\xf1>\xf2\x9b\xe4U\ud50a\xddVw\x92\x89Hz\x9a0E9D\x00\x00\u07d4\xc2\\\xf8&U\f\x8e\xaf\x10\xaf\"4\xfe\xf9\x04\u0779R\x13\xbe\x8965\u026d\xc5\u07a0\x00\x00\u07d4\xc2f?\x81E\xdb\xfe\xc6\xc6F\xfc\\I\x96\x13E\xde\x1c\x9f\x11\x89%g\xacp9+\x88\x00\x00\u07d4\xc2pEh\x854+d\vL\xfc\x1bR\x0e\x1aTN\xe0\xd5q\x89b\xa9\x92\xe5:\n\xf0\x00\x00\u07d4\xc2sv\xf4]!\xe1^\xde;&\xf2e_\xce\xe0,\xcc\x0f*\x89\x01\x15\x8eF\t\x13\xd0\x00\x00\xe0\x94\xc2w\x97q\xf0Smy\xa8p\x8fi1\xab\xc4K05\u964a\x04<O\x83\x00\u0733H\x00\x00\u07d4\xc2\u007fN\b\t\x9d\x8c\xf3\x9e\xe1\x16\x01\x83\x8e\xf9\xfc\x06\xd7\xfcA\x89a\t=|,m8\x00\x00\u07d4\u0082\xe6\x99?\xbez\x91.\xa0G\x15?\xfd\x92t'\x0e([\x89\a\x96\v3\x12Gc\x80\x00\u07d4\u0083a\x88\u0662\x92S\xe0\xcb\xdaeq\xb0X\u0089\xa0\xbb2\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\u00aat\x84~\x86\xed\xfd\xd3\xf3\xdb\"\xf8\xa2\x15/\xee\xe5\xb7\xf7\x89o\x11\x88\x86\xb7\x84\xa2\x00\x00\xe0\x94\u00b2\xcb\xe6[\xc6\xc2\xeez<u\xb2\xe4|\x18\x9c\x06.\x8d\x8b\x8a\x04<3\xc1\x93ud\x80\x00\x00\xe0\x94\u00ba\xe4\xa23\xc2\xd8W$\xf0\u06be\xbd\xa0$\x9d\x83>7\u04ca\x01\x0f\f\xf0d\xddY \x00\x00\u07d4\xc2\xc1>r\xd2h\xe7\x15\r\u01d9\xe7\xc6\xcf\x03\u0209T\xce\u05c9%\xf2s\x93=\xb5p\x00\x00\u07d4\xc2\xcb\x1a\xda]\xa9\xa0B8s\x81G\x93\xf1aD\xef6\xb2\xf3\x89HU~;p\x17\xdf\x00\x00\u07d4\xc2\xd1w\x8e\xf6\xee_\xe4\x88\xc1E\xf3Xkn\xbb\xe3\xfb\xb4E\x89>\x1f\xf1\xe0;U\xa8\x00\x00\xe0\x94\xc2\xd9\xee\xdb\xc9\x01\x92c\xd9\xd1l\u016e\a-\x1d=\xd9\xdb\x03\x8a\x04<3\xc1\x93ud\x80\x00\x00\u07d4\xc2\xe0XJq4\x8c\xc3\x14\xb7; )\xb6#\v\x92\u06f1\x16\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\xc2\xe2\u0518\xf7\r\xcd\bY\xe5\v\x02:q\nmK!3\xbd\x8989\x11\xf0\f\xbc\xe1\x00\x00\u07d4\xc2\xed_\xfd\u046d\xd8U\xa2i/\xe0b\xb5\xd6\x18t#`\u0509A\rXj \xa4\xc0\x00\x00\u07d4\xc2\xee\x91\xd3\xefX\xc9\u0465\x89\x84N\xa1\xae1%\xd6\u017ai\x894\x95tD\xb8@\xe8\x00\x00\u07d4\xc2\xfa\xfd\xd3\n\xcbmg\x06\xe9)<\xb0&A\xf9\xed\xbe\a\xb5\x89Q\x00\x86\vC\x0fH\x00\x00\u07d4\xc2\xfd\v\xf7\xc7%\xef>\x04~Z\xe1\u009f\xe1\x8f\x12\xa7)\x9c\x89Hz\x9a0E9D\x00\x00\u07d4\xc2\xfe}us\x1fcm\xcd\t\xdb\xda\x06q9;\xa0\xc8*}\x89wC\"\x17\xe6\x83`\x00\x00\u07d4\xc3\x10z\x9a\xf32-R8\xdf\x012A\x911b\x959W}\x89\x1a\xb4\xe4d\xd4\x141\x00\x00\xe0\x94\xc3\x11\v\xe0\x1d\xc9sL\xfcn\x1c\xe0\u007f\x87\xd7}\x13E\xb7\xe1\x8a\x01\x0f\f\xe9I\xe0\x0f\x93\x00\x00\u07d4\xc3 8\xcaR\xae\xe1\x97E\xbe\\1\xfc\xdcT\x14\x8b\xb2\xc4\u0409\x02\xb5\xaa\xd7,e \x00\x00\u07d4\xc3%\xc3R\x80\x1b\xa8\x83\xb3\"l_\xeb\r\xf9\xea\xe2\xd6\xe6S\x89\u0556{\xe4\xfc?\x10\x00\x00\u07d4\xc3.\xc7\xe4*\xd1l\xe3\xe2UZ\xd4\xc5C\x06\xed\xa0\xb2gX\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\xc32\xdfP\xb1<\x014\x90\xa5\xd7\xc7]\xbf\xa3f\u0687\xb6\u0589\xd8\xd7&\xb7\x17z\x80\x00\x00\u07d4\xc3:\u0373\xba\x1a\xab'P{\x86\xb1]g\xfa\xf9\x1e\xcfb\x93\x89lk\x93[\x8b\xbd@\x00\x00\xe0\x94\xc3>\u0393Z\x8fN\xf98\xea~\x1b\xac\x87\u02d2]\x84\x90\u028a\a\x03\x8c\x16x\x1fxH\x00\x00\u07d4\xc3@\xf9\xb9\x1c&r\x8c1\xd1!\xd5\xd6\xfc;\xb5m=\x86$\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\xc3F\xcb\x1f\xbc\xe2\xab(]\x8eT\x01\xf4-\xd7#M7\xe8m\x89\x04\x86\u02d7\x99\x19\x1e\x00\x00\xe0\x94\xc3H=n\x88\xac\x1fJ\xe7<\xc4@\x8dl\x03\xab\xe0\xe4\x9d\u028a\x03\x99\x92d\x8a#\u0220\x00\x00\xe0\x94\xc3H\xfcZF\x13#\xb5{\xe3\x03\u02c96\x1b\x99\x19\x13\xdf(\x8a\x15-\x02\xc7\xe1J\xf6\x80\x00\x00\u07d4\xc3N;\xa12.\xd0W\x11\x83\xa2O\x94 N\xe4\x9c\x18fA\x89\x03'\xaf\uf927\xbc\x00\x00\xe0\x94\xc3[\x95\xa2\xa3s|\xb8\xf0\xf5\x96\xb3E$\x87+\xd3\r\xa24\x8a\x01\x98\xbe\x85#^-P\x00\x00\xe0\x94\xc3c\x1cv\x98\xb6\xc5\x11\x19\x89\xbfE''\xb3\xf99Zm\xea\x8a\x02C'X\x96d\x1d\xbe\x00\x00\u07d4\xc3l\vc\xbf\xd7\\/\x8e\xfb\x06\b\x83\xd8h\xcc\xcdl\xbd\xb4\x89\xa2\xa1]\tQ\x9b\xe0\x00\x00\xe0\x94\xc3uk\xcd\xcc~\xect\xed\x89j\xdf\xc35'Y0&n\b\x8a\x01EB\xba\x12\xa37\xc0\x00\x00\u07d4\u00c4\xacn\xe2|9\xe2\xf2x\xc2 \xbd\xfa[\xae\xd6&\xd9\u04c9 \x86\xac5\x10R`\x00\x00\u07d4\u00e0F\xe3\u04b2\xbfh\x14\x88\x82n2\xd9\xc0aQ\x8c\xfe\x8c\x89\x8c\xf2?\x90\x9c\x0f\xa0\x00\x00\u07d4\u00e9\"j\xe2u\xdf,\xab1+\x91\x10@cJ\x9c\x9c\x9e\xf6\x89\xd8\xd7&\xb7\x17z\x80\x00\x00\u07d4\u00f9(\xa7o\xadex\xf0O\x05U\xe69R\xcd!\xd1R\n\x89lk\x93[\x8b\xbd@\x00\x00\xe0\x94\xc3\xc2)s)\xa6\xfd\x99\x11~T\xfcj\xf3y\xb4\xd5VT~\x8a\x01EB\xba\x12\xa37\xc0\x00\x00\u07d4\xc3\xc3\xc2Q\rg\x80 HZcs]\x13\a\xecL\xa60+\x8965\u026d\xc5\u07a0\x00\x00\u07d4\xc3\xcbk6\xafD?,n%\x8bJ9U:\x81\x87G\x81\x1f\x89WG=\x05\u06ba\xe8\x00\x00\xe0\x94\xc3\xdbVW\xbbr\xf1\rX\xf21\xfd\xdf\x11\x98\n\xffg\x86\x93\x8a\x01@a\xb9\xd7z^\x98\x00\x00\xe0\x94\xc3\u06df\xb6\xf4lH\n\xf3De\u05d7S\xb4\xe2\xb7Jg\u038a\x04<3\xc1\x93ud\x80\x00\x00\u07d4\xc3\xddX\x908\x860;\x92\x86%%z\xe1\xa0\x13\xd7\x1a\xe2\x16\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\xc3\xe0G\x1cd\xff5\xfaR2\xcc1!\xd1\u04cd\x1a\x0f\xb7\u0789lk\x93[\x8b\xbd@\x00\x00\u07d4\xc3\xe2\f\x96\u07cdN8\xf5\v&Z\x98\xa9\x06\xd6\x1b\xc5\x1aq\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\xc3\u31f0<\xe9\\\xcf\xd7\xfaQ\u0744\x01\x83\xbcCS(\t\x89lk\x93[\x8b\xbd@\x00\x00\xe0\x94\xc3\xf8\xf6r\x95\xa5\xcd\x04\x93d\xd0]#P&#\xa3\xe5.\x84\x8a\x01EB\xba\x12\xa37\xc0\x00\x00\u07d4\xc4\x01\xc4'\xcc\xcf\xf1\r\xec\xb8d /6\xf5\x80\x83\"\xa0\xa8\x89\xb4{Q\xa6\x9c\xd4\x02\x00\x00\u07d4\xc4\b\x8c\x02_>\x85\x01?T9\xfb4@\xa1s\x01\xe5D\xfe\x89~\t\xdbM\x9f?4\x00\x00\u07d4\xc4\x14a\xa3\u03fd2\u0246UU\xa4\x8117\xc0v1#`\x8965\xc6 G9\u0640\x00\u07d4\xc4 8\x8f\xbe\xe8J\xd6V\xddh\xcd\xc1\xfb\xaa\x93\x92x\v4\x89\n-\xcac\xaa\xf4\u0140\x00\u07d4\xc4\"P\xb0\xfeB\xe6\xb7\xdc\xd5\u0210\xa6\xf0\u020f__\xb5t\x89\b\x1e\xe4\x82SY\x84\x00\x00\u07d4\xc4-j\xebq\x0e:P\xbf\xb4Ml1\t)i\xa1\x1a\xa7\xf3\x89\b\"c\xca\xfd\x8c\xea\x00\x00\xe0\x94\xc4@\xc7\xca/\x96Kir\xeffJ\"a\xdd\xe8\x92a\x9d\x9c\x8a\x04<3\xc1\x93ud\x80\x00\x00\xe0\x94\xc4K\xde\xc8\xc3l\\h\xba\xa2\xdd\xf1\xd41i2)rlC\x8a\x15-\x02\xc7\xe1J\xf6\x80\x00\x00\u07d4\xc4OJ\xb5\xbc`9|s~\xb0h3\x91\xb63\xf8<H\xfa\x8965\u026d\xc5\u07a0\x00\x00\u07d4\xc4R\xe0\xe4\xb3\u05ae\x06\xb86\xf02\xca\t\xdb@\x9d\xdf\xe0\xfb\x89+^:\xf1k\x18\x80\x00\x00\u07d4\xc4Z\x1c\xa1\x03k\x95\x00A\x87\u036cD\xa3n3\xa9J\xb5\u00c9\r\xd0\x0fr\x03\x01\x88\x00\x00\u07d4\xc4]G\xab\f\x9a\xa9\x8a[\xd6-\x16\">\xa2G\x1b\x12\x1c\xa4\x89 .h\xf2\u00ae\xe4\x00\x00\u07d4\xc4h\x1es\xbb\x0e2\xf6\xb7& H1\xffi\xba\xa4\x87~2\x89b\xa9\x92\xe5:\n\xf0\x00\x00\u07d4\xc4k\xbd\xefv\xd4\xca`\xd3\x16\xc0\u007f]\x1ax\x0e;\x16_~\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\xc4}a\v9\x92P\xf7\x0e\xcf\x13\x89\xba\xb6),\x91&O#\x89\x0f\xa7\xe7\xb5\xdf<\xd0\x00\x00\u07d4\u0100;\xb4\a\xc7b\xf9\vu\x96\xe6\xfd\u1513\x1ev\x95\x90\x89\xd8\xd7&\xb7\x17z\x80\x00\x00\u07d4\u0106Q\xc1\xd9\xc1k\xffL\x95T\x88l??&C\x1foh\x89#\xab\x95\x99\xc4?\b\x00\x00\u07d4\u0109\xc8?\xfb\xb0%*\xc0\xdb\xe3R\x12\x17c\x0e\x0fI\x1f\x14\x89\xd8\xd7&\xb7\x17z\x80\x00\x00\u07d4\u010bi<\xac\xef\xdb\xd6\xcb]x\x95\xa4.1\x962~&\x1c\x8965\u026d\xc5\u07a0\x00\x00\u07d4\u0113H\x9eV\u00fd\xd8)\x00}\xc2\xf9VA)\x06\xf7k\xfa\x89\x02\xa7\x91H\x8eqT\x00\x00\u07d4\u0116\u02f0E\x9aj\x01`\x0f\u0149\xa5Z2\xb4T!\u007f\x9d\x89\x0e\u0683\x8cI)\b\x00\x00\u07d4\u011c\xfa\xa9g\xf3\xaf\xbfU\x03\x10a\xfcL\xef\x88\xf8]\xa5\x84\x89lk\x93[\x8b\xbd@\x00\x00\xe0\x94\u0136\xe5\xf0\x9c\xc1\xb9\r\xf0x\x03\xce=M\x13vj\x9cF\xf4\x8a\x01EB\xba\x12\xa37\xc0\x00\x00\xe0\x94\u013e\xc9c\b\xa2\x0f\x90\u02b1\x83\x99\u0113\xfd=\x06Z\xbfE\x8a\x02\xf6\xf1\a\x80\xd2,\xc0\x00\x00\xe0\x94\xc4\xc0\x1a\xfc>\x0f\x04R!\xda\x12\x84\u05c7\x85tD/\xb9\xac\x8a\x01\x92<h\x8bs\xab\x04\x00\x00\u07d4\xc4\xc1S\x18\xd3p\xc73\x18\xcc\x18\xbd\xd4f\u06eaLf\x03\xbf\x89\x01\x11du\x9f\xfb2\x00\x00\u07d4\xc4\xc6\xcbr=\u05ef\xa7\xebSV\x15\xe5?<\xef\x14\xf1\x81\x18\x89lk\x8f\xce\r\x18y\x80\x00\u07d4\xc4\xccE\xa2\xb6<'\xc0\xb4B\x9eX\xcdB\xdaY\xbes\x9b\u058965\u026d\xc5\u07a0\x00\x00\u07d4\xc4\u03d3\x0e]\x11j\xb8\xd1;\x9f\x9a~\u012bP\x03\xa6\xab\u0789\x11X\xe4`\x91=\x00\x00\x00\u07d4\xc4\xd9\x16WNh\u011f~\xf9\xd3\xd8-\x168\xb2\xb7\xee\t\x85\x89U\xa6\xe7\x9c\xcd\x1d0\x00\x00\xe0\x94\xc4\xda\u0168\xa0&O\xbc\x10U9\x1cP\x9c\xc3\xee!\xa6\xe0L\x8a\x01`k\u007f\xa09\xcet\x00\x00\u07d4\xc4\xdd\x04\x8b\xfb\x84\x0e+\xc8\\\xb5?\xcbu\xab\xc4C\xc7\xe9\x0f\x89\xc9q\xdc\a\xc9\u01d0\x00\x00\u07d4\xc4\xf2\x91;&\\C\x0f\xa1\xab\x8a\xdf&\xc33\xfc\x1d\x9bf\xf2\x89\x01\x15\x8eF\t\x13\xd0\x00\x00\u07d4\xc4\xf7\xb1:\xc6\xd4\xebM\xb3\xd4\xe6\xa2R\xaf\x8a\a\xbdYW\u0689\n\u05ce\xbcZ\xc6 \x00\x00\u07d4\xc4\xf7\xd2\xe2\xe2 \x84\xc4Op\xfe\xaa\xb6\xc3!\x05\xf3\xda7o\x89j\xcb=\xf2~\x1f\x88\x00\x00\u07d4\xc4\xffo\xbb\x1f\t\xbd\x9e\x10+\xa03\xd66\xac\x1cL\x0fS\x04\x8965\u026d\xc5\u07a0\x00\x00\u07d4\xc4\xff\xad\xaa\xf2\x82?\xbe\xa7\xbf\xf7\x02\x02\x1b\xff\u0105>\xb5\u0249\x02J\x19\xc1\xbdo\x12\x80\x00\xe0\x94\xc5\x00\xb7 sN\xd2)8\u05cc^H\xb2\xba\x93g\xa5u\xba\x8a\a\x12\x9e\x1c\xdf7>\xe0\x00\x00\u07d4\xc5\x0f\xe4\x15\xa6A\xb0\x85lNu\xbf\x96\x05\x15D\x1a\xfa5\x8d\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\xc5\x13L\xfb\xb1\xdfz \xb0\xedpWb.\xee\u0480\x94}\xad\x89\xcd\xff\x97\xfa\xbc\xb4`\x00\x00\xe0\x94\xc5\x17\xd01\\\x87\x88\x13\xc7\x17\u132f\xa1\xea\xb2eN\x01\u068a\x02\x1e\x19\xe0\u027a\xb2@\x00\x00\u07d4\xc5\x18y\x9aY%Wb\x13\xe2\x18\x96\xe0S\x9a\xbb\x85\xb0Z\xe3\x8965\u026d\xc5\u07a0\x00\x00\u07d4\xc5\"\xe2\x0f\xbf\x04\xed\u007fk\x05\xa3{G\x18\xd6\xfc\xe0\x14.\x1a\x89\xd8\xd7&\xb7\x17z\x80\x00\x00\u07d4\xc5$\bmF\xc8\x11+\x12\x8b/\xafo|}\x81`\xa88l\x89\x15\xaf\x1dx\xb5\x8c@\x00\x00\u07d4\xc5-\x1a\fs\u00a1\xbe\x84\x91Q\x85\xf8\xb3O\xaa\n\xdf\x1d\xe3\x89K\xe4\xea\xb3\xfa\x0f\xa6\x80\x00\xe0\x94\xc55\x94\xc7\u03f2\xa0\x8f(L\xc9\u05e6;\xbd\xfc\v1\x972\x8a\nk#(\xff:b\xc0\x00\x00\u07d4\xc57I(\xcd\xf1\x93pTC\xb1L\xc2\r\xa4#G<\xd9\u03c9\a}\x10P\x9b\xb3\xaf\x80\x00\u07d4\xc58\xa0\xff(*\xaa_Ku\u03f6,p\x03~\xe6}O\xb5\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\xc5;P\xfd;+r\xbclC\v\xaf\x19JQU\x85\u04d8m\x89\x01\x15\x8eF\t\x13\xd0\x00\x00\xe0\x94\xc5=y\xf7\u02dbp\x95/\xd3\x0f\xceX\xd5K\x9f\vY\xf6G\x8a\x01\x13\xe2\xd6tCE\xf8\x00\x00\u07d4\xc5I\u07c3\xc6\xf6^\xec\x0f\x1d\u0260\x93J\\_:P\xfd\x88\x89\x9d\xc0\\\xce(\u00b8\x00\x00\u07d4\xc5P\x05\xa6\xc3~\x8c\xa7\xe5C\xce%\x99s\xa3\xca\u0396\x1aJ\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\xc5U\xb91V\xf0\x91\x01#<o|\xf6\xeb<O\x19m3F\x89\xa2\xa1]\tQ\x9b\xe0\x00\x00\u07d4\xc5ZkGa\xfd\x11\xe8\xc8_\x15\x17Mtv|\u063d\x9ah\x89\a?u\u0460\x85\xba\x00\x00\u07d4\xc5nkb\xban@\xe5*\xab\x16}!\xdf\x02]\x00UuK\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\xc5s\xe8A\xfa\b\x17J \x8b\x06\f\xcb{L\rv\x97\x12\u007f\x89$=M\x18\"\x9c\xa2\x00\x00\u07d4\xc5v\x12\u0791\x11\fH.oP[\xcd#\xf3\xc5\x04}\x1da\x89\xc2\x12z\xf8X\xdap\x00\x00\u07d4\u01443\x99\xd1P\x06k\xf7\x97\x9c4\xba)F 6\x8a\xd7\xc0\x89\n\u05ce\xbcZ\xc6 \x00\x00\u07d4\u014b\x9c\xc6\x1d\xed\xbb\x98\xc3?\"M'\x1f\x0e\"\x8bX43\x89\xd2U\xd1\x12\xe1\x03\xa0\x00\x00\u07d4\u014fb\xfe\xe9q\x1ej\x05\xdc\t\x10\xb6\x18B\n\xa1'\xf2\x88\x89\xd7\xc1\x98q\x0ef\xb0\x00\x00\u07d4\u0153\xb5F\xb7i\x87\x10\xa2\x05\xadF\x8b,\x13\x15\"\x19\xa3B\x89T\x06\x923\xbf\u007fx\x00\x00\xe0\x94\u0153\xd6\xe3}\x14\xb5fd:\xc4\x13_$<\xaa\a\x87\xc1\x82\x8a\x02\x8a\x85t%Fo\x80\x00\x00\xe0\x94\u0163\xb9\x8eE\x93\xfe\xa0\xb3\x8cOEZPe\xf0Q\xa2\xf8\x15\x8a\x04L\xf4h\xaf%\xbfw\x00\x00\u07d4\u0164\x8a\x85\x00\xf9\xb4\xe2/\x0e\xb1loFIhvt&}\x89,\x0e\xc5\x03\x85\x04>\x80\x00\xe0\x94\u0166)\xa3\x96%R\u02ce\xde\u0609cj\xaf\xbd\f\x18\xcee\x8a\x02\x1e\x19\xe0\u027a\xb2@\x00\x00\u07d4\u016e\x86\xb0\xc6\xc7\xe3\x90\x0f\x13h\x10\\VS\u007f\xaf\x8dt>\x89\n1\x06+\xee\xedp\x00\x00\u07d4\u0170\t\xba\xea\xf7\x88\xa2v\xbd5\x81:\xd6[@\v\x84\x9f;\x8965\u026d\xc5\u07a0\x00\x00\u07d4\u0175l\xd24&|(\xe8\x9cok\"f\xb0\x86\xa1/\x97\f\x89\xd8\xd7&\xb7\x17z\x80\x00\x00\xe0\x94\xc5\u01a4\x99\x8a3\xfe\xb7dCz\x8b\xe9)\xa7;\xa3J\ad\x8a\n\x96\x81c\xf0\xa5{@\x00\x00\xe0\x94\xc5\xc7=a\xcc\xe7\xc8\xfeL\x8f\xce)\xf3\x90\x92\xcd\x19>\x0f\xff\x8a\x01\xb1\xaeMn.\xf5\x00\x00\x00\u07d4\xc5\xc7Y\vV!\xec\xf85\x85\x88\u079bh\x90\xf2baC\U000498a1]\tQ\x9b\xe0\x00\x00\u07d4\xc5\xcd\xce\xe0\xe8]\x11}\xab\xbfSj?@i\xbfD?T\xe7\x89j\xc5\xc6-\x94\x86\a\x00\x00\u07d4\xc5\u050c\xa2\xdb/\x85\xd8\xc5U\xcb\x0e\x9c\xfe\x82i6x?\x9e\x89\n\u05ce\xbcZ\xc6 \x00\x00\xe0\x94\xc5\xde\x12\x03\xd3\xcc,\xea1\xc8.\xe2\xdeY\x16\x88\a\x99\xea\xfd\x8a\x01\x0f\f\xf0d\xddY \x00\x00\u07d4\xc5\xe4\x88\xcf+Vw\x939q\xf6L\xb8 -\xd0WR\xa2\xc0\x8965\u026d\xc5\u07a0\x00\x00\u07d4\xc5\xe8\x12\xf7o\x15\xf2\xe1\xf2\xf9\xbcH#H<\x88\x04cog\x89\x03\xf5\x14\x19:\xbb\x84\x00\x00\u07d4\xc5\u94d34\xf1%.\u04ba&\x81D\x87\xdf\u0498+1(\x89\x03\xcbq\xf5\x1f\xc5X\x00\x00\u07d4\xc5\xebB)^\x9c\xad\xea\xf2\xaf\x12\xde\u078a\x8dS\xc5y\xc4i\x89\xcf\x15&@\xc5\xc80\x00\x00\xe0\x94\xc5\xed\xbb\xd2\xca\x03WeJ\xd0\xeaG\x93\xf8\xc5\xce\xcd0\xe2T\x8a\x01EB\xba\x12\xa37\xc0\x00\x00\u07d4\xc5\xf6K\xab\xb7\x031B\xf2\x0eF\u05eab\x01\xed\x86\xf6q\x03\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\xc5\xf6\x87qrF\u068a \r \xe5\u9f2c`\xb6\u007f8a\x89\x01\x8d\x99?4\xae\xf1\x00\x00\u07d4\xc6\x04[<5\vL\xe9\xca\fkuO\xb4\x1ai\xb9~\x99\x00\x892$\xf4'#\xd4T\x00\x00\u07d4\xc6\v\x04eN\x00;F\x83\x04\x1f\x1c\xbdk\u00cf\xda|\xdb\u0589lk\x93[\x8b\xbd@\x00\x00\u07d4\xc6\x14F\xb7T\xc2N;\x16B\xd9\xe5\x17e\xb4\xd3\xe4k4\xb6\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\xc6\x18R\x13!\xab\xaf[&Q:J\x95(\bo\"\n\xdco\x89\x01v\xb3D\xf2\xa7\x8c\x00\x00\u07d4\xc6#FW\xa8\a8A&\xf8\x96\x8c\xa1p\x8b\xb0{\xaaI<\x89\x01\x15\x8eF\t\x13\xd0\x00\x00\u07d4\xc6%\xf8\u024d'\xa0\x9a\x1b\u02bdQ(\xb1\u00a9HV\xaf0\x89\n\u05ce\xbcZ\xc6 \x00\x00\xe0\x94\xc65^\xc4v\x8cp\xa4\x9a\xf6\x95\x13\u0343\xa5\xbc\xa7\xe3\xb9\u034a\x01EB\xba\x12\xa37\xc0\x00\x00\u07d4\xc6:\xc4\x17\x99.\x9f\x9b`8n\xd9S\xe6\xd7\xdf\xf2\xb0\x90\xe8\x89\xd8\xd8X?\xa2\xd5/\x00\x00\u07d4\xc6<\u05c8!\x18\xb8\xa9\x1e\aML\x8fK\xa9\x18Q0;\x9a\x89\x0e\x189\x8ev\x01\x90\x00\x00\u07d4\xc6R\x87\x1d\x19$\"\u01bc#_\xa0c\xb4J~\x1dC\u3149\bg\x0e\x9e\xc6Y\x8c\x00\x00\xe0\x94\xc6gD\x1e\u007f)y\x9a\xbaadQ\xd5;?H\x9f\x9e\x0fH\x8a\x02\xf2\x9a\xceh\xad\u0740\x00\x00\u07d4\xc6j\xe4\xce\xe8\u007f\xb352\x19\xf7\u007f\x1dd\x86\u0140(\x032\x89\x01\x9a\x16\xb0o\xf8\xcb\x00\x00\u07d4\xc6t\xf2\x8c\x8a\xfd\a?\x8by\x96\x91\xb2\xf0XM\xf9B\xe8D\x89lk\x93[\x8b\xbd@\x00\x00\xe0\x94\u0197\xb7\x04w\u02b4.+\x8b&f\x81\xf4\xaesu\xbb%A\x8a\x01.W2\xba\xba\\\x98\x00\x00\u07d4\u019b\x85U9\xce\x1b\x04qG(\xee\xc2Z7\xf3g\x95\x1d\xe7\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\u019b\xe4@\x13Mb\x80\x98\x01D\xa9\xf6M\x84t\x8a7\xf3I\x89&\u009eG\u0104L\x00\x00\u07d4\u019df<\x8d`\x90\x83\x91\xc8\xd26\x19\x153\xfd\xf7wV\x13\x89\x1aJ\xba\"\\ t\x00\x00\u0794\u01a2\x86\xe0e\xc8_:\xf7H\x12\xed\x8b\u04e8\xce]%\xe2\x1d\x88\xfc\x93c\x92\x80\x1c\x00\x00\u07d4\u01a3\x0e\xf5\xbb3 \xf4\r\xc5\xe9\x81#\rR\xae:\xc1\x93\"\x89\t\xdd\xc1\xe3\xb9\x01\x18\x00\x00\u07d4\u01ae(}\xdb\xe1\x14\x9b\xa1m\xdc\xcaO\xe0j\xa2\uaa48\xa9\x89\x15\xaf\x1dx\xb5\x8c@\x00\x00\u07d4\xc6\xc7\xc1\x917\x98\x97\u075c\x9d\x9a3\x83\x9cJ_b\xc0\x89\r\x89\xd8\xd8T\xb2$0h\x80\x00\xe0\x94\xc6\xcdh\xec56,Z\xd8L\x82\xadN\xdc#!%\x91-\x99\x8a\x05\xe0T\x9c\x962\xe1\xd8\x00\x00\u07d4\xc6\u0615N\x8f?\xc53\xd2\xd20\xff\x02\\\xb4\xdc\xe1O4&\x89\x15\xaf\x1dx\xb5\x8c@\x00\x00\u07d4\xc6\xdb\u06de\xfd^\xc1\xb3xn\x06q\xeb\"y\xb2S\xf2\x15\xed\x8965\u026d\xc5\u07a0\x00\x00\u07d4\xc6\xdf u\xeb\xd2@\xd4Hi\u00bek\u07c2\xe6=N\xf1\xf5\x89\x01\x15\x8eF\t\x13\xd0\x00\x00\u07d4\xc6\xe2\xf5\xaf\x97\x9a\x03\xfdr:\x1bn\xfar\x83\x18\u03dc\x18\x00\x89$=M\x18\"\x9c\xa2\x00\x00\u07d4\xc6\xe3$\xbe\xeb[6v^\xcdFB`\xf7\xf2`\x06\xc5\xc6.\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\xc6\xe4\xcc\fr\x83\xfc\x1c\x85\xbcH\x13\xef\xfa\xafr\xb4\x98#\xc0\x89\x0f\x03\x1e\xc9\xc8}\xd3\x00\x00\xe0\x94\xc6\xee5\x93B)i5)\xdcA\u067bq\xa2IfX\xb8\x8e\x8a\x04+\xf0kx\xed;P\x00\x00\u07d4\xc6\xfb\x1e\xe3t\x17\u0400\xa0\xd0H\x92;\u06ba\xb0\x95\xd0w\u0189\n\u05ce\xbcZ\xc6 \x00\x00\u07d4\xc7\x05'\xd4D\u0110\xe9\xfc?\\\xc4Nf\xebO0k8\x0f\x89\xd8\xd7&\xb7\x17z\x80\x00\x00\u07d4\xc7\r\x85mb\x1e\xc1E0<\nd\x00\xcd\x17\xbb\xd6\xf5\xea\xf7\x89\x01\x15\x8eF\t\x13\xd0\x00\x00\u07d4\xc7\x0f\xa4Uv\xbf\x9c\x86_\x988\x93\x00,AI&\xf6\x10)\x89\x15\xb4\xaa\x8e\x97\x02h\x00\x00\u07d4\xc7\x11E\xe5)\u01e7\x14\xe6y\x03\xeeb\x06\xe4\xc3\x04+g'\x89M\x85<\x8f\x89\b\x98\x00\x00\u07d4\xc7\x1b*=q5\u04a8_\xb5\xa5q\u073ei^\x13\xfcC\u034965\u026d\xc5\u07a0\x00\x00\u07d4\xc7\x1f\x1du\x87?3\u0732\xddK9\x87\xa1-\a\x91\xa5\xce'\x897\b\xba\xed=h\x90\x00\x00\u07d4\xc7\x1f\x92\xa3\xa5J{\x8c/^\xa4C\x05\xfc\u02c4\xee\xe21H\x89\x02\xb5\x9c\xa11\xd2\x06\x00\x00\u07d4\xc7!\xb2\xa7\xaaD\xc2\x12\x98\xe8P9\xd0\x0e.F\x0eg\v\x9c\x89\a\xa1\xfe\x16\x02w\x00\x00\x00\u07d4\xc7,\xb3\x01%\x8e\x91\xbc\b\x99\x8a\x80]\u0452\xf2\\/\x9a5\x89 \t\xc5\u023fo\xdc\x00\x00\xe0\x94\xc76\x8b\x97\t\xa5\xc1\xb5\x1c\n\xdf\x18ze\xdf\x14\xe1+}\xba\x8a\x02\x02o\xc7\u007f\x03\u5b80\x00\u07d4\xc79%\x9e\u007f\x85\xf2e\x9b\xef_`\x9e\xd8k=Yl \x1e\x89\n\u05ce\xbcZ\xc6 \x00\x00\xe0\x94\xc7>!\x12(\"\x15\xdc\ab\xf3+~\x80}\xcd\x1az\xae>\x8a\x01v\f\xbcb;\xb3P\x00\x00\xe0\x94\xc7If\x80B\xe7\x11#\xa6H\x97^\b\xedc\x82\xf8>\x05\xe2\x8a\x02\xf6\xf1\a\x80\xd2,\xc0\x00\x00\u07d4\xc7J9\x95\xf8\a\xde\x1d\xb0\x1a.\xb9\xc6.\x97\xd0T\x8fio\x8965\u026d\xc5\u07a0\x00\x00\u07d4\xc7Pl\x10\x19\x12\x1f\xf0\x8a,\x8c\x15\x91\xa6^\xb4\xbd\xfbJ?\x89 \x86\xac5\x10R`\x00\x00\u07d4\xc7\\7\xce-\xa0k\xbc@\b\x11Y\u01ba\x0f\x97n9\x93\xb1\x89:y#\x15\x1e\xcfX\x00\x00\u07d4\xc7]\"Y0j\xec}\xf0\"v\x8ci\x89\x9ae!\x85\xdb\u0109\xd8\xd7&\xb7\x17z\x80\x00\x00\u07d4\xc7`\x97\x1b\xbc\x18\x1cj|\xf7tA\xf2BG\u045c\xe9\xb4\u03c9lk\x93[\x8b\xbd@\x00\x00\u07d4\xc7a0\xc7<\xb9!\x028\x02\\\x9d\xf9]\v\xe5J\xc6\u007f\xbe\x89QP\xae\x84\xa8\xcd\xf0\x00\x00\u07d4\xc7e\xe0\x04v\x81\tG\x81j\xf1B\xd4m.\u7f28\xccO\x89\x1b\x1a\xe4\xd6\xe2\xefP\x00\x00\u07d4\xc7g^VG\xb9\xd8\xda\xf4\xd3\xdf\xf1\xe5R\xf6\xb0qT\xac8\x89\t\xc2\x00vQ\xb2P\x00\x00\u07d4\xc7{\x01\xa6\xe9\x11\xfa\x98\x8d\x01\xa3\xab3dk\xee\xf9\xc18\xf3\x89'\x1bo\xa5\xdb\xe6\xcc\x00\x00\u07d4\u01c3z\u0420\xbf\x14\x18i7\xac\xe0lUF\xa3j\xa5OF\x89\xd8\xd7&\xb7\x17z\x80\x00\x00\u07d4\u01d8\x06\x03+\xc7\xd8(\xf1\x9a\u01a6@\u018e=\x82\x0f\xa4B\x89\x01\x15\x8eF\t\x13\xd0\x00\x00\u07d4\u01d9\xe3N\x88\xff\x88\xbe}\xe2\x8e\x15\xe4\xf2\xa6=\v3\xc4\u02c9\n\u05ce\xbcZ\xc6 \x00\x00\xe0\x94\u01ddPb\u01d6\xddwa\xf1\xf1>U\x8ds\xa5\x9f\x82\xf3\x8b\x8a\x01\xb1\xaeMn.\xf5\x00\x00\x00\u07d4\u01e0\x18\xf0\x96\x8aQ\xd1\xf6`<\\I\xdcT[\xcb\x0f\xf2\x93\x89\xd8\xd7&\xb7\x17z\x80\x00\x00\u07d4\u01ef\xf9\x19)yt\x89UZ/\xf1\xd1M\\iZ\x10\x83U\x8965\u026d\xc5\u07a0\x00\x00\u0794\u01f1\xc8>c ?\x95G&>\xf6(.}\xa3;n\xd6Y\x88\xfc\x93c\x92\x80\x1c\x00\x00\xe0\x94\u01f3\x9b\x06\x04Q\x00\f\xa1\x04\x9b\xa1T\xbc\xfa\x00\xff\x8a\xf2b\x8a\x15-\x02\xc7\xe1J\xf6\x80\x00\x00\u07d4\u01ff\x17\xc4\xc1\x1f\x98\x94\x1fP~w\bO\xff\xbd-\xbd=\xb5\x8965\u026d\xc5\u07a0\x00\x00\xe0\x94\u01ff.\xd1\xed1)@\xeej\xde\xd1Qn&\x8eJ`HV\x8a\x01EB\xba\x12\xa37\xc0\x00\x00\u07d4\xc7\xd4O\xe3,\u007f\x8c\xd5\xf1\xa9t'\xb6\xcd:\xfc\x9eE\x02>\x89U\xa6\xe7\x9c\xcd\x1d0\x00\x00\u07d4\xc7\xd5\xc7\x05@\x81\xe9\x18\xech{Z\xb3n\x97=\x18\x13)5\x89\t\xdd\xc1\xe3\xb9\x01\x18\x00\x00\u07d4\xc7\xde^\x8e\xaf\xb5\xf6+\x1a\n\xf2\x19\\\xf7\x93\u01c9L\x92h\x8965\u026d\xc5\u07a0\x00\x00\u07d4\xc7\xe30\xcd\f\x89\n\u025f\xe7q\xfc\xc7\xe7\xb0\t\xb7A=\x8a\x89\xd8\xd7&\xb7\x17z\x80\x00\x00\u07d4\xc7\xea\xc3\x1a\xbc\xe6\xd5\xf1\u07a4\"\x02\xb6\xa6t\x15=\xb4z)\x89 \t\xc5\u023fo\xdc\x00\x00\xe0\x94\xc7\xecb\xb8\x04\xb1\xf6\x9b\x1e0p\xb5\xd3b\xc6/\xb3\t\xb0p\x8a\x02\xc4k\xf5A`f\x11\x00\x00\u07d4\xc7\xf7+\xb7X\x01k7G\x14\u0509\x9b\xce\"\xb4\xae\xc7\n1\x89:&\xc9G\x8f^-\x00\x00\u0794\xc8\v6\u047e\xaf\xba_\xccdM`\xacnF\xed)'\xe7\u0708\xb9\x8b\xc8)\xa6\xf9\x00\x00\u07d4\xc8\x11\xc2\xe9\xaa\x1a\xc3F.\xba^\x88\xfc\xb5\x12\x0e\x9fn,\xa2\x89K\xe6\u0607\xbd\x87n\x00\x00\u07d4\xc8\x17\xdf\x1b\x91\xfa\xf3\x0f\xe3%\x15qr|\x97\x11\xb4]\x8f\x06\x89lj\xccg\u05f1\xd4\x00\x00\u07d4\xc8\x1f\xb7\xd2\x0f\u0480\x01\x92\xf0\xaa\xc1\x98\xd6\u05a3}?\xcb}\x89\x0e\x11I3\x1c-\xde\x00\x00\u07d4\xc8 \xc7\x11\xf0w\x05'8\a\xaa\xaam\xe4M\x0eKH\xbe.\x89\bg\x0e\x9e\xc6Y\x8c\x00\x00\u07d4\xc8#\x1b\xa5\xa4\x11\xa1>\"+)\xbf\xc1\b?v1X\xf2&\x8967\tlK\xcci\x00\x00\u07d4\xc86\xe2Jo\xcf)\x94;6\b\xe6b)\n!_e)\xea\x89\x0f\xd4Pd\xea\xee\x10\x00\x00\xe0\x94\xc8;\xa6\u0755I\xbe\x1d2\x87\xa5\xa6T\xd1\x06\xc3Lk]\xa2\x8a\x01{x\x83\xc0i\x16`\x00\x00\u07d4\xc8>\x9djX%;\uefb7\x93\xe6\xf2\x8b\x05JXI\x1bt\x89\x0fF\u00b6\xf5\xa9\x14\x00\x00\u07d4\xc8A\x88O\xa4x_\xb7s\xb2\x8e\x97\x15\xfa\xe9\x9aQ40]\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\xc8M\x9b\xea\n{\x9f\x14\x02 \xfd\x8b\x90\x97\u03ff\xd5\xed\xf5d\x89\x06\xab\x9e\u0091\xad}\x80\x00\u07d4\xc8RB\x8d+Xd\x97\xac\xd3\fV\xaa\x13\xfbU\x82\xf8D\x02\x893B\xd6\r\xff\x19`\x00\x00\u07d4\xc8S![\x9b\x9f-,\xd0t\x1eX^\x98{_\xb8\f!.\x89T\x06\x923\xbf\u007fx\x00\x00\u07d4\xc8S%\uaca5\x9b>\xd8c\xc8j_)\x06\xa0B)\xff\xa9\x89\x19=\u007f}%=\xe0\x00\x00\u07d4\xc8^\xf2}\x82\x04\x03\x80_\xc9\xed%\x9f\xffd\xac\xb8\xd64j\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\xc8akN\xc0\x91(\xcd\xff9\xd6\u4e6c\x86\xee\xc4q\xd5\xf2\x89\x01\r:\xa56\xe2\x94\x00\x00\xe0\x94\xc8a\x90\x90K\x8d\a\x9e\xc0\x10\xe4b\xcb\xff\xc9\b4\xff\xaa\\\x8a\x02#\x85\xa8'\xe8\x15P\x00\x00\u07d4\xc8q\r~\x8bZ;\u059aB\xfe\x0f\xa8\xb8|5\u007f\xdd\xcd\u0209\xd8\xd7&\xb7\x17z\x80\x00\x00\u07d4\xc8sR\u06e5\x82\xee f\xb9\xc0\x02\xa9b\xe0\x03\x13Ox\xb1\x89\x1b\x1a\xe4\xd6\xe2\xefP\x00\x00\xe0\x94\xc8|w\xe3\xc2J\xde\xcd\xcd\x108\xa3\x8bV\xe1\x8d\xea\u04f7\x02\x8a\x01\xdd\f\x88_\x9a\r\x80\x00\x00\u07d4\xc8}:\xe3\u0607\x04\u066b\x00\t\xdc\xc1\xa0\x06q1\xf8\xba<\x89j\xc5\xc6-\x94\x86\a\x00\x00\xe0\x94\u0201N4R>8\xe1\xf9'\xa7\xdc\xe8FjDz\t6\x03\x8a\x02\x1e\x19\xe0\u027a\xb2@\x00\x00\u07d4\u0202U\xed\xdc\xf5!\xc6\xf8\x1d\x97\xf5\xa4!\x81\xc9\a=N\xf1\x89\x0f\u00d0D\xd0\n*\x80\x00\u07d4\u0205\xa1\x8a\xab\xf4T\x1b{{~\xcd0\xf6\xfa\u619d\x95i\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\u020c\xa1\xe6\xe5\xf4\xd5X\xd17\x80\xf4\x88\xf1\rJ\xd3\x13\r4\x89T\x06\x923\xbf\u007fx\x00\x00\u07d4\u020e\xecT\xd3\x05\xc9(\xcc(H\xc2\xfe\xe251\xac\xb9mI\x89lj\u04c2\xd4\xfba\x00\x00\xe0\x94\u021c\xf5\x04\xb9\xf3\xf85\x18\x1f\xd8BO\\\xcb\xc8\xe1\xbd\xdf}\x8a\x02\x1e\x19\xe0\u027a\xb2@\x00\x00\u07d4\u0222\xc4\xe5\x9e\x1c\u007f\xc5H\x05X\x048\xae\xd3\xe4J\xfd\xf0\x0e\x89\x02b\x9ff\xe0\xc50\x00\x00\u07d4\u022aI\u301f\b\x99\xf2\x8a\xb5~gCp\x9dXA\x903\x89/\xb4t\t\x8fg\xc0\x00\x00\u07d4\u022b\x1a<\xf4l\xb8\xb0d\xdf.\"-9`s\x94 2w\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\u0231\x85\x05%\xd9F\xf2\xae\x84\xf3\x17\xb1Q\x88\xc56\xa5\u0706\x89\x91\x8d\xdc:B\xa3\xd4\x00\x00\u07d4\xc8\xd4\xe1Y\x9d\x03\xb7\x98\t\xe0\x13\n\x8d\u00c4\b\xf0^\x8c\u04c9\x9f\xad\x06$\x12y\x16\x00\x00\u07d4\xc8\xdd'\xf1k\xf2$P\xf5w\x1b\x9f\xe4\xedO\xfc\xb3\t6\xf4\x89\n\xad\xec\x98?\xcf\xf4\x00\x00\u07d4\xc8\xdezVL\u007f@\x12\xa6\xf6\xd1\x0f\u040fG\x89\x0f\xbf\a\u0509\x10CV\x1a\x88)0\x00\x00\u07d4\xc8\xe2\xad\xebT^I\x9d\x98,\f\x11sc\u03b4\x89\u0171\x1f\x895e\x9e\xf9?\x0f\xc4\x00\x00\xe0\x94\xc8\xe5X\xa3\xc5i~o\xb2:%\x94\u0200\xb7\xa1\xb6\x8f\x98`\x8a\x02\x1e\x19\xe0\u027a\xb2@\x00\x00\u07d4\xc8\xf2\xb3 \xe6\xdf\xd7\t\x06\u0157\xba\xd2\xf9P\x13\x12\u01c2Y\x89Q\x93K\x8b:W\xd0\x00\x00\u07d4\xc9\x03\x00\xcb\x1d@w\xe6\xa6\xd7\xe1i\xa4`F\x8c\xf4\xa4\x92\u05c9lk\x93[\x8b\xbd@\x00\x00\u07d4\xc9\f7e\x15k\u028eH\x97\xab\x80$\x19\x15<\xbeR%\xa9\x89\n\u05ce\xbcZ\xc6 \x00\x00\u07d4\xc9\x10\xa9pUl\x97\x16\xeaS\xaff\xdd\xef\x93\x141$\x91=\x89U\xa6\xe7\x9c\xcd\x1d0\x00\x00\xe0\x94\xc9\x12{\u007ff)\xee\x13\xfc?`\xbc/Dg\xa2\aE\xa7b\x8a\x03|\x9a\xa4\xe7\xceB\x1d\x80\x00\u07d4\xc9\x1b\xb5b\xe4+\xd4a0\xe2\u04eeFR\xb6\xa4\ub1bc\x0f\x89\x1dF\x01b\xf5\x16\xf0\x00\x00\xe0\x94\xc90\x88y\x05m\xfe\x13\x8e\xf8 \x8fy\xa9\x15\u01bc~p\xa8\x8a\x02\x1e\x19\xe0\u027a\xb2@\x00\x00\xe0\x94\xc94\xbe\xca\xf7\x1f\"_\x8bJK\xf7\xb1\x97\xf4\xac\x9604\\\x8a\x04<3\xc1\x93ud\x80\x00\x00\u07d4\xc9?\xbd\xe8\xd4m+\xcc\x0f\xa9\xb3;\u063a\u007f\x80B\x12Ue\x89K\xe4\xe7&{j\xe0\x00\x00\u07d4\xc9@\x89U:\xe4\xc2,\xa0\x9f\xbc\x98\xf5pu\xcf.\u0155\x04\x89\xd8\xd7&\xb7\x17z\x80\x00\x00\u07d4\xc9A\x10\xe7\x1a\xfeW\x8a\xa2\x18\xe4\xfc(d\x03\xb03\n\u038d\x89lk\x93[\x8b\xbd@\x00\x00\xe0\x94\xc9F\u056c\xc14n\xba\nry\xa0\xac\x1dF\\\x99m\x82~\x8a\x03x=T_\xdf\n\xa4\x00\x00\u07d4\xc9J(\xfb20\xa9\xdd\xfa\x96Nw\x0f,\xe3\xc2S\xa7\xbeO\x89\n\u05ce\xbcZ\xc6 \x00\x00\xe0\x94\xc9JXR\x03\xda{\xba\xfd\x93\xe1X\x84\xe6`\u0531\xea\xd8T\x8a\x01{x\x83\xc0i\x16`\x00\x00\u07d4\xc9O|5\xc0'\xd4}\xf8\xefO\x9d\xf8Z\x92H\xa1}\xd2;\x89\x01\x9f\x8euY\x92L\x00\x00\u07d4\xc9Q\x90\f4\x1a\xbb\xb3\xba\xfb\xf7\xee )7pq\xdb\xc3j\x89\x11\xc2]\x00M\x01\xf8\x00\x00\u07d4\xc9S\xf94\xc0\xeb-\x0f\x14K\u06b0\x04\x83\xfd\x81\x94\x86\\\xe7\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\xc9f&r\x8a\xaaLO\xb3\xd3\x1c&\xdf:\xf3\x10\b\x17\x10\u0449\xb5\x0f\u03ef\xeb\xec\xb0\x00\x00\u07d4\xc9gQel\n\x8e\xf45{sD2!4\xb9\x83PJ\u0289lk\x93[\x8b\xbd@\x00\x00\u07d4\u0240Hh\u007f+\xfc\u027d\x90\xed\x18slW\xed\xd3R\xb6]\x8965\u026d\xc5\u07a0\x00\x00\u07d4\u0241\xd3\x12\u0487\xd5X\x87\x1e\u0757:\xbbv\xb9y\xe5\xc3^\x89j\xcb=\xf2~\x1f\x88\x00\x00\u07d4\u0242Xmc\xb0\xd7L \x1b\x1a\xf8A\x83r\xe3\fv\x16\xbe\x89\x05k\xc7^-c\x10\x00\x00\u07d4\u0249CO\x82Z\xaf\x9cU/h^\xba|\x11\xdbJ_\xc7:\x89\x1b(\u014d\x96\x96\xb4\x00\x00\u07d4\u0249\xee\xc3\a\u80db\x9dr7\xcf\xda\b\x82)b\xab\u41c9\x15\xaf\x1dx\xb5\x8c@\x00\x00\u07d4\u0252\xbeY\xc6r\x1c\xafN\x02\x8f\x9e\x8f\x05\xc2\\UQ[\u0509\x01\x15\x8eF\t\x13\xd0\x00\x00\u07d4\u0255{\xa9L\x1b)\xe5'~\xc3f\"pI\x04\xc6=\xc0#\x89h>\xfcg\x82d,\x00\x00\xe0\x94\u025a\x9c\xd6\xc9\xc1\xbe54\xee\u0352\xec\xc2/\\8\xe9Q[\x8a\x01\x05Y;:\x16\x9dw\x00\x00\xe0\x94\u026c\x01\xc3\xfb\t)\x03?\f\xcc~\x1a\xcf\uaae7\x94]G\x8a\x02\xa3j\x9e\x9c\xa4\xd2\x03\x80\x00\u07d4\u0276\x98\xe8\x98\xd2\rMO@\x8eNM\x06\x19\"\xaa\x85c\a\x89\x02+\x1c\x8c\x12'\xa0\x00\x00\u07d4\u0276\xb6\x86\x11\x16\x91\xeej\xa1\x97\xc7#\x1a\x88\xdc`\xbd)]\x89\x1b\x1a\xe4\xd6\xe2\xefP\x00\x00\u07d4\xc9\u01ec\v\u0753B\xb5\xea\xd46\t#\xf6\x8cr\xa6\xbac:\x89\x1b\x1a\xe4\xd6\xe2\xefP\x00\x00\u07d4\xc9\xc8\r\xc1.{\xab\x86\xe9I\xd0\x1eL>\xd3_+\x9b\xba_\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\xc9\xd7dF\u056a\xdf\xf8\vh\xb9\x1b\b\u035b\xc8\xf5U\x1a\xc1\x89&\xb4\xbd\x91\x10\xdc\xe8\x00\x00\xe0\x94\xc9\u073b\x05oM\xb7\xd9\xda9\x93b\x02\u017d\x820\xb3\xb4w\x8a\x04<3\xc1\x93ud\x80\x00\x00\u07d4\xc9\xe0&\b\x06h(\x84\x8a\xeb(\xc76r\xa1)%\x18\x1fM\x89\x1b\x1bk\u05efd\xc7\x00\x00\u07d4\xca\x042\xcb\x15{Qy\xf0.\xbb\xa5\xc9\u0475O\xecM\x88\u028965\u026d\xc5\u07a0\x00\x00\u07d4\xca\x12,\xf0\U00094216\xb7HC\xf4\x9a\xfe\u043a\x16\x18\xee\u05c9\x1e[\x8f\xa8\xfe*\xc0\x00\x00\xe0\x94\xca\"\u0363`m\xa5\xca\xd0\x13\xb8\aG\x06\xd7\xe9\xe7!\xa5\f\x8a\x01q\x81\xc6\xfa9\x81\x94\x00\x00\u07d4\xca#\xf6-\xff\rd`\x03lb\xe8@\xae\xc5W~\v\xef\u0489\a\xa1\xfe\x16\x02w\x00\x00\x00\u07d4\xca%\xff4\x93L\x19B\xe2*N{\xd5o\x14\x02\x1a\x1a\xf0\x88\x89\n\xad\xec\x98?\xcf\xf4\x00\x00\u07d4\xca7?\xe3\xc9\x06\xb8\xc6U\x9e\xe4\x9c\xcd\a\xf3|\xd4\xfbRf\x89a\t=|,m8\x00\x00\u07d4\xcaA\u032c0\x17 R\xd5\"\xcd//\x95}$\x81S@\x9f\x89j\xcb=\xf2~\x1f\x88\x00\x00\u07d4\xcaB\x88\x01N\xdd\xc5c/_\xac\xb5\xe3\x85\x17\xa8\xf8\xbc]\x98\x89\x12nr\xa6\x9aP\xd0\x00\x00\u07d4\xcaB\x88c\xa5\xca06\x98\x92\xd6\x12\x18>\xf9\xfb\x1a\x04\xbc\xea\x89Rf<\u02b1\xe1\xc0\x00\x00\u07d4\xcaI\xa5\xf5\x8a\xdb\xef\xae#\xeeY\xee\xa2A\xcf\x04\x82b.\xaa\x89M\x85<\x8f\x89\b\x98\x00\x00\u07d4\xcaL\xa9\xe4w\x9dS\x0e\u02ec\xd4~j\x80X\xcf\xdee\u064f\x89+^:\xf1k\x18\x80\x00\x00\u07d4\xcae~\xc0o\xe5\xbc\t\xcf#\xe5*\xf7\xf8\f\xc3h\x9en\u07890\xca\x02O\x98{\x90\x00\x00\u07d4\xcaf\xb2(\x0f\xa2\x82\u0176v1\xceU+b\xeeU\xad\x84t\x89j\xc4\"\xf54\x92\x88\x00\x00\xe0\x94\xcal\x81\x8b\xef\xd2Q6\x1e\x02t@h\xbe\x99\u062a`\xb8J\x8a\x01EB\xba\x12\xa37\xc0\x00\x00\u07d4\xcap\xf4\u077f\x06\x9d!C\xbdk\xbc\u007fikRx\x9b2\u7262\xa1]\tQ\x9b\xe0\x00\x00\xe0\x94\xcatuvDjL\x8f0\xb0\x83@\xfe\xe1\x98\xdec\xec\x92\u03ca\x01|\x8e\x12\x06r*0\x00\x00\u07d4\xca{\xa3\xffSl~_\x0e\x158\x00\xbd8=\xb81)\x98\xe0\x89\t1\xac=k\xb2@\x00\x00\xe0\x94\u0282v\xc4w\xb4\xa0{\x80\x10{\x845\x94\x18\x96\a\xb5;\xec\x8a\x01EB\xba\x12\xa37\xc0\x00\x00\u07d4\u0284\t\b>\x01\xb3\x97\xcf\x12\x92\x8a\x05\xb6\x84U\xceb\x01\u07c9V\xbcu\xe2\xd61\x00\x00\x00\u07d4\u0298\u01d8\x8e\xfa\b\xe9%\uf719ER\x03&\xe9\xf4;\x99\x89\xd8\xd7&\xb7\x17z\x80\x00\x00\u07d4\u029a\x04*j\x80o\xfc\x92\x17\x95\x00\xd2D)\xe8\xabR\x81\x17\x89;\xa1\x91\v\xf3A\xb0\x00\x00\u07d4\u029d\xec\x02\x84\x1a\xdf\\\xc9 WjQ\x87\xed\u04bdCJ\x18\x89\x1b\x1a\xe4\xd6\xe2\xefP\x00\x00\u07d4\u029f\xaa\x17T/\xaf\xbb8\x8e\xab!\xbcL\x94\u89f3G\x88\x89lk\x8f\xce\r\x18y\x80\x00\xe0\x94\u02aah\xeel\xdf\r4EJv\x9b\r\xa1H\xa1\xfa\xaa\x18e\x8a\x01\x87.\x1d\xe7\xfeR\xc0\x00\x00\u07d4\u02ad\x9d\xc2\rX\x9c\xe4(\xd8\xfd\xa3\xa9\xd5:`{y\x88\xb5\x89\xd8\xd7&\xb7\x17z\x80\x00\x00\xe0\x94\u02b0\xd3,\xf3v\u007f\xa6\xb3S|\x842\x8b\xaa\x9fPE\x816\x8a\x01\xe5\xb8\xfa\x8f\xe2\xac\x00\x00\x00\u07d4\u02b9\xa3\x01\xe6\xbdF\xe9@5P(\xec\xcd@\xceMZ\x1a\u00c9\x15\xaf\x1dx\xb5\x8c@\x00\x00\u07d4\u02b9\xa9z\xda\x06\\\x87\x81nh`\xa8\xf1Bo\xe6\xb3\xd7u\x8965\u026d\xc5\u07a0\x00\x00\xe0\x94\u02ba\xb6'N\xd1P\x89s~({\xe8x\xb7W\x93Hd\xe2\x8a\x04<3\xc1\x93ud\x80\x00\x00\u07d4\u02bd\xaf5OG \xa4f\xa7d\xa5(\xd6\x0e:H*9<\x8965\u026d\xc5\u07a0\x00\x00\u07d4\xca\xcbg^\t\x96#T\x04\ufbfb.\u02c1R'\x1bU\xe0\x89%\xf2s\x93=\xb5p\x00\x00\u07d4\xca\xd1O\x9e\xbb\xa7f\x80\xeb\x83k\a\x9c\u007f{\xaa\xf4\x81\xedm\x89\f\xef={\xd7\xd04\x00\x00\xe0\x94\xca\xe3\xa2S\xbc\xb2\xcfN\x13\xba\x80\u0098\xab\x04\x02\xda|*\xa0\x8a\x01$\xbc\r\u0752\xe5`\x00\x00\u07d4\xca\xef\x02{\x1a\xb5\x04\xc7?A\xf2\xa1\ty\xb4t\xf9~0\x9f\x89\n\u05ce\xbcZ\xc6 \x00\x00\xe0\x94\xca\xf4H\x1d\x9d\xb7\x8d\xc4\xf2_{J\u023d;\x1c\xa0\x10k1\x8a\x01\x0f\f\xf0d\xddY \x00\x00\xe0\x94\xca\xfd\xe8U\x86L%\x98\xda<\xaf\xc0Z\u064d\U00089380H\x8a\x03\x00\xa8\xed\x96\xffJ\x94\x00\x00\xe0\x94\xcb\r\xd7\xcfN]\x86a\xf6\x02\x89C\xa4\xb9\xb7\\\x91D6\xa7\x8a\x19i6\x89t\xc0[\x00\x00\x00\u07d4\xcb\x1b\xb6\xf1\xda^\xb1\rH\x99\xf7\xe6\x1d\x06\xc1\xb0\x0f\u07f5-\x898E$\xccp\xb7x\x00\x00\u07d4\xcb=vl\x98?\x19+\xce\xca\xc7\x0fN\xe0=\xd9\xffqMQ\x89\x05k\xc7^-c\x10\x00\x00\u07d4\xcbB\xb4N\xb5\xfd`\xb5\x83~O\x9e\xb4rgR=\x1a\"\x9c\x89.\xe4IU\b\x98\xe4\x00\x00\u07d4\xcbG\xbd0\u03e8\xecTh\xaa\xa6\xa9FB\xce\xd9\xc8\x19\xc8\u0509\xd8\xd7&\xb7\x17z\x80\x00\x00\u07d4\xcbH\xfe\x82e\u066fU\xebp\x06\xbc3VE\xb0\xa3\xa1\x83\xbe\x89\xa2\xa1]\tQ\x9b\xe0\x00\x00\u07d4\xcbJ\x91M+\xb0)\xf3._\xef\\#LO\xec--\xd5w\x89a\x94\x04\x9f0\xf7 \x00\x00\xe0\x94\xcbJ\xbf\u0082\xae\xd7n]W\xaf\xfd\xa5B\xc1\xf3\x82\xfc\xac\xf4\x8a\x01\xb9\x0f\x11\xc3\x18?\xaa\x00\x00\u07d4\xcbJ\xd0\xc7#\xdaF\xabV\xd5&\xda\f\x1d%\xc7=\xaf\xf1\n\x89\x1b\xa5\xab\xf9\xe7y8\x00\x00\u07d4\xcbK\xb1\xc6#\xba(\xdcB\xbd\xaa\xa6\xe7N\x1d*\xa1%l*\x89lj\xccg\u05f1\xd4\x00\x00\u07d4\xcbPXt\x12\x82#\x04\xeb\u02e0}\xab:\x0f\t\xff\xfe\u4189JD\x91\xbdm\xcd(\x00\x00\u07d4\xcbX\x99\v\u0350\u03ffm\x8f\t\x86\xf6\xfa`\x02v\xb9N-\x8964\xbf9\xab\x98x\x80\x00\u07d4\xcbh\xaeZ\xbe\x02\xdc\xf8\xcb\u016aq\x9c%\x81FQ\xaf\x8b\x85\x89\x1b\x1a\xe4\xd6\xe2\xefP\x00\x00\u07d4\xcbty\x10\x9bC\xb2fW\xf4F_M\x18\xc6\xf9t\xbe_B\x89b\xa9\x92\xe5:\n\xf0\x00\x00\xe0\x94\xcb}+\x80\x89\xe91,\u026e\xaa's\xf3S\b\xecl*{\x8a\x02\x1e\x19\xe0\u027a\xb2@\x00\x00\u07d4\u02c6\xed\xbc\x8b\xbb\x1f\x911\x02+\xe6IV^\xbd\xb0\x9e2\xa1\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\u02d3\x19\x9b\x9c\x90\xbcI\x15\xbd\x85\x9e=B\x86m\xc8\xc1\x87I\x89\f\x90\xdf\a\xde\xf7\x8c\x00\x00\u07d4\u02d4\xe7o\xeb\xe2\b\x11g3\xe7n\x80]H\xd1\x12\xec\x9f\u028965\u026d\xc5\u07a0\x00\x00\u07d4\u02dbQ\x03\xe4\u0389\xafOd\x91aP\xbf\xf9\xee\u02df\xaa\\\x89\x1b\x1a\xe4\xd6\xe2\xefP\x00\x00\u07d4\u02e2\\zP<\xc8\xe0\xd0Iq\xca\x05\xc7b\xf9\xb7b\xb4\x8b\x89\x1b\x1a\xe4\xd6\xe2\xefP\x00\x00\u07d4\u02e2\x88\xcd<\x1e\xb4\u055d\xdb\x06\xa6B\x1c\x14\xc3E\xa4{$\x89\xd8\xd7&\xb7\x17z\x80\x00\x00\u07d4\u02f3\x18\x9eK\xd7\xf4_\x17\x8b\x1c0\xc7n&1MJK\n\x89\x0f\xfe\vg|e\xa9\x80\x00\xe0\x94\u02f7\xbe\x17\x95?,\u0313\u1f19\x80[\xf4U\x11CNL\x8a\n\xae[\x9d\xf5m/ \x00\x00\xe0\x94\xcb\xc0KM\x8b\x82\xca\xf6p\x99o\x16\f6)@\xd6o\xcf\x1a\x8a\x01EB\xba\x12\xa37\xc0\x00\x00\u07d4\xcb\u07974\xb8\xe6\xaaS\x8c)\x1dm\u007f\xac\xed\xb0\xf38\xf8W\x89lk\x93[\x8b\xbd@\x00\x00\xe0\x94\xcb\xe1\xb9H\x86M\x84t\xe7e\x14XX\xfc\xa4U\x0fxK\x92\x8a\x02\x1e\x19\xe0\u027a\xb2@\x00\x00\u07d4\xcb\xe5/\xc53\xd7\xdd`\x8c\x92\xa2`\xb3|?E\u07b4\xeb3\x8965\u026d\xc5\u07a0\x00\x00\xe0\x94\xcb\xe8\x10\xfe\x0f\xec\xc9dGJ\x1d\xb9w(\xbc\x87\xe9s\xfc\xbd\x8a\x02\x1e\x19\xe0\u027a\xb2@\x00\x00\u07d4\xcb\xf1j\x0f\xe2tRX\xcdR\xdb+\xf2\x19T\xc9u\xfcj\x15\x89\x10CV\x1a\x88)0\x00\x00\xe0\x94\xcb\xf3\u007f\xf8T\xa2\xf1\xceS\x93D\x94wx\x92\xd3\xeceW\x82\x8a\x02\x1e\x19\xe0\u027a\xb2@\x00\x00\u07d4\xcb\xfaj\xf6\u0083\xb0F\xe2w,`c\xb0\xb2\x15S\xc4\x01\x06\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\xcb\xfav\xdb\x04\xce8\xfb ]7\xb8\xd3w\xcf\x13\x80\xda\x03\x17\x89M\x85<\x8f\x89\b\x98\x00\x00\u07d4\xcc\x03I\x85\xd3\xf2\x8c-9\xb1\xa3K\xce\xd4\u04f2\xb6\xca#N\x89\t\xdd\xc1\xe3\xb9\x01\x18\x00\x00\u07d4\xcc\x04<C\x88\xd3E\xf8\x84\u0185^q\x14*\x9fA\xfdi5\x89\x01\x15\x8eF\t\x13\xd0\x00\x00\u07d4\xcc\x1dn\xad\x01\xaa\xda>\x8d\u01f9]\xca%\xdf&\xee\xfac\x9d\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\xcc+_D\x8f5(\xd3\xfeA\xcc}\x1f\xa9\xc0\xdcv\xf1\xb7v\x89\x03@\xaa\xd2\x1b;p\x00\x00\u07d4\xcc-\x04\xf0\xa4\x01q\x89\xb3@\xcaw\x19\x86A\xdc\xf6Ek\x91\x89\u0556{\xe4\xfc?\x10\x00\x00\xe0\x94\xccA\x9f\u0651+\x85\x13VY\xe7z\x93\xbc=\xf1\x82\xd4Q\x15\x8a\x02\x1e\x19\xe0\u027a\xb2@\x00\x00\u07d4\xccE\xfb:U[\xad\x80{8\x8a\x03W\xc8U _|u\xe8\x89.\xe4IU\b\x98\xe4\x00\x00\u07d4\xccHAM*\xc4\xd4*Yb\xf2\x9e\xeeD\x97\t/C\x13R\x89\b\xbaR\xe6\xfcE\xe4\x00\x00\u07d4\xccJ/,\xf8l\xf3\xe43u\xf3`\xa4sF\x91\x19_\x14\x90\x89I\x15\x05;\xd1)\t\x80\x00\u07d4\xccO\x0f\xf2\xae\xb6}T\xce;\xc8\xc6Q\v\x9a\xe8>\x9d2\x8b\x89\x15\xaf\x1dx\xb5\x8c@\x00\x00\u07d4\xccO\xaa\xc0\v\xe6b\x8f\x92\xefk\x8c\xb1\xb1\xe7j\xac\x81\xfa\x18\x89\v\"\xa2\xea\xb0\xf0\xfd\x00\x00\xe0\x94\xccO\xebr\u07d8\xff5\xa18\xe0\x17a\xd1 ?\x9b~\xdf\n\x8a\x01{x\x83\xc0i\x16`\x00\x00\u07d4\xcc`oQ\x13\x97\xa3\x8f\u01c7+\u04f0\xbd\x03\xc7\x1b\xbdv\x8b\x8965\u026d\xc5\u07a0\x00\x00\u07d4\xcc`\xf86\xac\xde\xf3T\x8a\x1f\xef\u0321>\u01a97\xdbD\xa0\x89\x04\xb0m\xbb\xb4\x0fJ\x00\x00\u07d4\xccl\x03\xbd`>\t\xdeT\xe9\xc4\u056cmA\xcb\xceqW$\x89\x05V\xf6L\x1f\xe7\xfa\x00\x00\u07d4\xccl-\xf0\x0e\x86\xec\xa4\x0f!\xff\xda\x1ag\xa1i\x0fG|e\x89\xabM\xcf9\x9a:`\x00\x00\xe0\x94\xccm{\x12\x06\x1b\xc9m\x10M`me\xff\xa3+\x006\xeb\a\x8a\x02\x1e\x19\xe0\u027a\xb2@\x00\x00\u07d4\xccs\xdd5kIy\xb5y\xb4\x01\xd4\xccz1\xa2h\xdd\xceZ\x89\x1b\x1a\xe4\xd6\xe2\xefP\x00\x00\xe0\x94\xccu\x8d\a\x1d%\xa62\n\xf6\x8c]\xc9\xc4\xf6\x95[\xa9E \x8a\x01EB\xba\x12\xa37\xc0\x00\x00\u07d4\xcc{\x04\x81\xcc2\xe6\xfa\xef#\x86\xa0p\"\xbc\xb6\xd2\u00f4\xfc\x89\xabM\xcf9\x9a:`\x00\x00\xe0\x94\u0314;\xe1\",\xd1@\n#\x99\xdd\x1bE\x94E\xcfmT\xa9\x8a\x02\xa7@\xaee6\xfc\x88\x00\x00\u07d4\u0315\x19\xd1\xf3\x98_k%^\xad\xed\x12\xd5bJ\x97'!\xe1\x8965\u026d\xc5\u07a0\x00\x00\u0794\u031a\xc7\x15\xcdo&\x10\xc5+XgdV\x88B\x97\x01\x8b)\x88\xb9\x8b\xc8)\xa6\xf9\x00\x00\u07d4\u0320{\xb7\x94W\x1dJ\xcf\x04\x1d\xad\x87\xf0\xd1\xef1\x85\xb3\x19\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\u032b\xc6\x04\x8aSFD$\xfc\xf7n\xeb\x9en\x18\x01\xfa#\u0509\x02\xab{&\x0f\xf3\xfd\x00\x00\u07d4\u032e\r=\x85*}\xa3\x86\x0f\x066\x15L\nl\xa3\x16(\u0509\x05\xc6\xd1+k\xc1\xa0\x00\x00\u07d4\xcc\xca$\xd8\xc5mn,\a\xdb\bn\xc0~X[\xe2g\xac\x8d\x89\n\u05ce\xbcZ\xc6 \x00\x00\u07d4\xcc\xd5!\x13-\x98l\xb9hi\x84&\"\xa7\u0762l>\xd0W\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\xcc\xf49u\xb7k\xfes_\xec<\xb7\xd4\xdd$\xf8\x05\xba\tb\x89\x03@\xaa\xd2\x1b;p\x00\x00\u07d4\xcc\xf6*f?\x13S\xba.\xf8\xe6R\x1d\xc1\xec\xb6s\xec\x8e\xf7\x89\b=lz\xabc`\x00\x00\u07d4\xcc\xf7\x11\r\x1b\u0667K\xfd\x1d}}-\x9dU`~{\x83}\x890\xca\x02O\x98{\x90\x00\x00\u07d4\xcc\xfdrW`\xa6\x88#\xff\x1e\x06/L\xc9~\x13`\xe8\u0657\x89\x15\xacV\xed\xc4\xd1,\x00\x00\u07d4\xcd\x02\x0f\x8e\xdf\xcfRG\x98\xa9\xb7:d\x034\xbb\xf7/\x80\xa5\x89\a?u\u0460\x85\xba\x00\x00\u07d4\xcd\x06\xf8\xc1\xb5\u037d(\xe2\xd9kcF\xc3\xe8Z\x04\x83\xba$\x8965\u026d\xc5\u07a0\x00\x00\xe0\x94\xcd\a.n\x183\x13y\x95\x19m{\xb1r_\xef\x87a\xf6U\x8a\x01EB\xba\x12\xa37\xc0\x00\x00\u07d4\xcd\n\x16\x1b\xc3g\xae\t'\xa9*\xac\x9c\xf6\xe5\bg\x14\xef\u0289lk\x93[\x8b\xbd@\x00\x00\u07d4\xcd\n\xf3GN\"\xf0i\xec4\a\x87\r\xd7pD=[\x12\xb0\x89\x8e^\xb4\xeew\xb2\xef\x00\x00\u07d4\xcd\v\x02W\u70e3\xd2\xc2\u3e9dny\xb7^\xf9\x80$\u0509\x9f\xad\x06$\x12y\x16\x00\x00\u07d4\xcd\x10,\xd6\xdb=\xf1J\u05af\x0f\x87\xc7$y\x86\x1b\xfc=$\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\xcd\x1ef\xedS\x9d\xd9/\xc4\v\xba\xa1\xfa\x16\u078c\x02\xc1ME\x89\fw\xe4%hc\xd8\x00\x00\u07d4\xcd\x1e\xd2c\xfb\xf6\xf6\xf7\xb4\x8a\xef\x8fs=2\x9dC\x82\xc7\u01c9\x01\x00\xbd3\xfb\x98\xba\x00\x00\u07d4\xcd*6\xd7S\xe9\xe0\xed\x01*XMqh\aX{A\xd5j\x89\x0e+\xa7[\v\x1f\x1c\x00\x00\u07d4\xcd2\xa4\xa8\xa2\u007f\x1c\xc69T\xaacOxW\x05s4\u01e3\x89:\xd1fWlr\xd4\x00\x00\u07d4\xcd5\xff\x01\x0e\xc5\x01\xa7!\xa1\xb2\xf0z\x9c\xa5\x87}\xfc\xf9Z\x89\xd9o\u0390\u03eb\xcc\x00\x00\u07d4\xcdC\x06\xd7\xf6\x94z\xc1tMN\x13\xb8\xef2\xcbe~\x1c\x00\x89\x1b\x1a\xb3\x19\xf5\xecu\x00\x00\u07d4\xcdC%\x8bs\x92\xa90\x83\x9aQ\xb2\xef\x8a\xd24\x12\xf7Z\x9f\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\xcdI\xbf\x18^p\xd0E\a\x99\x9f\x92\xa4\xdeDU1('\u040965\u026d\xc5\u07a0\x00\x00\u07d4\xcdU\x10\xa2B\u07f0\x18=\xe9%\xfb\xa8f\xe3\x12\xfa\xbc\x16W\x89\x82\x1a\xb0\xd4AI\x80\x00\x00\u07d4\xcdVj\u05f8\x83\xf0\x1f\u04d9\x8a\x9aX\xa9\xde\xe4rM\u0725\x89\x030\xae\x185\xbe0\x00\x00\xe0\x94\xcdY\xf3\xdd\xe7~\t\x94\v\xef\xb6\xeeX\x03\x19e\xca\xe7\xa36\x8a\x02\x1e\x19\xe0\u027a\xb2@\x00\x00\u07d4\xcdr]p\xbe\x97\xe6w\xe3\xc8\xe8\\\v&\xef1\xe9\x95PE\x89Hz\x9a0E9D\x00\x00\xe0\x94\xcd~G\x90\x94d\xd8q\xb9\xa6\xdcv\xa8\xe9\x19]\xb3H^z\x8a\x02\x15\xf85\xbcv\x9d\xa8\x00\x00\u07d4\xcd~\xce\bkKa\x9b;6\x93R\xee8\xb7\x1d\xdb\x06C\x9a\x89\n\u05ce\xbcZ\xc6 \x00\x00\u07d4\xcd\u007f\t\xd7\xedf\xd0\u00cb\u016dN2\xb7\xf2\xb0\x8d\xc1\xb3\r\x89>;\xb3M\xa2\xa4p\x00\x00\u07d4\u0355)I+\\)\xe4u\xac\xb9A@+=;\xa5\x06\x86\xb0\x89j\xcb=\xf2~\x1f\x88\x00\x00\u07d4\u0355\xfaB=o\xc1 'J\xac\xde\x19\xf4\xee\xb7f\xf1\x04 \x89\n\u05ce\xbcZ\xc6 \x00\x00\u07d4\u035bL\xefs9\f\x83\xa8\xfdq\u05f5@\xa7\xf9\u03cb\x8c\x92\x89\x04\xe1\x00;(\xd9(\x00\x00\u07d4\u0361t\x11\t\xc0&[?\xb2\xbf\x8d^\xc9\u00b8\xa34kc\x89\x01\x15\x8eF\t\x13\xd0\x00\x00\u07d4\u0361\xb8\x86\u39d5\u027aw\x91N\n/\xe5go\x0f\\\u03c9\x05\xbf`\xeaB\xc2\x04\x00\x00\u07d4\u0364S\x0fK\x9b\xc5\t\x05\xb7\x9d\x17\u008f\xc4o\x954\x9b\u07c93\x10\xe0I\x11\xf1\xf8\x00\x00\u07d4\u036bF\xa5\x90 \x80do\xbf\x95B\x04 J\xe8\x84\x04\x82+\x89\x1d\x8a\x96\xe5\xc6\x06\xeb\x00\x00\u07d4\u0375\x97)\x900\x18?n-#\x853\xf4d*\xa5\x87T\xb6\x89\x15\xaf\x1dx\xb5\x8c@\x00\x00\u07d4\xcd\xd5\u0601\xa76,\x90p\a;\u07fcu\xe7$S\xacQ\x0e\x89-\xa5\x18\xea\xe4\x8e\xe8\x00\x00\u07d4\xcd\xd6\rs\xef\xaa\xd8s\u027b\xfb\x17\x8c\xa1\xb7\x10Z\x81\xa6\x81\x89\x01\xbc\x16\xd6t\xec\x80\x00\x00\u07d4\xcd\xd9\xef\xacMm`\xbdq\xd9U\x85\xdc\xe5\u0557\x05\xc15d\x89\x05k\xc7^-c\x10\x00\x00\u07d4\xcd\xe3m\x81\xd1(\u015d\xa1Ee!\x93\xee\u00bf\xd9e\x86\xef\x89\xd8\xd7&\xb7\x17z\x80\x00\x00\u07d4\xcd\xea8o\x9d\x0f\xd8\x04\xd0(\x18\xf27\xb7\xd9\xfavF\xd3^\x89\xa3I\xd3m\x80\xecW\x80\x00\u07d4\xcd\xec\xf5gT3\u0370\xc2\xe5Zh\xdb]\x8b\xbexA\x9d\u0489\x01\x15\x8eF\t\x13\xd0\x00\x00\xe0\x94\xcd\xfd\x82\x173\x97%\xd7\xeb\xac\x11\xa66U\xf2e\xef\xf1\xcc=\x8a\x01\x0f\fid\x10\xe3\xa9\x00\x00\u07d4\xce\a\x9fQ\x88wt\xd8\x02\x1c\xb3\xb5u\xf5\x8f\x18\xe9\xac\xf9\x84\x89\t\xc2\x00vQ\xb2P\x00\x00\u07d4\xce\x18\x84\u077b\xb8\xe1\x0eM\xbanD\xfe\xee\u00a7\xe5\xf9/\x05\x89\xd8\xd7&\xb7\x17z\x80\x00\x00\u07d4\xce\x1b\f\xb4j\xae\xcf\u05db\x88\f\xad\x0f-\u068a\x8d\xed\u0431\x89\x01\x15\x8eF\t\x13\xd0\x00\x00\u07d4\xce&\xf9\xa50_\x83\x81\tCT\xdb\xfc\x92fN\x84\xf9\x02\xb5\x89\fz\xaa\xb0Y\x1e\xec\x00\x00\u07d4\xce-\xea\xb5\x1c\n\x9a\xe0\x9c\xd2\x12\xc4\xfaL\xc5+S\xcc\r\xec\x89lk\x93[\x8b\xbd@\x00\x00\xe0\x94\xce.\r\xa8\x93F\x99\xbb\x1aU>U\xa0\xb8\\\x16\x945\xbe\xa3\x8a\x01\x0f\fid\x10\xe3\xa9\x00\x00\u07d4\xce:a\xf0F\x1b\x00\x93^\x85\xfa\x1e\xad\x82\xc4^Zd\u0508\x89\x1b\x1a\xe4\xd6\xe2\xefP\x00\x00\u07d4\xceK\x06]\xbc\xb20G 2b\xfbH\xc1\x18\x83d\x97tp\x89\x1b\x1a\xe4\xd6\xe2\xefP\x00\x00\u07d4\xceS\xc8\xcd\xd7B\x96\xac\xa9\x87\xb2\xbc\x19\u00b8u\xa4\x87I\u0409\xa2\xa1]\tQ\x9b\xe0\x00\x00\u07d4\xce^\x04\xf0\x18Ci\xbc\xfa\x06\xac\xa6o\xfa\x91\xbfY\xfa\x0f\xb9\x89\x02+\x1c\x8c\x12'\xa0\x00\x00\u07d4\xce^\xb6:{\xf4\xfb\xc2\xf6\u4ea0\u018a\xb1\xcbL\xf9\x8f\xb4\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\xceb\x12Z\xde\xc37\n\xc5!\x10\x95:Nv\v\xe9E\x1e;\x89\b=lz\xabc`\x00\x00\xe0\x94\xceq\bmL`%T\xb8-\xcb\xfc\xe8\x8d cMS\xccM\x8a\t(\x96R\x9b\xad\u0708\x00\x00\u07d4\u038akmP3\xb1I\x8b\x1f\xfe\xb4\x1aAU\x04\x05\xfa\x03\xa2\x89\xd8\xd7&\xb7\x17z\x80\x00\x00\u07d4\u0397\x86\xd3q/\xa2\x00\xe9\xf6\x857\xee\xaa\x1a\x06\xa6\xf4ZK\x89a\t=|,m8\x00\x00\u07d4\u039d!\u0192\xcd<\x01\xf2\x01\x1fP_\x87\x006\xfa\x8fl\u0489\x15\xaf\x1dx\xb5\x8c@\x00\x00\xe0\x94\u03a2\x89f#\xf4\x91\x02\x87\xa2\xbd\u017e\x83\xae\xa3\xf2\xe6\xde\b\x8a\x01\xfbZ7Q\xe4\x90\xdc\x00\x00\u07d4\u03a3JM\xd9=\u066e\xfd9\x90\x02\xa9}\x99z\x1bK\x89\u0349QP\xae\x84\xa8\xcd\xf0\x00\x00\u07d4\u03a4?pu\x81k`\xbb\xfc\u62d9:\xf0\x88\x12p\xf6\u0109lk\x93[\x8b\xbd@\x00\x00\u07d4\u03a8t3AS<\xb2\xf0\xb9\xc6\xef\xb8\xfd\xa8\rw\x16(%\x89\x05k\xc7^-c\x10\x00\x00\u07d4\u03b0\x89\xec\x8ax3~\x8e\xf8\x8d\xe1\x1bI\xe3\u0751\x0ft\x8f\x8965\u026d\xc5\u07a0\x00\x00\u07d4\u03b3=x\xe7Tz\x9d\xa2\xe8}Q\xae\xc5\xf3D\x1c\x87\x92:\x89\x01\x15\x8eF\t\x13\xd0\x00\x00\u07d4\u03b3\x898\x1dH\xa8\xaeO\xfcH:\u043b^ L\xfd\xb1\xec\x89('\xe6\xe4\xddb\xba\x80\x00\u07d4\xce\xc6\xfce\x85?\x9c\xce_\x8e\x84Fv6.\x15y\x01_\x02\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\xce\xd3\u01fe\x8d\xe7XQ@\x95*\xebP\x1d\xc1\xf8v\ucbf0\x89\xd8\xd7&\xb7\x17z\x80\x00\x00\u07d4\xce\xd8\x1e\xc3S?\xf1\xbf\xeb\xf3\xe3\x84>\xe7@\xad\x11u\x8d>\x89j\xcb=\xf2~\x1f\x88\x00\x00\u07d4\xce\u0733\xa1\u0584?\xb6\xbe\xf6Ca}\xea\U000cf398\xdd_\x89\x19\xe2\xa4\xc8\x18\xb9\x06\x00\x00\u07d4\xce\xe6\x99\xc0pzx6%+)/\x04|\xe8\xad(\x9b/U\x89\x11\x9a\x1e!\xaaiV\x00\x00\u07d4\xce\xedG\xca[\x89\x9f\xd1b?!\xe9\xbdM\xb6Z\x10\u5c1d\x89\a8w@L\x1e\xee\x00\x00\u07d4\xce\xf7tQ\u07e2\xc6C\xe0\v\x15mlo\xf8N#s\xebf\x89\n1\x06+\xee\xedp\x00\x00\u07d4\xcf\x11i\x04\x1c\x17E\xe4[\x17$5\xa2\xfc\x99\xb4\x9a\xce+\x00\x89\x01\xbb\x88\xba\xab-|\x00\x00\xe0\x94\xcf\x15v\x12vN\x0f\u0596\xc8\xcb_\xba\x85\xdfL\r\xdc<\xb0\x8a\x06ZM\xa2]0\x16\xc0\x00\x00\u0794\xcf\x1b\xdby\x9b.\xa6<\xe14f\x8b\xdc\x19\x8bT\x84\x0f\x18\v\x88\xfc\x93c\x92\x80\x1c\x00\x00\u07d4\xcf\"\x88\xefN\xbf\x88\xe8m\xb1=\x8a\x0e\v\xf5*\x05e\x82\u00c9\x89Po\xbf\x97@t\x00\x00\u07d4\xcf&Ni%\x13\t\x06\xc4\xd7\xc1\x85\x91\xaaA\xb2\xa6\u007foX\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\xcf&\xb4{\xd04\xbcP\x8elK\xcf\xd6\xc7\xd3\x004\x92Wa\x89a\x94\x04\x9f0\xf7 \x00\x00\xe0\x94\xcf.*\xd65\xe9\x86\x1a\xe9\\\xb9\xba\xfc\xca\x03kR\x81\xf5\u038a\at2!~h6\x00\x00\x00\u07d4\xcf.s@B\xa3U\xd0_\xfb.9\x15\xb1h\x11\xf4Zi^\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\xcf4\x8f/\xe4{~A<\az{\xaf:u\xfb\xf8B\x86\x92\x89lk\x93[\x8b\xbd@\x00\x00\xe0\x94\xcf?\x91(\xb0r\x03\xa3\xe1\r}WU\xc0\u012b\xc6\xe2\xca\u008a\x01\x0f\f\xf0d\xddY \x00\x00\u07d4\xcf?\xbf\xa1\xfd2\u05e6\xe0\xe6\xf8\xefN\xabW\xbe4\x02\\L\x899\xa1\xc0\xf7YMH\x00\x00\u07d4\xcfAftn\x1d;\xc1\xf8\xd0qK\x01\xf1~\x8ab\xdf\x14d\x896w\x03n\xdf\n\xf6\x00\x00\u07d4\xcfO\x118\xf1\xbdk\xf5\xb6\u0505\xcc\xe4\xc1\x01\u007f\u02c5\xf0}\x89/\u043cw\xc3+\xff\x00\x00\u07d4\xcfZo\x9d\xf7Uy\xc6D\xf7\x94q\x12\x15\xb3\rw\xa0\xce@\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\xcf^\x0e\xac\u0473\x9d\x06U\xf2\xf7u5\xeff\b\xeb\x95\v\xa0\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\xcfhM\xfb\x83\x04r\x93U\xb5\x83\x15\xe8\x01\x9b\x1a\xa2\xad\x1b\xac\x89\x17r$\xaa\x84Lr\x00\x00\u07d4\xcfi@\x81\xc7m\x18\xc6L\xa7\x13\x82\xbe\\\xd6;<\xb4v\xf8\x8965\u026d\xc5\u07a0\x00\x00\u07d4\xcfnR\xe6\xb7t\x80\xb1\x86~\xfe\xc6Dm\x9f\xc3\xcc5w\xe8\x89\f\t\x01\xf6\xbd\x98y\x00\x00\u07d4\u03c8: 2\x96g\xea\"j\x1e<v]\xbbk\xab2!\x9f\x89\xa4\xbe5d\xd6\x16f\x00\x00\xe0\x94\u03c8\x825\x9c\x0f\xb23\x87\xf5g@t\u0631z\xdeQ/\x98\x8a\x01EB\xba\x12\xa37\xc0\x00\x00\u07d4\u03c9\xf7F\v\xa3\xdf\xe8<Z\x1d:\x01\x9e\xe1%\x0f$/\x0f\x895h\x13\xcd\xce\xfd\x02\x80\x00\u07d4\u03d2:]\x8f\xbc=\x01\xaa\a\x9d\x1c\xfeKC\xce\a\x1b\x16\x11\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\u03db\u9e6b\x86\xc6kY\x96\x8eg\xb8\xd4\xdc\xffF\xb1\x81J\x89#\xc7W\a+\x8d\xd0\x00\x00\u07d4\u03e8\xb3q'\x14\x9b\xdb\xfe\xe2\\4\xd8xQ\tQ\xea\x10\xeb\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\u03ec.\x1b\xf32\x05\xb0U3i\x1a\x02&~\xe1\x9c\xd8\x186\x8965\u026d\xc5\u07a0\x00\x00\u07d4\u03fb2\xb7\xd0$5\x0e3!\xfa \u0269\x14\x03Sr\xff\u0189\x15\xbeat\xe1\x91.\x00\x00\u07d4\xcf\xc4\xe6\xf7\xf8\xb0\x11AK\xfb\xa4/#\xad\xfa\xa7\x8dN\xcc^\x89dI\xe8NG\xa8\xa8\x00\x00\u07d4\xcf\xd2r\x8d\xfb\x8b\xdb\xf3\xbfsY\x8an\x13\xea\xf40R\xea+\x89\t79SM(h\x00\x00\u07d4\xcf\xd4t\x93\xc9\xf8\x9f\u603d\xa5uM\xd7\xc9\xcf\xe7\xcb[\xbe\x89\x02\xf4sQ4H\xfe\x00\x00\u07d4\xcf\xde\x0f\xc7]o\x16\xc4C\xc3\x03\x82\x177-\x99\xf5\xd9\a\xf7\x89\x83\"^c\x96\xb5\xec\x00\x00\xe0\x94\xcf\xe2\u02af<\xec\x97\x06\x1d\t9t\x879\xbf\xfehJ\xe9\x1f\x8a\x02\x1e\x19\xe0\u027a\xb2@\x00\x00\u07d4\xcf\xea\u02ae\xd5r\x85\xe0\xacrh\xcejN5\xec\xfd\xb2B\u05c9:\xe4\xd4$\x01\x90`\x00\x00\u07d4\xcf\ucfa0|'\x00/e\xfeSK\xb8\x84-\t%\u01c4\x02\x89\xd8\xd7&\xb7\x17z\x80\x00\x00\u07d4\xcf\xee\x05\u019d\x1f)\xe7qF\x84\u020d\xe5\xa1`\x98\xe9\x13\x99\x89j\xcb=\xf2~\x1f\x88\x00\x00\u07d4\xcf\xf6\xa6\xfe>\x9a\x92*\x12\xf2\x1f\xaa\x03\x81V\x91\x8cO\u02dc\x89\x04E\x91\xd6\u007f\xec\xc8\x00\x00\u07d4\xcf\xf7\xf8\x9aMB\x19\xa3\x82\x95%\x131V\x82\x10\xff\xc1\xc14\x89_h\xe8\x13\x1e\u03c0\x00\x00\u07d4\xcf\xf8\xd0k\x00\xe3\xf5\f\x19\x10\x99\xadV\xbaj\xe2eq\u0348\x8965\u026d\xc5\u07a0\x00\x00\xe0\x94\xcf\xfcI\xc1x~\ubcb5l\xab\xe9$\x04\xb66\x14}EX\x8a\x013\xe00\x8f@\xa3\u0680\x00\u07d4\xd0\bQ;'`J\x89\xba\x17c\xb6\xf8L\u6233F\x94[\x8965\u026d\xc5\u07a0\x00\x00\u07d4\xd0\x0f\x06r\x86\xc0\xfb\u0402\xf9\xf4\xa6\x10\x83\xecv\u07b3\xce\xe6\x8965\u026d\xc5\u07a0\x00\x00\u07d4\xd0\x15\xf6\xfc\xb8M\xf7\xbbA\x0e\x8c\x8f\x04\x89J\x88\x1d\xca\xc27\x898E$\xccp\xb7x\x00\x00\u07d4\xd0\x1a\xf9\x13O\xafRW\x17N\x8by\x18oB\xee5Nd-\x8965\u026d\xc5\u07a0\x00\x00\u07d4\xd0!\b\u04ae<\xab\x10\xcb\xcf\x16W\xaf\">\x02|\x82\x10\xf6\x89lm\x84\xbc\xcd\xd9\xce\x00\x00\u07d4\xd0*\xfe\u03ce.\u00b6*\u022d Aa\xfd\x1f\xaew\x1d\x0e\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\xd01\x919\xfb\xab.\x8e*\xcc\xc1\xd9$\u0531\x1d\xf6ilZ\x89\n\u05ce\xbcZ\xc6 \x00\x00\u07d4\xd07\xd2\x15\xd1\x1d\x1d\xf3\xd5O\xbd2\x1c\u0495\xc5F^';\x89K\xe4\xe7&{j\xe0\x00\x00\u07d4\xd0:-\xa4\x1e\x86\x8e\xd3\xfe\xf5t[\x96\xf5\xec\xa4b\xffo\u0689\xa2\xa1]\tQ\x9b\xe0\x00\x00\xe0\x94\xd0?\xc1eWj\xae\xd5%\xe5P,\x8e\x14\x0f\x8b.\x86\x969\x8a\x01sV\u0633%\x01\xc8\x00\x00\u07d4\xd0C\xa0\x11\xecBp\xee~\u0239hsu\x15\xe5\x03\xf80(\x89\x1b\x1a\xe4\xd6\xe2\xefP\x00\x00\u07d4\xd0K\x86\x1b=\x9a\xccV:\x90\x16\x89\x94\x1a\xb1\xe1\x86\x11a\xa2\x89\x01\x15\x8eF\t\x13\xd0\x00\x00\u07d4\xd0ZD|\x91\x1d\xbb'[\xfb.Z7\xe5\xa7\x03\xa5o\x99\x97\x89\n\u05ce\xbcZ\xc6 \x00\x00\u07d4\xd0_\xfb+t\xf8g O\xe51e;\x02H\xe2\x1c\x13TN\x8965\u026d\xc5\u07a0\x00\x00\u07d4\xd0bX\x81q\u03d9\xbb\xebX\xf1&\xb8p\xf9\xa3r\x8da\xec\x89\xf3\xf2\v\x8d\xfai\xd0\x00\x00\u07d4\xd0c\x8e\xa5q\x89\xa6\xa6\x99\x02J\u05ccq\xd99\xc1\xc2\xff\x8c\x89\x8e\xaeVg\x10\xfc \x00\x00\xe0\x94\xd0d\x8aX\x1b5\b\xe15\xa2\x93]\x12\xc9epE\xd8q\u028a\x01\xb2\u07dd!\x9fW\x98\x00\x00\u07d4\xd0q\x19)f\xebi\xc3R\x0f\xca:\xa4\xdd\x04)~\xa0KN\x89\x05\xf6\x8e\x811\xec\xf8\x00\x00\u07d4\xd0q\x85 \xea\xe0\xa4\xd6-p\xde\x1b\xe0\xcaC\x1c^\xea$\x82\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\xd0w]\xba*\xf4\xc3\n:x6Y9\xcdq\xc2\xf9\u0795\u0489i*\xe8\x89p\x81\xd0\x00\x00\u07d4\xd0{\xe0\xf9\t\x97\xca\xf9\x03\u022c\x1dS\xcd\xe9\x04\xfb\x19\aA\x8968\x908\xb6\x99\xb4\x00\x00\u07d4\xd0~Q\x18d\xb1\u03d9i\xe3V\x06\x02\x82\x9e2\xfcNq\xf5\x89\x02\xb5\xe3\xaf\x16\xb1\x88\x00\x00\u07d4\u0400\x94\x98\xc5H\x04z\x1e**\xa6\xa2\x9c\xd6\x1a\x0e\xe2h\xbd\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\u0402'_tZ,\xac\x02v\xfb\xdb\x02\u0532\xa3\xab\x17\x11\xfe\x89\x01\xa0Ui\r\x9d\xb8\x00\x00\u07d4\u040f\xc0\x9a\x000\xfd\t(\xcd2\x11\x98X\x01\x82\xa7j\xae\x9f\x8965\u026d\xc5\u07a0\x00\x00\u07d4\u0413\xe8)\x81\x9f\xd2\xe2[\x978\x00\xbb=XA\xdd\x15-\x05\x89\xd8\xd7&\xb7\x17z\x80\x00\x00\u07d4\u0414J\xa1\x85\xa13pa\xae \u071d\xd9l\x83\xb2\xbaF\x02\x89\n\u05ce\xbcZ\xc6 \x00\x00\u07d4\u0416V[|t\a\xd0e6X\x03U\xfd\xd6\xd29\x14J\xa1\x89\r\x8drkqw\xa8\x00\x00\u07d4\u041c\xb2\xe6\b-i:\x13\xe8\xd2\xf6\x8d\xd1\u0744a\xf5X@\x8965\u026d\xc5\u07a0\x00\x00\u07d4\u0426\xc6\xf9\xe9\u0133\x83\xd7\x16\xb3\x1d\xe7\x8dVAM\xe8\xfa\x91\x89\x10CV\x1a\x88)0\x00\x00\u07d4\u0427 \x9b\x80\xcf`\xdbb\xf5}\n]}R\x1ai`fU\x89\b\xacr0H\x9e\x80\x00\x00\xe0\x94\u0428\xab\xd8\n\x19\x9bT\xb0\x8be\xf0\x1d \x9c'\xfe\xf0\x11[\x8a\x01a\xc6&\xdca\xa2\xef\x80\x00\xe0\x94\u042b\xccp\xc0B\x0e\x0e\x17/\x97\xd4;\x87\xd5\xe8\f3n\xa9\x8a\x02\x1e\x19\xe0\u027a\xb2@\x00\x00\u07d4\u042es]\x91^\x94hf\xe1\xfe\xa7~^\xa4f\xb5\xca\xdd\x16\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\u0431\x1do+\u0394^\fjP \u00f5'S\xf8\x03\xf9\u0449\n\u05ce\xbcZ\xc6 \x00\x00\xe0\x94\xd0\xc1\x01\xfd\x1f\x01\xc6?k\x1d\x19\xbc\x92\r\x9f\x93#\x14\xb16\x8a\x04<3\xc1\x93ud\x80\x00\x00\u07d4\xd0\xc5Z\xbf\x97o\xdc=\xb2\xaf\u9f99\u0519HMWl\x02\x8965\u026d\xc5\u07a0\x00\x00\u07d4\xd0\u0422\xadE\xf5\x9a\x9d\xcc\u0195\xd8_%\xcaF\xed1\xa5\xa3\x89-\x89W}}@ \x00\x00\u07d4\xd0\xd6,G\xea`\xfb\x90\xa3c\x92\t\xbb\xfd\xd4\xd93\x99\x1c\u0189\n\x84Jt$\xd9\xc8\x00\x00\u07d4\xd0\xdbEax o\\D0\xfe\x00Pc\x90<=zI\xa7\x89&I\x1eE\xa7S\xc0\x80\x00\u07d4\xd0\xe1\x94\xf3K\x1d\xb6\t(\x85\t\xcc\xd2\xe7;a1\xa2S\x8b\x8965f3\xeb\xd8\xea\x00\x00\u07d4\xd0\xe3^\x04vF\xe7Y\xf4Qp\x93\xd6@\x86BQ\u007f\bM\x89\u054f\xa4h\x18\xec\u02c0\x00\u07d4\xd0\xeeM\x02\xcf$8,0\x90\xd3\xe9\x95`\xde6xs\\\u07c9\x82\x1a\xb0\xd4AI\x80\x00\x00\u07d4\xd0\xf0OR\x10\x9a\xeb\xec\x9a{\x1e\x932v\x1e\x9f\xe2\xb9{\xb5\x89\xd8\xd7&\xb7\x17z\x80\x00\x00\u07d4\xd0\xf9Yx\x11\xb0\xb9\x92\xbb}7W\xaa%\xb4\xc2V\x1d2\xe2\x89\x1b\x1a\xe4\xd6\xe2\xefP\x00\x00\u07d4\xd1\x03\x02\xfa\xa1\x92\x9a2i\x04\xd3v\xbf\v\x8d\xc9:\xd0LL\x89a\t=|,m8\x00\x00\xe0\x94\xd1\x10\r\xd0\x0f\xe2\xdd\xf1\x81c\xad\x96M\vi\xf1\xf2\xe9e\x8a\x8a\x01C\x12\tU\xb2Pk\x00\x00\u07d4\xd1\x16\xf3\xdc\xd5\xdbtK\xd0\b\x88v\x87\xaa\x0e\xc9\xfdr\x92\xaa\x8965\u026d\xc5\u07a0\x00\x00\u07d4\xd1\x19A|Fs,\xf3M\x1a\x1a\xfby\xc3\xe7\xe2\u034e\xec\xe4\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\xd1-w\xae\x01\xa9-5\x11{\xacpZ\xac\u0642\xd0.t\xc1\x8965\u026d\xc5\u07a0\x00\x00\xe0\x94\xd15yK\x14\x9a\x18\xe1G\xd1nb\x1ai1\xf0\xa4\n\x96\x9a\x8a\x04<3\xc1\x93ud\x80\x00\x00\xe0\x94\xd1C%8\xe3[vd\x95j\u4563*\xbd\xf0A\xa7\xa2\x1c\x8a\x04+\xf0kx\xed;P\x00\x00\u07d4\xd1C\x82g#\x17\x04\xfcr\x80\xd5c\xad\xf4v8D\xa8\a\"\x89\n\u05ce\xbcZ\xc6 \x00\x00\u07d4\xd1S\x8e\x9a\x87\u5729\xec\x8eX&\xa5\xb7\x93\xf9\x9f\x96\xc4\u00c965\u026d\xc5\u07a0\x00\x00\xe0\x94\xd1d\x85\x03\xb1\xcc\u0178\xbe\x03\xfa\x1e\xc4\xf3\xee&~j\xdf{\x8a\x01;\xef\xbfQ\xee\xc0\x90\x00\x00\xe0\x94\xd1h,!Y\x01\x8d\xc3\xd0\u007f\b$\n\x8c`m\xafe\xf8\xe1\x8a*Z\x05\x8f\u0095\xed\x00\x00\x00\u07d4\xd1q\xc3\xf2%\x8a\xef5\xe5\x99\xc7\xda\x1a\xa0s\x00#M\xa9\xa6\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\xd1w\x8c\x13\xfb\xd9h\xbc\b<\xb7\xd1\x02O\xfe\x1fI\xd0,\xaa\x89\xd9\xec\xb4\xfd \x8eP\x00\x00\u07d4\xd1\u007f\xbe\"\xd9\x04b\xed7(\x06p\xa2\xea\v0\x86\xa0\xd6\u0589\n\xd6\xee\xdd\x17\xcf;\x80\x00\u07d4\u0441\x1cU\x97i\x80\xf0\x83\x90\x1d\x8a\r\xb2i\"-\xfb\\\xfe\x89T\x06\x923\xbf\u007fx\x00\x00\u07d4\u044e\xb9\xe1\u0485\u06be\x93\xe5\u053a\xe7k\xee\xfeC\xb5!\xe8\x89$=M\x18\"\x9c\xa2\x00\x00\u07d4\u0453\xe5\x83\xd6\a\x05c\xe7\xb8b\xb9aJG\u9509\xf3\xe5\x8965f3\xeb\xd8\xea\x00\x00\u07d4\u0457\x8f.4@\u007f\xab\x1d\xc2\x18=\x95\xcf\xdab`\xb3Y\x82\x89*\xb7\xb2`\xff?\xd0\x00\x00\u07d4\u045c\xaf9\xbb7\u007f\xdf,\xf1\x9b\xd4\xfbRY\x1c&1\xa6<\x8965\u026d\xc5\u07a0\x00\x00\u0794\u0463\x96\xdc\u06b2\xc7IA0\xb3\xfd0x 4\r\xfd\x8c\x1f\x88\xf9\"P\xe2\xdf\xd0\x00\x00\xe0\x94\u0467\x1b-\bX\xe82p\b]\x95\xa3\xb1T\x96P\x03^#\x8a\x03'\xbb\t\xd0j\xa8P\x00\x00\u07d4\u046c\xb5\xad\xc1\x189s%\x8dk\x85$\xff\xa2\x8f\xfe\xb2=\xe3\x89\xd8\xd7&\xb7\x17z\x80\x00\x00\u07d4\u0473\u007f\x03\xcb\x10t$\xe9\xc4\xddW\\\xcdOL\xeeW\xe6\u0349lk\x93[\x8b\xbd@\x00\x00\u07d4\u0475\xa4T\xac4\x05\xbbAy \x8cl\x84\xde\x00k\u02db\xe9\x89\x1b\x1a\xe4\xd6\xe2\xefP\x00\x00\u07d4\xd1\xc4YT\xa6+\x91\x1a\xd7\x01\xff.\x90\x13\x1e\x8c\xeb\x89\xc9\\\x89K\x91\xa2\xdeE~\x88\x00\x00\u07d4\xd1\xc9np\xf0Z\xe0\xe6\xcd`!\xb2\b7P\xa7q|\xdeV\x89\x1b\x1a\xe4\xd6\xe2\xefP\x00\x00\u07d4\xd1\u0571\u007f\xfe-{\xbby\xcc}y0\xbc\xb2\xe5\x18\xfb\x1b\xbf\x89\xa2\xa1]\tQ\x9b\xe0\x00\x00\u07d4\xd1\xda\f\x8f\xb7\xc2\x10\xe0\xf2\xeca\x8f\x85\xbd\xae}>sK\x1c\x89j\xcb=\xf2~\x1f\x88\x00\x00\u07d4\xd1\xddy\xfb\x15\x81`\xe5\xb4\xe8\xe2?1.j\x90\u007f\xbcMN\x89\x1b\x1a\xe4\xd6\xe2\xefP\x00\x00\u07d4\xd1\xdeZ\xad:_\xd8\x03\U00071bb6\x10<\xb8\xe1O\xe7#\xb7\x89\x01\x15\x8eF\t\x13\xd0\x00\x00\u07d4\xd1\xe1\xf2\xb9\xc1l0\x98t\xde\xe7\xfa\xc3&u\xaf\xf1)\u00d8\x89\x03\xf2M\x8eJ\x00p\x00\x00\xe0\x94\xd1\xe5\xe24\xa9\xf4Bf\xa4\xa6$\x1a\x84\u05e1\xa5Z\u0567\xfe\x8a\x04<3\xc1\x93ud\x80\x00\x00\u07d4\xd1\xeaMr\xa6{[>\x0f1UY\xf5+\xd0aMq0i\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\xd1\xee\x90YW\xfe|\xc7\x0e\xc8\xf2\x86\x8bC\xfeG\xb1?\xeb\xff\x89\x02b\x9ff\xe0\xc50\x00\x00\u07d4\xd1\xf1iM\"g\x1bZ\xadj\x94\x99\\6\x9f\xbea3go\x8965\u026d\xc5\u07a0\x00\x00\u07d4\xd1\xf4\xdc\x1d\u06ca\xbb\x88H\xa8\xb1N%\xf3\xb5Z\x85\x91\xc2f\x89\r\x8drkqw\xa8\x00\x00\u07d4\xd1\xfe\u042e\xe6\xf5\xdf\xd7\xe2Wi%L<\xfa\xd1Z\xde\u032a\x89'\x92\xc8\xfcKS(\x00\x00\u07d4\xd2\x05\x1c\xb3\xcbg\x04\xf0T\x8c\u0210\xab\n\x19\xdb4\x15\xb4*\x89\x12\x1b.^ddx\x00\x00\u07d4\xd2\x06\xaa\u07736\xd4^yr\xe9<\xb0uG\x1d\x15\x89{]\x89 \x86\xac5\x10R`\x00\x00\u07d4\xd2\tH+\xb5I\xab\xc4w{\xeam\u007fe\x00b\xc9\xc5z\x1c\x89\x11e\x1a\xc3\xe7\xa7X\x00\x00\u07d4\xd2\r\xcb\vxh+\x94\xbc0\x00(\x14H\xd5W\xa2\v\xfc\x83\x890\x84\x9e\xbe\x166\x9c\x00\x00\u07d4\xd2\x10{57&\u00e2\xb4ef\xea\xa7\xd9\xf8\v]!\xdb\xe3\x89\x01\x15\x8eF\t\x13\xd0\x00\x00\u07d4\xd2\x11\xb2\x1f\x1b\x12\xb5\ta\x81Y\r\xe0~\xf8\x1a\x89S~\xad\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\xd2\x18\xef\xb4\u06d8\x1c\xddjy\u007fK\u050c|&)<\xeb@\x89\xa1Fk1\xc6C\x1c\x00\x00\xe0\x94\xd2\x1asA\xeb\x84\xfd\x15\x10T\xe5\u31fb%\xd3nI\x9c\t\x8a\x02\xf6\xf1\a\x80\xd2,\xc0\x00\x00\xe0\x94\xd2$\xf8\x80\xf9G\x9a\x89\xd3/\t\xe5+\u9432\x88\x13\\\xef\x8a\x03\xa9\u057a\xa4\xab\xf1\xd0\x00\x00\u07d4\xd2/\f\xa4\xcdG\x9ef\x17u\x05;\xccI\xe3\x90\xf6p\u074a\x8965\u026d\xc5\u07a0\x00\x00\u07d4\xd21\x92\x975\x13!\x02G\x1b\xa5\x90\a\xb6dL\xc0\xc1\xde>\x8967\tlK\xcci\x00\x00\u07d4\xd25\xd1\\\xb5\xec\xee\xbba)\x9e\x0e\x82\u007f\xa8'H\x91\x1d\x89\x89\xd8\xd7&\xb7\x17z\x80\x00\x00\u07d4\xd2:$\xd7\xf9F\x83C\xc1C\xa4\x1ds\xb8\x8f|\xbec\xbe^\x89\n\u05ce\xbcZ\xc6 \x00\x00\u07d4\xd2=z\xff\xac\xdc>\x9f=\xaez\xfc\xb4\x00oX\xf8\xa4F\x00\x89\xc3(\t>a\xee@\x00\x00\u07d4\xd2C\x18L\x80\x1e]y\xd2\x06?5x\u06ee\x81\u7ce9\u02c9k\u0722h\x1e\x1a\xba\x00\x00\u07d4\xd2KfD\xf49\xc8\x05\x1d\xfcd\u04c1\xb8\xc8lu\xc1u8\x89lk\x93[\x8b\xbd@\x00\x00\xe0\x94\xd2K\xf1--\xdfE}\xec\xb1xt\xef\xde R\xb6\\\xbbI\x8a\x02\xf6\xf1\a\x80\xd2,\xc0\x00\x00\xe0\x94\xd2Q\xf9\x03\xae\x18rrY\xee\xe8A\xa1\x89\xa1\xf5i\xa5\xfdv\x8a\x02\x1e\x19\xe0\u027a\xb2@\x00\x00\u07d4\xd2R\x96\v\v\xf6\xb2\x84\x8f\u07ad\x80\x13m\xb5\xf5\a\xf8\xbe\x02\x89lk\x93[\x8b\xbd@\x00\x00\xe0\x94\xd2X\x1aU\xce#\xab\x10\u062d\x8cD7\x8fY\a\x9b\xd6\xf6X\x8a\x01\xdd\f\x88_\x9a\r\x80\x00\x00\u07d4\xd2Z\xec\xd7\xeb\x8b\xd64[\x06;]\xbd'\x1cw\xd3QD\x94\x89b\xa9\x92\xe5:\n\xf0\x00\x00\u07d4\xd2|#O\xf7\xac\xca\xce=\x99g\b\xf8\xf9\xb0Ip\xf9}6\x89Hz\x9a0E9D\x00\x00\u07d4\u0482\x98RM\xf5\xecK$\xb0\xff\xb9\u07c5\x17\n\x14Z\x9e\xb5\x89\x0f\x98\xa3\xb9\xb37\xe2\x00\x00\xe0\x94\u0483\xb8\xed\xb1\n%R\x8aD\x04\xde\x1ce\xe7A\r\xbc\xaag\x8a\x02\x8a\x85t%Fo\x80\x00\x00\u07d4\u0484\xa5\x03\x82\xf8:am9\xb8\xa9\xc0\xf3\x96\xe0\ubfe9]\x8966\xc2^f\xec\xe7\x00\x00\u07d4\u0488\xe7\xcb{\xa9\xf6 \xab\x0ftR\xe5\bc=\x1cZ\xa2v\x89\xd8\xd7&\xb7\x17z\x80\x00\x00\xe0\x94\u049d\xc0\x8e\xfb\xb3\xd7.&?x\xabv\x10\xd0\"m\xe7k\x00\x8a\x02\x8a\x85t%Fo\x80\x00\x00\u07d4\u04a00\xac\x89R2_\x9e\x1d\xb3x\xa7\x14\x85\xa2N\x1b\a\xb2\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\u04a4y@CG\xc5T:\xab)*\xe1\xbbJo\x15\x83W\xfa\x89\xd8\xd7&\xb7\x17z\x80\x00\x00\xe0\x94\u04a5\xa0$#\nW\xcc\xc6fv\v\x89\xb0\xe2l\xaf\u0449\u01ca\n\x96YZ\\n\x8a?\x80\x00\u07d4\u04a8\x03'\xcb\xe5\\L{\xd5\x1f\xf9\xdd\xe4\xcad\x8f\x9e\xb3\xf8\x89\x02\xb5\xe3\xaf\x16\xb1\x88\x00\x00\u07d4\u04a8Oug\\b\xd8\f\x88ulB\x8e\xee+\xcb\x18T!\x89A\rXj \xa4\xc0\x00\x00\u07d4\u04ab\xd8J\x18\x10\x93\xe5\xe2)\x13oB\xd85\xe8#]\xe1\t\x89\x05k\xe0<\xa3\xe4}\x80\x00\u07d4\u04ac\r:X`^\x1d\x0f\x0e\xb3\xde%\xb2\xca\xd1)\xed`X\x89\xd8\xd7&\xb7\x17z\x80\x00\x00\u07d4\u04bfg\xa7\xf3\xc6\xceV\xb7\xbeAg]\xbb\xad\xfe~\xa9:3\x89\x15\xaf\x1dx\xb5\x8c@\x00\x00\u07d4\xd2\xdb\xeb\xe8\x9b\x03W\xae\xa9\x8b\xbe\x8eIc8\u07bb(\xe8\x05\x89\xd8\xd7&\xb7\x17z\x80\x00\x00\u07d4\xd2\xe2\x1e\xd5hh\xfa\xb2\x8e\tG\x92z\xda\xf2\x9f#\xeb\xadl\x89l\x18O\x13U\xd0\xe8\x00\x00\u07d4\xd2\xe8\x17s\x8a\xbf\x1f\xb4\x86X?\x80\xc3P1\x8b\xed\x86\f\x80\x89\r\x02\xce\xcf_]\x81\x00\x00\u07d4\xd2\xed\xd1\xdd\xd6\xd8m\xc0\x05\xba\xebT\x1d\"\xb6@\xd5\xc7\xca\xe5\x89\x01\x15\x8eF\t\x13\xd0\x00\x00\u07d4\xd2\xf1\x99\x8e\x1c\xb1X\f\xecOl\x04}\xcd=\xce\xc5L\xf7<\x89\n\u05ce\xbcZ\xc6 \x00\x00\u07d4\xd2\xf2A%]\xd7\xc3\xf7<\a\x040q\xec\b\xdd\xd9\xc5\xcd\xe5\x89\x1b\x1a\xe4\xd6\xe2\xefP\x00\x00\u07d4\xd2\xffg \x16\xf6;/\x859\x8fJo\xed\xbb`\xa5\r<\u0389\x12\x91$o[sJ\x00\x00\u07d4\xd3\rLC\xad\xcfU\xb2\xcbS\u0583#&A4I\x8d\x89\u038965\u026d\xc5\u07a0\x00\x00\u07d4\xd3\x0e\xe9\xa1+Mh\xab\xac\xe6\xba\u029a\u05ff\\\xd1\xfa\xf9\x1c\x89QO\xcb$\xff\x9cP\x00\x00\u07d4\xd3\x11\x8e\xa3\xc85\x05\xa9\u0613\xbbg\xe2\xde\x14-Sz>\xe7\x89\x01\x15\x8eF\t\x13\xd0\x00\x00\u07d4\xd3\x11\xbc\u05eaN\x9bO8?\xf3\xd0\u05b6\xe0~!\xe3p]\x89\n\u05ce\xbcZ\xc6 \x00\x00\u07d4\xd3\x15\xde\xea\x1d\x8c\x12q\xf9\xd11\x12c\xabG\xc0\a\xaf\xb6\xf5\x89\x03\xc8\x1dNeK@\x00\x00\u07d4\xd3+,y\xc3dx\xc5C\x19\x01\xf6\xd7\x00\xb0M\xbe\x9b\x88\x10\x89\x15w\x9a\x9d\xe6\xee\xb0\x00\x00\u07d4\xd3+EVF\x14Ql\x91\xb0\u007f\xa9\xf7-\xcfx|\xceN\x1c\x89\x0f\xc6o\xae7F\xac\x00\x00\u07d4\xd30r\x811\xfe\x8e:\x15Hz4W<\x93E~*\xfe\x95\x89\xd8\xd7&\xb7\x17z\x80\x00\x00\u07d4\xd31\xc8#\x82Z\x9eRc\xd0R\u0611]M\xcd\xe0z\\7\x89\x1e\x93\x12\x83\xcc\xc8P\x00\x00\u07d4\xd33btE\xf2\u05c7\x90\x1e\xf3;\xb2\xa8\xa3g^'\xff\xec\x89\x15\xaf\x1dx\xb5\x8c@\x00\x00\u07d4\xd3<\xf8+\xf1LY&@\xa0\x86\b\x91L#py\u057e4\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\xd3Mp\x8ds\x98\x02E3\xa5\xa2\xb20\x9b\x19\xd3\xc5Qq\xbb\x89\x15\xaf\x1dx\xb5\x8c@\x00\x00\u07d4\xd3N\x03\xd3j+\xd4\u045a_\xa1b\x18\xd1\xd6\x1e?\xfa\v\x15\x89\x11X\xe4`\x91=\x00\x00\x00\u07d4\xd3Pu\xcaa\xfeY\xd1#\x96\x9c6\xa8-\x1a\xb2\xd9\x18\xaa8\x89\x90\xf54`\x8ar\x88\x00\x00\u07d4\xd3g\x00\x9a\xb6X&;b\xc23:\x1c\x9eA@I\x8e\x13\x89\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\xd3g\x9aG\xdf-\x99\xa4\x9b\x01\u024d\x1c>\f\x98|\xe1\xe1X\x89\x0f-\xc7\xd4\u007f\x15`\x00\x00\xe0\x94\u04cf\xa2\xc4\xcc\x14z\xd0j\u0562\xf7Uy(\x1f\"\xa7\xcc\x1f\x8a\x04<3\xc1\x93ud\x80\x00\x00\xe0\x94\u04da]\xa4`9+\x94\v<i\xbc\x03u{\xf3\xf2\xe8$\x89\x8a\x01|\x83\xa9}kl\xa5\x00\x00\u07d4\u04db|\xbc\x94\x00?\xc9H\xf0\xcd\xe2{\x10\r\xb8\xcc\xd6\xe0c\x89\x15\xaf\x1dx\xb5\x8c@\x00\x00\u07d4\u04e1\x0e\u01e5\xc92I\x99\u075e\x9bk\xde|\x91\x1eXK\u0689 \x86\xac5\x10R`\x00\x00\u07d4\u04e9A\xc9a\xe8\u028b\x10p\xf2<mm\r*u\x8aDD\x89\n\u05ce\xbcZ\xc6 \x00\x00\u07d4\u04fbY\xfa1%\x8b\xe6/\x8e\xd22\xf1\xa7\xd4{J\vA\xee\x89\x05k\xc7^-c\x10\x00\x00\u07d4\u04fcs\t7\xfau\xd8E&\x16\xad\x1e\xf1\xfe\u007f\xff\xe0\xd0\xe7\x89\x04\x84\xe4\xde\xd2\xea\xe3\x80\x00\u07d4\xd3\xc2MK:^\x0f\xf8\xa4b-Q\x8e\xdds\xf1j\xb2\x86\x10\x89\x01\x15\x8eF\t\x13\xd0\x00\x00\xe0\x94\xd3\xc6\xf1\xe0\xf5\x0e\xc3\u04a6~k\xcd\x19>\u01ee8\xf1e\u007f\x8a\x01f\xc5H\b\x89\xdbw\x00\x00\xe0\x94\xd3\xd6\xe9\xfb\x82T/\u049e\xd9\xea6\t\x89\x1e\x15\x13\x96\xb6\xf7\x8a\voX\x8a\xa7\xbc\xf5\xc0\x00\x00\xe0\x94\xd3\xda\u0476\u040dE\x81\u032ee\xa8s-\xb6\xaci\xf0\u019e\x8a\x01EB\xba\x12\xa37\xc0\x00\x00\u07d4\xd3\xdf;S\xcb;GU\xdeT\xe1\x80E\x1c\xc4L\x9e\x8a\u0a89#\u0114\t\xb9w\x82\x80\x00\u07d4\xd3\xf8s\xbd\x99V\x13W\x89\xab\x00\xeb\xc1\x95\xb9\"\xe9K%\x9d\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\xd4\x02\xb4\xf6\xa0\x99\xeb\xe7\x16\xcb\x14\xdfOy\xc0\xcd\x01\xc6\a\x1b\x89lk\x93[\x8b\xbd@\x00\x00\xe0\x94\xd4\r\x00U\xfd\x9a8H\x8a\xff\x92?\xd0=5\xecF\xd7\x11\xb3\x8a\x01\x0f\b\xed\xa8\xe5U\t\x80\x00\u07d4\xd4\x0e\xd6j\xb3\xce\xff$\xca\x05\xec\xd4q\ufd12\xc1__\xfa\x89\x1b\x1a\xe4\xd6\xe2\xefP\x00\x00\u07d4\xd4\x18\x87\v\xc2\xe4\xfa{\x8aa!\xae\br\xd5RG\xb6%\x01\x89U\xa6\xe7\x9c\xcd\x1d0\x00\x00\u07d4\xd4\x1d\u007f\xb4\x9f\xe7\x01\xba\xac%qpBl\u0273\x8c\xa3\xa9\xb2\x89\t\x8a}\x9b\x83\x14\xc0\x00\x00\u07d4\xd4 U\x92\x84@U\xb3\u01e1\xf8\f\xef\xe3\xb8\xebP\x9b\xcd\xe7\x89\t\xb3\xbf\xd3B\xa9\xfc\x80\x00\u07d4\xd4+ \xbd\x03\x11`\x8bf\xf8\xa6\xd1[*\x95\xe6\xde'\u017f\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\xd44O}\\\xade\xd1~\\-\x0es#\x94=ob\xfe\x92\x89\x0e~\xeb\xa3A\vt\x00\x00\u07d4\xd4>\xe48\xd8=\xe9\xa3ub\xbbN(l\xb1\xbd\x19\xf4\x96M\x8965\u026d\xc5\u07a0\x00\x00\u07d4\xd4C4\xb4\xe2:\x16\x9a\f\x16\xbd!\xe8f\xbb\xa5-\x97\x05\x87\x89\x8c\xf2?\x90\x9c\x0f\xa0\x00\x00\xe0\x94\xd4M\x81\xe1\x8fF\xe2\u03f5\xc1\xfc\xf5\x04\x1b\xc8V\x97g\xd1\x00\x8a\a\xb4B\xe6\x84\xf6Z\xa4\x00\x00\u07d4\xd4OJ\xc5\xfa\xd7k\xdc\x157\xa3\xb3\xafdr1\x9bA\r\x9d\x89V\xbcu\xe2\xd61\x00\x00\x00\u07d4\xd4O^\xdf+\xcf$3\xf2\x11\xda\xdd\f\xc4P\xdb\x1b\x00\x8e\x14\x89\x0e~\xeb\xa3A\vt\x00\x00\xe0\x94\xd4Oj\u00d2;_\xd71\xa4\xc4YD\xecO~\xc5*j\xe4\x8a\x02\x1e\x19\xe0\u027a\xb2@\x00\x00\u07d4\xd4[3A\xe8\xf1\\\x802\x93 \u00d7~;\x90\xe7\x82j~\x89\x1b\x1a\xe4\xd6\xe2\xefP\x00\x00\u07d4\xd4]]\xaa\x13\x8d\xd1\xd3t\xc7\x1b\x90\x19\x91h\x11\xf4\xb2\nN\x89\x1f9\x9b\x148\xa1\x00\x00\x00\u07d4\xd4`\xa4\xb9\b\xdd+\x05gY\xb4\x88\x85\vf\xa88\xfcw\xa8\x89j\xcb=\xf2~\x1f\x88\x00\x00\u07d4\xd4g\xcf\x06L\bq\x98\x9b\x90\u0632\xeb\x14\xcc\xc6;6\b#\x89\n\u05ce\xbcZ\xc6 \x00\x00\u07d4\xd4k\xaea\xb0'\xe5\xbbB.\x83\xa3\xf9\xc9?<\x8f\xc7}'\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\xd4o\x82#E)\x82\xa1\xee\xa0\x19\xa8\x81n\xfc-o\xc0\ah\x89\amA\xc6$\x94\x84\x00\x00\u07d4\xd4uG\u007f\xa5c\x90\xd30\x17Q\x8dg\x11\x02\u007f\x05\U0008dfc9k\x11\x133\xd4\xfdL\x00\x00\u07d4\xd4|$.\xdf\xfe\xa0\x91\xbcT\xd5}\xf5\xd1\xfd\xb91\x01Gl\x89\x9d\xf7\u07e8\xf7`H\x00\x00\u07d4\xd4}\x86\x85\xfa\xee\x14|R\x0f\u0646p\x91u\xbf/\x88k\xef\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\xd4\u007fP\u07c9\xa1\xcf\xf9e\x13\xbe\xf1\xb2\xae:)q\xac\xcf,\x89-\x89W}}@ \x00\x00\u07d4\u0502\xe7\xf6\x8eA\xf28\xfeQx)\xde\x15G\u007f\xe0\xf6\xdd\x1d\x89\x1b\x1a\xe4\xd6\xe2\xefP\x00\x00\u07d4\u0507\x9f\xd1+\x1f:'\xf7\xe1\tv\x1b#\xca4<H\xe3\u0609$\x1a\x9bOaz(\x00\x00\u07d4\u050e?\x93W\xe3\x03Q8A\xb3\xf8K\u0683\xfc\x89ru\x87\x8965\u026d\xc5\u07a0\x00\x00\xe0\x94\u051au\xbb\x93?\xca\x1f\u029a\xa10:d\xb6\xcbD\xea0\xe1\x8a\x02\x1e\x19\xe0\u027a\xb2@\x00\x00\u07d4\u0530\x85\xfb\bo=\rh\xbf\x12\x92k\x1c\xc3\x14,\xae\x87p\x89\u0213\u041c\x8fQP\x00\x00\u07d4\u0532\xff;\xae\x19\x93\xff\xeaM;\x18\x021\xdaC\x9fu\x02\xa2\x89lk\x93[\x8b\xbd@\x00\x00\xe0\x94\u0533\x8a_\xdbc\xe0\x17\x14\xe9\x80\x1d\xb4{\u0250\xbdP\x91\x83\x8a\x01E4\xd9[\xef\x90\\\x00\x00\u07d4\u0538\xbd\xf3\u07daQ\xb0\xb9\x1d\x16\xab\xbe\xa0[\xb4x<\x86a\x8965\u026d\xc5\u07a0\x00\x00\u07d4\xd4\xc4\u0467\xc3\xc7I\x84\xf6\x85{/_\a\xe8\xfa\xceh\x05m\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\xd4\u01act.|\x85}J\x05\xa0L3\xd4\xd0\\\x14gW\x1d\x89\n\u05ce\xbcZ\xc6 \x00\x00\u07d4\xd4\xcb!\xe5\x90\u0160\xe0h\x016j\xff4,}}\xb1d$\x89\x1a\u01e0\x8e\xad\x02\xf8\x00\x00\u07d4\xd4\xd9,b\xb2\x80\xe0\x0fbm\x86W\xf1\xb8af\xcb\x1ft\x0f\x89\n\xd7\xf264\xcb\xd6\x00\x00\u07d4\xd4\ubc52\x9a#\x87\x1c\xf7\u007f\xe0I\xab\x96\x02\xbe\b\xbe\ns\x89g\x8a\x93 b\xe4\x18\x00\x00\xe0\x94\xd4\xeeI\x19\xfb7\xf2\xbb\x97\f?\xffT\xaa\xf1\xf3\u0766\xc0?\x8a\bxg\x83&\xea\xc9\x00\x00\x00\u07d4\xd4\xfe\xed\x99\xe8\x91|\\TXc_6\x03\xec\xb7\xe8\x17\xa7\u0409\x10C\xc4<\xde\x1d9\x80\x00\u07d4\xd4\xffF >\xfa#\x06K\x1c\xaf\x00Qn(pJ\x82\xa4\xf8\x89Hz\x9a0E9D\x00\x00\u07d4\xd5\x00\xe4\xd1\u0242K\xa9\xf5\xb65\u03e3\xa8\xc2\u00cb\xbdL\xed\x89\x15\xaf\x1dx\xb5\x8c@\x00\x00\u07d4\xd5\b\u04dcp\x91oj\xbcL\xc7\xf9\x99\xf0\x11\xf0w\x10X\x02\x89\x05rM$\xaf\xe7\u007f\x00\x00\u07d4\xd5\x0f\u007f\xa0>8\x98v\u04d0\x8b`\xa57\xa6pc\x04\xfbV\x89\x05k\xc7^-c\x10\x00\x00\u07d4\xd5\x13\xa4P\x80\xff/\xeb\xe6,\u0545J\xbe)\xeeDg\xf9\x96\x89\bN\x13\xbcO\xc5\xd8\x00\x00\u07d4\xd5'o\f\xd5\xff\xd5\xff\xb6?\x98\xb5p=U\x94\xed\xe0\x83\x8b\x89\x15\xaf\x1dx\xb5\x8c@\x00\x00\u07d4\xd5)KfbB0;m\xf0\xb1\u020d7B\x9b\xc8\xc9e\xaa\x89\x10M\r\x00\u04b7\xf6\x00\x00\u07d4\xd5*\xec\xc6I98\xa2\x8c\xa1\xc3g\xb7\x01\xc2\x15\x98\xb6\xa0.\x89;\xa1\x91\v\xf3A\xb0\x00\x00\u07d4\xd5<V\u007f\f?\xf2\xe0\x8b}Y\xe2\xb5\xc74\x85C\u007f\u014d\x89 \x86\xac5\x10R`\x00\x00\u07d4\xd5A\xac\x18z\xd7\xe0\x90R-\xe6\xda2\x13\xe9\xa7\xf4C\x96s\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\xd5K\xa2\xd8V\x81\xdc\x13\x0e[\x9b\x02\xc4\xe8\xc8Q9\x1f\u0679\x89\u0556{\xe4\xfc?\x10\x00\x00\u07d4\xd5U\b\xad\xbb\xbe\x9b\xe8\x1b\x80\xf9zn\xa8\x9a\xddh\xdagO\x89lk\x93[\x8b\xbd@\x00\x00\xe0\x94\xd5U\f\xaa\xf7C\xb07\xc5o\xd2U\x8a\x1c\x8e\xd25\x13\aP\x8a\x01!\xe4\u05106%[\x00\x00\u07d4\xd5Xm\xa4\u5543\xc8\xd8l\xcc\xf7\x1a\x86\x19\u007f\x17\x99gI\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\xd5\\\x1c\x8d\xfb\xe1\xe0,\xac\xbc\xa6\x0f\xdb\xdd@[\t\xf0\xb7_\x89lk\x93[\x8b\xbd@\x00\x00\xe0\x94\xd5a\u02fc\x05Q]\xe7:\xb8\u03de\xae\x13W4\x1e}\xfd\xf4\x8a\x01EB\xba\x12\xa37\xc0\x00\x00\xe0\x94\xd5j\x14Mz\xf0\xae\x8d\xf6I\xab\xaeSZ\x15\x98:\xa0M\x02\x8a\x01\x0f\f\xf0d\xddY \x00\x00\xe0\x94\xd5r0\x91i\xb1@.\xc8\x13\x1a\x17\xa6\xaa\xc3\"/\x89\xe6\xeb\x8a\x02\xec\x19x\xc4wf\xa0\x00\x00\u07d4\xd5xvh\xc2\xc5\x17[\x01\xa8\xee\x1a\xc3\xec\xc9\u0232\xab\xa9Z\x89lj\xccg\u05f1\xd4\x00\x00\u07d4\u0548\u00e5\xdf\"\x81\x85\u064e\xe7\xe6\aH%\\\u07a6\x8b\x01\x89\xd8\xd7&\xb7\x17z\x80\x00\x00\u07d4\u054aR\xe0x\xa8\x05Yk\rV\xeaJ\xe13Z\xf0\x1cf\xeb\x89\x0e~\xeb\xa3A\vt\x00\x00\xe0\x94\u0550>\x99x\xee \xa3\x8c?I\x8dc\xd5\u007f1\xa3\x9fj\x06\x8a\x022\xb3o\xfcg*\xb0\x00\x00\u07d4\u05568\xd3\xc5\xfa\xa7q\x1b\xf0\x85t_\x9d[\xdc#\u0518\u0609lk\x93[\x8b\xbd@\x00\x00\xe0\x94\u055d\x92\xd2\xc8p\x19\x80\xcc\a<7]r\n\xf0dt<\f\x8a\x04\x05\xfd\xf7\u5bc5\xe0\x00\x00\u07d4\u0567\xbe\xc32\xad\xde\x18\xb3\x10KW\x92Tj\xa5\x9b\x87\x9bR\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\u0571\x17\xec\x11n\xb8FA\x89a\xeb~\xdbb\x9c\xd0\xddi\u007f\x89\xa2\xa1]\tQ\x9b\xe0\x00\x00\u07d4\u0572\x84\x04\x010\xab\xf7\xc1\xd1cq#q\xcc~(\xadf\u0689j\xcb=\xf2~\x1f\x88\x00\x00\u07d4\u0579\xd2w\u062a\xd2\x06\x97\xa5\x1fv\xe2\tx\x99k\xff\xe0U\x89\a\xc3\xfe<\aj\xb5\x00\x00\u07d4\u057d^\x84U\xc10\x16\x93W\xc4q\xe3\u6077\x99jrv\x89-\x9e(\x8f\x8a\xbb6\x00\x00\u07d4\xd5\u02e5\xb2k\xea]s\xfa\xbb\x1a\xba\xfa\xcd\xef\x85\xde\xf3h\u0309\n\u05ce\xbcZ\xc6 \x00\x00\u07d4\xd5\xceU\u0476/YC<!&\xbc\xec\t\xba\xfc\x9d\xfa\xa5\x14\x89\n\xad\xec\x98?\xcf\xf4\x00\x00\u07d4\xd5\xe5Q\x00\xfb\u0455k\xbe\xd2\xcaQ\x8dK\x1f\xa3v\x03+\v\x89\x05k\xc7^-c\x10\x00\x00\u07d4\xd5\xe5\xc15\xd0\xc4\xc3094q\x19\x93\xd0\xd1o\xf9\u7ea0\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\xd5\xe6V\xa1\xb9\x16\xf9\xbfE\xaf\xb0}\u062f\xafs\xb4\xc5oA\x89\x05B%:\x12l\xe4\x00\x00\xe0\x94\xd5\xeaG,\xb9F`\x18\x11\n\xf0\f7I[\\,q1\x12\x8a\x01\x0e\xeehl\x85OD\x00\x00\u07d4\xd5\xf0uR\xb5\u0193\xc2\x00g\xb3x\xb8\t\xce\xe8S\xb8\xf16\x89\x1bg\xc6\u07c8\xc6\xfa\x00\x00\u07d4\xd5\xf7\xc4\x1e\ar\x9d\xfam\xfcd\xc4B1`\xa2,`\x9f\u04c9a\t=|,m8\x00\x00\u07d4\xd6\x04\xab\xceC0\x84.=9l\xa7=\xdbU\x19\xed>\xc0?\x89\b\xe3\x1f\xe1h\x9d\x8a\x00\x00\u07d4\xd6\x06Q\xe3\x93x4#\xe5\xcc\x1b\xc5\xf8\x89\xe4N\xf7\xea$>\x89\x15\x9ev7\x11)\xc8\x00\x00\u07d4\xd6\t\xbfO\x14n\xeak\r\xc8\xe0m\xdc\xf4D\x8a\x1f\xcc\xc9\xfa\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\xd6\t\xec\v\xe7\r\n\xd2ong\xc9\xd4v+R\xeeQ\x12,\x8965\u026d\xc5\u07a0\x00\x00\u07d4\xd6\nRX\a(R\r\xf7Tk\xc1\xe2\x83)\x17\x88\u06ee\f\x8964\x89\xef?\xf0\xd7\x00\x00\u07d4\xd6\v$s!\xa3*Z\xff\xb9k\x1e'\x99'\xccXM\xe9C\x89z\xd0 \xd6\xdd\xd7v\x00\x00\u07d4\xd6\x11\x02v\xcf\xe3\x1eB\x82ZW\u007fkC]\xbc\xc1\f\xf7d\x8965\u026d\xc5\u07a0\x00\x00\xe0\x94\xd6\x12Y{\xc3\x17C\u01c63\xf63\xf29\xb1\xe9Bk\xd9%\x8a\x10\x17\xf7\u07d6\xbe\x17\x80\x00\x00\u07d4\xd6#J\xafE\xc6\xf2.f\xa2%\xff\xb9:\xddb\x9bN\xf8\x0f\x8965\u026d\xc5\u07a0\x00\x00\u07d4\xd6.\u06d6\xfc\u259a\xaflT^\x96|\xf1\xc0\xbc\x80R\x05\x89\x04\xa5eSjZ\u0680\x00\u07d4\xd60\v2\x15\xb1\x1d\xe7b\xec\xdeKp\xb7\x92}\x01)\x15\x82\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\xd69]\xb5\xa4\xbbf\xe6\x0fL\xfb\xcd\xf0\x05{\xb4\xd9xb\xe2\x891T\xc9r\x9d\x05x\x00\x00\xe0\x94\xd6J-P\xf8\x85\x857\x18\x8a$\xe0\xf5\r\xf1h\x1a\xb0~\u05ca\b7Z*\xbc\xca$@\x00\x00\u07d4\xd6X\n\xb5\xedL}\xfaPo\xa6\xfed\xad\\\xe1)pw2\x89\xd8\xd7&\xb7\x17z\x80\x00\x00\u07d4\xd6Y\x8b\x13\x86\xe9<\\\u02d6\x02\xffK\xbb\xec\xdb\xd3p\x1d\u0109\f%\xf4\xec\xb0A\xf0\x00\x00\u07d4\xd6dM@\xe9\v\xc9\u007f\xe7\xdf\xe7\u02bd2i\xfdW\x9b\xa4\xb3\x89\b\x9e\x91y\x94\xf7\x1c\x00\x00\xe0\x94\xd6g\f\x03m\xf7T\xbeC\xda\u074fP\xfe\xea(\x9d\x06\x1f\u058a\x01D\xa2\x904H\xce\xf7\x80\x00\u07d4\xd6hR:\x90\xf0)=e\xc58\xd2\xddlWg7\x10\x19n\x89\x02$,0\xb8S\xee\x00\x00\u07d4\xd6j\xb7\x92\x94\aL\x8bb}\x84-\xabA\xe1}\xd7\f]\xe5\x8965\u026d\xc5\u07a0\x00\x00\u0794\xd6j\xcc\r\x11\xb6\x89\u03a6\xd9\xea_\xf4\x01L\"J]\xc7\u0108\xfc\x93c\x92\x80\x1c\x00\x00\u07d4\xd6m\xdf\x11Y\xcf\"\xfd\x8czK\xc8\u0540wV\xd43\xc4>\x89wC\"\x17\xe6\x83`\x00\x00\u07d4\u0587\xce\xc0\x05\x90\x87\xfd\xc7\x13\xd4\xd2\xd6^w\xda\xef\xed\xc1_\x89\x03@\xaa\xd2\x1b;p\x00\x00\u07d4\u0588\xe7\x85\u024f\x00\xf8K:\xa1S3U\u01e2X\xe8yH\x89\x1b\x1a\xe4\xd6\xe2\xefP\x00\x00\u07d4\u05a2.Y\x8d\xab\u04ce\xa6\xe9X\xbdy\u050d\u0756\x04\xf4\u07c965\u026d\xc5\u07a0\x00\x00\u07d4\u05a7\xacM\xe7\xb5\x10\xf0\xe8\xdeQ\x9d\x97?\xa4\xc0\x1b\xa84\x00\x89e\xea=\xb7UF`\x00\x00\u07d4\u05ac\xc2 \xba.Q\xdf\xcf!\xd4C6\x1e\xeav\\\xbd5\u0609\x01\x15\x8eF\t\x13\xd0\x00\x00\u07d4\u05ac\xff\u043f\u065c8.{\xd5o\xf0\xe6\x14J\x9eR\xb0\x8e\x89\b\xacr0H\x9e\x80\x00\x00\u07d4\xd6\xc0\u043c\x93\xa6.%qtp\x0e\x10\xf0$\u0232?\x1f\x87\x89lk\x93[\x8b\xbd@\x00\x00\xe0\x94\xd6\xcf\\\x1b\u03dd\xa6b\xbc\xea\"U\x90P\x99\xf9\xd6\xe8M\u030a\x01\u011eB\x01W\xd9\xc2\x00\x00\u07d4\xd6\xd05r\xa4RE\xdb\xd46\x8cO\x82\xc9W\x14\xbd!g\xe2\x89?\x00\xc3\xd6f\x86\xfc\x00\x00\u07d4\xd6\xd6wiX\xee#\x14:\x81\xad\xad\xeb\b8 \t\xe9\x96\u0089\xa2\xa1]\tQ\x9b\xe0\x00\x00\u07d4\xd6\xd9\xe3\x0f\bB\x01*qv\xa9\x17\xd9\xd2\x04\x8c\xa0s\x87Y\x89\xd8\xd7&\xb7\x17z\x80\x00\x00\u07d4\xd6\xe0\x9e\x98\xfe\x13\x003!\x04\xc1\xca4\xfb\xfa\xc5T6N\u0649lk\x93[\x8b\xbd@\x00\x00\u07d4\xd6\xe8\xe9z\u90db\x9e\xe5\a\xee\xdb(\xed\xfbtw\x03\x149\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\xd6\uea18\u052e+q\x80'\xa1\x9c\xe9\xa5\xebs\x00\xab\xe3\u0289\x01}J\xce\xeec\u06c0\x00\xe0\x94\xd6\xf1\xe5[\x16\x94\b\x9e\xbc\xb4\xfe}x\x82\xaaf\u0217av\x8a\x04<#\xbd\xbe\x92\x9d\xb3\x00\x00\u07d4\xd6\xf4\xa7\xd0N\x8f\xaf \xe8\xc6\ub15c\xf7\xf7\x8d\xd2=z\x15\x89\a$\xde\xd1\xc7H\x14\x00\x00\u07d4\xd6\xfc\x04F\u01a8\xd4\n\xe3U\x1d\xb7\xe7\x01\xd1\xfa\x87nJI\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\xd7\x03\u01a4\xf1\x1d`\x19Ey\u054c'f\xa7\xef\x16\xc3\n)\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\xd7\x05%\x19uj\xf4%\x90\xf1S\x91\xb7#\xa0?\xa5d\xa9Q\x89\xfa61H\r\x01\xfd\x80\x00\u07d4\xd7\na+\xd6\u0769\xea\xb0\xdd\xdc\xffJ\xafA\"\u04cf\xea\xe4\x89\x1dF\x01b\xf5\x16\xf0\x00\x00\u07d4\xd7\n\xd2\xc4\xe9\uefe67\xefV\xbdHj\u04a1\xe5\xbc\xe0\x93\x89\n\u05ce\xbcZ\xc6 \x00\x00\u07d4\xd7\x14\f\x8eZC\a\xfa\xb0\xcc'\xba\u0752\x95\x01\x8b\xf8yp\x89\x05\xf1\x01kPv\xd0\x00\x00\u07d4\xd7\x16J\xa2a\xc0\x9a\u0672\xb5\x06\x8dE>\xd8\xebj\xa10\x83\x89\xa2\xa1]\tQ\x9b\xe0\x00\x00\u07d4\xd7\x1eC\xa4Qw\xadQ\xcb\xe0\xf7!\x84\xa5\xcbP9\x17(Z\x89\n\u05ce\xbcZ\xc6 \x00\x00\u07d4\xd7\x1f\xb10\xf0\x15\fVRi\xe0\x0e\xfbC\x90+R\xa4U\xa6\x89\n\u05ce\xbcZ\xc6 \x00\x00\u07d4\xd7\"W8\xdc\xf3W\x848\xf8\xe7\u0233\x83~B\xe0J&/\x89\x18+\x8c\ubec3\xaa\x00\x00\u07d4\xd7'MP\x80M\x9cw\u0693\xfaH\x01V\xef\xe5{\xa5\x01\u0789i*\xe8\x89p\x81\xd0\x00\x00\u07d4\xd71\xbbk_<79^\t\u03ac\xcd\x14\xa9\x18\xa6\x06\a\x89\x89\u0556{\xe4\xfc?\x10\x00\x00\xe0\x94\xd7>\xd2\u0645\xb5\xf2\x1bU\xb2td;\xc6\xda\x03\x1d\x8e\u074d\x8a\nm\xd9\f\xaeQ\x14H\x00\x00\u07d4\xd7D\xac~S\x10\xbeijc\xb0\x03\xc4\v\xd097\x05a\u0189Z\x87\xe7\xd7\xf5\xf6X\x00\x00\xe0\x94\xd7Jn\x8dj\xab4\u0385\x97h\x14\xc12{\xd6\xea\a\x84\u048a\x15-\x02\xc7\xe1J\xf6\x80\x00\x00\u07d4\xd7ZP*[gr\x87G\x0fe\u016aQ\xb8|\x10\x15\x05r\x8910\xb4dc\x85t\x00\x00\u07d4\xd7m\xba\xeb\xc3\rN\xf6{\x03\xe6\xe6\xec\xc6\xd8N\x00MP-\x89mv\xb9\x18\x8e\x13\x85\x00\x00\u07d4\xd7q\xd9\xe0\u028a\b\xa1\x13wW1CN\xb3'\x05\x99\xc4\r\x89\x01\x15\x8eF\t\x13\xd0\x00\x00\xe0\x94\xd7x\x8e\xf2\x86X\xaa\x06\xccS\xe1\xf3\xf0\xdeX\xe5\xc3q\xbex\x8a\x01je\x02\xf1Z\x1eT\x00\x00\u07d4\xd7x\x92\xe2';#]v\x89\xe40\xe7\xae\ud73c\xe8\xa1\xf3\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\u05c1\xf7\xfc\t\x18F\x11V\x85p\xb4\x98n,r\x87+~\u0409\x01\x15\x95a\x06]]\x00\x00\u07d4\u05c5\xa8\xf1\x8c8\xb9\xbcO\xfb\x9b\x8f\xa8\xc7r{\xd6B\xee\x1c\x8965\u026d\xc5\u07a0\x00\x00\u07d4\u05ce\xcd%\xad\xc8k\xc2\x05\x1d\x96\xf6Sd\x86kB\xa4&\xb7\x89\xd20X\xbf/&\x12\x00\x00\xe0\x94\u05cf\x84\xe3\x89D\xa0\xe0%_\xae\xceH\xbaIP\u053d9\u048a\x01\x0f\f\xf0d\xddY \x00\x00\u07d4\u05d4\x83\xf6\xa8DO%I\xd6\x11\xaf\xe0,C-\x15\xe1\x10Q\x89\x01\x15\x8eF\t\x13\xd0\x00\x00\u07d4\u05d85\xe4\x04\xfb\x86\xbf\x84_\xba\t\rk\xa2^\f\x88f\xa6\x89\x82\x1a\xb0\xd4AI\x80\x00\x00\u07d4\u05da\xff\x13\xba-\xa7]F$\f\xac\n$g\xc6V\x94\x98#\x89]\u0212\xaa\x111\xc8\x00\x00\u07d4\u05dd\xb5\xabCb\x1az=\xa7\x95\xe5\x89)\xf3\xdd%\xafg\u0649lj\xccg\u05f1\xd4\x00\x00\u07d4\u05e1C\x1e\xe4S\xd1\xe4\x9a\x05P\xd1%hy\xb4\xf5\xd1\x02\x01\x89Z\x87\xe7\xd7\xf5\xf6X\x00\x00\u07d4\u05ed\t\xc6\xd3&WhSU\xb5\xc6\uc39fW\xb4\ube42\x89j\xcb=\xf2~\x1f\x88\x00\x00\u07d4\u05f7@\xdf\xf8\xc4Wf\x8f\xdft\xf6\xa2f\xbf\xc1\u0737#\xf9\x89\x01\x15\x8eF\t\x13\xd0\x00\x00\xe0\x94\xd7\u0080>\u05f0\xe0\x83sQA\x1a\x8ef7\xd1h\xbc[\x05\x8a\x06A\xda\xf5\xc9\x1b\xd95\x80\x00\u07d4\xd7\xc6&]\xea\x11\x87l\x90;q\x8eL\u062b$\xfe&[\u0789lk\x93[\x8b\xbd@\x00\x00\u07d4\xd7\xca\u007f\xdc\xfe\xbeE\x88\xef\xf5B\x1d\x15\"\xb6\x13(\xdf{\xf3\x89\xd8\xe6\x00\x1el0+\x00\x00\u07d4\xd7\u037dA\xff\xf2\r\xf7'\xc7\vbU\xc1\xbav\x06\x05Th\x89\n\u05ce\xbcZ\xc6 \x00\x00\u07d4\xd7\xd1W\xe4\xc0\xa9d7\xa6\u0485t\x1d\xd2>\xc46\x1f\xa3k\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\xd7\xd2\xc6\xfc\xa8\xad\x1fu9R\x10\xb5}\xe5\xdf\xd6s\x939\t\x89\x12nr\xa6\x9aP\xd0\x00\x00\xe0\x94\xd7\xd3\xc7Y Y\x048\xb8,>\x95\x15\xbe.\xb6\xedz\x8b\x1a\x8a\f\xb4\x9bD\xba`-\x80\x00\x00\u07d4\xd7\xd7\xf2\u02a4b\xa4\x1b;0\xa3J\xeb;\xa6\x10\x10\xe2bo\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\xd7\xe7J\xfd\xba\xd5^\x96\u03bcZ7O,\x8bv\x86\x80\xf2\xb0\x89\x05]\xe6\xa7y\xbb\xac\x00\x00\xe0\x94\xd7\xeb\x901b'\x1c\x1a\xfa5\xfei\xe3s\"\u0224\u049b\x11\x8a\x02\x1e\x19\xe0\u027a\xb2@\x00\x00\u07d4\xd7\xeb\u0779\xf99\x87w\x9bh\x01U7T8\xdbe\xaf\xcbj\x89\x05t\x1a\xfe\xff\x94L\x00\x00\u07d4\xd7\xef4\x0ef\xb0\u05ef\xcc\xe2\n\x19\xcb{\xfc\x81\xda3\xd9N\x89\xa2\xa1]\tQ\x9b\xe0\x00\x00\u07d4\xd7\xf3p\u053e\xd9\xd5|oI\u0259\xder\x9e\xe5i\xd3\xf4\xe4\x89\n\u05ce\xbcZ\xc6 \x00\x00\u07d4\xd7\xfa_\xfb`H\xf9o\xb1\xab\xa0\x9e\xf8{\x1c\x11\xddp\x05\xe4\x8965\u026d\xc5\u07a0\x00\x00\u07d4\xd8\x06\x9f\x84\xb5!I?G\x15\x03\u007f2&\xb2_3\xb6\x05\x86\x89g\x8a\x93 b\xe4\x18\x00\x00\u0794\xd8\x15\xe1\xd9\xf4\xe2\xb5\xe5~4\x82k|\xfd\x88\x81\xb8Th\x90\x88\xf0\x15\xf2W6B\x00\x00\u07d4\xd8\x1b\xd5K\xa2\xc4Jok\xeb\x15a\u058b\x80\xb5DNm\u0189?\x17\r~\xe4<C\x00\x00\xe0\x94\xd8\"QEm\xc18\x0f\x8fV\x92\xf9b\x82\x86@\xab\x9f*\x03\x8a\x01\b\x8bS\xb2\xc2\x02\xbe\x00\x00\u07d4\xd8,o\xed\xbd\xac\x98\xaf.\xed\x10\xb0\x0f2\xb0\x00V\xcaZm\x89\n\u05ce\xbcZ\xc6 \x00\x00\u07d4\xd8/\xd9\xfd\xf6\x99k\xed\xad(C\x15\x9c\x06\xf3~\t$3}\x89[\x8c\xce\xdcZ\xa7\xb0\x00\x00\u07d4\xd8:\xd2`\xe9\xa6\xf42\xfbn\xa2\x87C)\x9bJ\t\xade\x8c\x89lk\x93[\x8b\xbd@\x00\x00\u0794\xd8C\xee\bc\u0393>\"\xf8\x9c\x80-1({\x96q\xe8\x1c\x88\xb9\x8b\xc8)\xa6\xf9\x00\x00\u07d4\xd8K\x92/xA\xfcWt\xf0\x0e\x14`J\xe0\xdfB\xc8U\x1e\x89\xd9o\u0390\u03eb\xcc\x00\x00\u07d4\xd8U\xb0<\xcb\x02\x9awG\xb1\xf0s\x03\xe0\xa6dy59\u0209lk\x93[\x8b\xbd@\x00\x00\u07d4\xd8_\u07af*a\xf9]\xb9\x02\xf9\xb5\xa5<\x9b\x8f\x92f\u00ec\x89l\xf6Z~\x90G(\x00\x00\u07d4\xd8q^\xf9\x17o\x85\v.0\xeb\x8e8'\a\xf7w\xa6\xfb\xe9\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\xd8t\xb9\u07eeEj\x92\x9b\xa3\xb1\xa2~W,\x9b,\xec\u07f3\x89\t79SM(h\x00\x00\u07d4\u0613\n9\xc7sW\xc3\n\u04e0`\xf0\v\x06\x04c1\xfdb\x89,s\xc97t,P\x00\x00\u07d4\u061b\xc2q\xb2{\xa3\xabib\xc9JU\x90\x06\xae8\xd5\xf5j\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\u0637}\xb9\xb8\x1b\xbe\x90B{b\xf7\x02\xb2\x01\xff\u009f\xf6\x18\x892m\x1eC\x96\xd4\\\x00\x00\u07d4\xd8\xcdd\xe0(N\xecS\xaaF9\xaf\xc4u\b\x10\xb9\u007f\xabV\x89\x01\x15\x8eF\t\x13\xd0\x00\x00\u07d4\xd8\xd6C\x84$\x9bwg\x94\x06;V\x98x\xd5\xe3\xb50\xa4\xb2\x89\t\xa0C\u0432\xf9V\x80\x00\u07d4\xd8\xd6T \xc1\x8c#'\xccZ\xf9t%\xf8W\xe4\xa9\xfdQ\xb3\x89_h\xe8\x13\x1e\u03c0\x00\x00\u07d4\xd8\xe5\xc9g^\xf4\xde\xed&k\x86\x95o\xc4Y\x0e\xa7\u0522}\x8965\u026d\xc5\u07a0\x00\x00\xe0\x94\xd8\xe8GB\x92\xe7\xa0Q`L\xa1d\xc0pw\x83\xbb(\x85\xe8\x8a\x02\xd4\xca\x05\xe2\xb4<\xa8\x00\x00\u07d4\xd8\xebxP>\xc3\x1aT\xa9\x016x\x1a\xe1\t\x00Lt2W\x8965\u026d\xc5\u07a0\x00\x00\u07d4\xd8\xee\xf4\xcfK\xeb\x01\xee \xd1\x11t\x8ba\xcbM?d\x1a\x01\x89\x94\x89#z\u06daP\x00\x00\u07d4\xd8\xf4\xba\xe6\xf8M\x91\rm}Z\xc9\x14\xb1\xe6\x83r\xf9A5\x89\x05k\xc7^-c\x10\x00\x00\u07d4\xd8\xf6 6\xf0;v5\xb8X\xf1\x10?\x8a\x1d\x90\x19\xa8\x92\xb6\x89\x02\xb5\xe3\xaf\x16\xb1\x88\x00\x00\u07d4\xd8\xf6e\xfd\x8c\xd5\u00bc\xc6\xdd\xc0\xa8\xaeR\x1eM\u01aa``\x89\\(=A\x03\x94\x10\x00\x00\u07d4\xd8\xf9$\fU\xcf\xf05R<m[\xd3\x00\xd3p\u070f\f\x95\x89\x0fs+f\x01ZT\x00\x00\xe0\x94\xd8\xf9EyIg%\xb5\xcbS\u05d8\\\x98\x97I\xaf\xf8I\xc0\x8a\x03\x99\x92d\x8a#\u0220\x00\x00\u07d4\xd8\xfd\xf5FgG8\u0244\xd8\xfa\xb8W\x88\v>B\x80\xc0\x9e\x89\x01\x15\x8eF\t\x13\xd0\x00\x00\u07d4\xd8\xfe\b\x8f\xff\u0394\x8fQ7\xee#\xb0\x1d\x95\x9e\x84\xacB#\x89\f[T\xa9O\xc0\x17\x00\x00\u07d4\xd9\x0f0\t\xdbC~N\x11\u01c0\xbe\u0209os\x8de\xef\r\x89\xd8\xd7&\xb7\x17z\x80\x00\x00\u07d4\xd9\x10;\xb6\xb6zU\xa7\xfe\xce-\x1a\xf6-E|!x\x94m\x8965\u026d\xc5\u07a0\x00\x00\u07d4\xd9\x13\xf0w\x19Iu<G&\xac\xaa+\xd3a\x9c\\ \xffw\x89\xa2\xa1]\tQ\x9b\xe0\x00\x00\u07d4\xd9\x1d\x88\x91dG\x9c\xe46\xec\xe5\x17c\xe2,\xda\x19\xb2-k\x89\xb6m\x88\x12h\x00\x88\x00\x00\u07d4\xd9)\xc6]i\u057b\xae\xa5\x97bf.\xf4\x18\xbc!\xad\x92J\x8965\u026d\xc5\u07a0\x00\x00\u07d4\xd90\xb2zx\x87d\x85\xd0\xf4\x8bp\xddS6T\x96y\u028f\x89\x02+\x1c\x8c\x12'\xa0\x00\x00\u07d4\xd91\xac&h\xbaj\x84H\x1a\xb19sZ\xec\x14\xb7\xbf\xba\xbf\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\xd98=Km\x17\xb3\xf9\xcdBn\x10\xfb\x94@\x15\xc0\xd4K\xfb\x89+^:\xf1k\x18\x80\x00\x00\xe0\x94\xd9B\xdeG\x84\xf7\xa4\x87\x16\xc0\xfdK\x9dT\xa6\xe5L_/>\x8a\x04<3\xc1\x93ud\x80\x00\x00\u07d4\xd9D\u0226\x9f\xf2\xca\x12Ii\f\x12)\xc7\x19/6%\x10b\x89j\xcb=\xf2~\x1f\x88\x00\x00\u07d4\xd9JW\x88*Rs\x9b\xbe*\x06G\xc8\f$\xf5\x8a+O\x1c\x89H\xb5N*\xdb\xe1+\x00\x00\xe0\x94\xd9SB\x95<\x8a!\xe8\xb65\xee\xfa\u01c1\x9b\xea0\xf1pG\x8a\x13\xf0l\u007f\xfe\xf0]@\x00\x00\u07d4\xd9\\\x90\xff\xbeT\x84\x86G\x80\xb8gIJ\x83\u0212V\xd6\xe4\x89X\xe7\x92n\xe8X\xa0\x00\x00\u07d4\xd9g\x11T\x0e.\x99\x83C\xd4\xf5\x90\xb6\xfc\x8f\xac;\xb8\xb3\x1d\x89_Z@h\xb7\x1c\xb0\x00\x00\u07d4\xd9j\xc2Pt\t\u01e3\x83\xab.\xee\x18\"\xa5\xd78\xb3kV\x89\n\u05ce\xbcZ\xc6 \x00\x00\u07d4\xd9m\xb3;{Z\x95\f>\xfa-\xc3\x1b\x10\xba\x10\xa52\uf1c9lk\x93[\x8b\xbd@\x00\x00\xe0\x94\xd9wYe\xb7\x16Gfu\xa8\xd5\x13\xeb\x14\xbb\xf7\xb0|\xd1J\x8a\x01\x13.m-#\xc5\xe4\x00\x00\u07d4\xd9{\xc8J\xbdG\xc0[\xbfE{.\xf6Y\xd6\x1c\xa5\xe5\u43c9\x06\x9d\x17\x11\x9d\u0168\x00\x00\u07d4\xd9\u007fE&\u07a9\xb1c\xf8\xe8\xe3:k\u03d2\xfb\x90}\xe6\xec\x89\x0feJ\xafM\xb2\xf0\x00\x00\u07d4\xd9\u007f\xe6\xf5?*X\xf6\xd7mu*\xdft\xa8\xa2\xc1\x8e\x90t\x89\x10\xcd\xf9\xb6\x9aCW\x00\x00\u07d4\u0659\x99\xa2I\r\x94\x94\xa50\xca\xe4\xda\xf3\x85T\xf4\xddc>\x89\x06\x81U\xa46v\xe0\x00\x00\u07d4\u065d\xf7B\x1b\x93\x82\xe4,\x89\xb0\x06\xc7\xf0\x87p*\aW\xc0\x89\x1a\x05V\x90\xd9\u06c0\x00\x00\xe0\x94\u0677\x83\xd3\x1d2\xad\xc5\x0f\xa3\xea\u02a1]\x92\xb5h\xea\xebG\x8a\a3\xaf\x907L\x1b(\x00\x00\u07d4\xd9\xd3p\xfe\xc65v\xab\x15\xb3\x18\xbf\x9eX6M\u00a3U*\x89\x05k\xc7^-c\x10\x00\x00\xe0\x94\xd9\xd4/\xd1>\xbdK\xf6\x9c\xac^\x9c~\x82H:\xb4m\xd7\xe9\x8a\x01!\xeah\xc1\x14\xe5\x10\x00\x00\u07d4\xd9\xe2~\xb0}\xfcq\xa7\x06\x06\f\u007f\a\x928\u0293\xe8\x859\x8965\u026d\xc5\u07a0\x00\x00\u07d4\xd9\xe3\x85~\xfd\x1e *D\x17p\xa7w\xa4\x9d\xccE\xe2\xe0\u04c9\f\x1d\xaf\x81\u0623\xce\x00\x00\u07d4\xd9\xec.\xfe\x99\xff\\\xf0\r\x03\xa81{\x92\xa2J\xefD\x1f~\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\xd9\xec\x8f\xe6\x9bw\x16\xc0\x86Z\xf8\x88\xa1\x1b+\x12\xf7 \xed3\x89\xd8\xd7&\xb7\x17z\x80\x00\x00\u07d4\xd9\xf1\xb2d\b\xf0\xecg\xad\x1d\ro\xe2.\x85\x15\xe1t\x06$\x89\x01M\x11 \u05f1`\x00\x00\u07d4\xd9\xf5G\xf2\xc1\xde\x0e\u064aS\xd1a\xdfWc]\xd2\x1a\x00\xbd\x89\x05V\xf6L\x1f\xe7\xfa\x00\x00\u07d4\xd9\xff\x11]\x01&l\x9fs\xb0c\xc1\xc28\xef5e\xe6;6\x89$\xdc\xe5M4\xa1\xa0\x00\x00\u07d4\xda\x06\x04N)<e,F\u007f\xe7AF\xbf\x18[!3\x8a\x1c\x8965\u026d\xc5\u07a0\x00\x00\u07d4\xda\vH\xe4\x89\xd3\x02\xb4\xb7\xbf O\x95|\x1c\x9b\u30f0\u07c9lk\x93[\x8b\xbd@\x00\x00\xe0\x94\xda\rK~\xf9\x1f\xb5Z\xd2e\xf2Q\x14 g\xf1\x03v\xce\u058a\x04<3\xc1\x93ud\x80\x00\x00\u07d4\xda\x10\x97\x8a9\xa4o\U0003b10c\xf6]\xd9\xc7u\t\xa6\xd7\x0e\x89lk\x93[\x8b\xbd@\x00\x00\xe0\x94\xda\x16\xdd\\=\x1a'\x145\x8f\xe3u,\xaeS\u06eb+\u930a\x04\x1b\xad\x15^e\x12 \x00\x00\u07d4\xda!L\x02>#&\xffil\x0091h\xceF\xff\xac9\xec\x8965\u026d\xc5\u07a0\x00\x00\u07d4\xda*\x14\xf9r@\x15\u05d0\x14\xed\x8eY\th\x1dYaH\xf1\x89\x02\xa1\x0f\x0f\x8a\x91\xab\x80\x00\u07d4\xda*\u054ew\xde\xdd\xed\xe2\x18vF\xc4e\x94Z\x8d\xc3\xf6A\x89#\xc7W\a+\x8d\xd0\x00\x00\u07d4\xda0\x17\xc1P\xdd\r\xce\u007f\u03c8\x1b\nH\xd0\xd1\xc7V\xc4\u01c9\x05k\xf9\x1b\x1ae\xeb\x00\x00\u07d4\xda4\xb2\xea\xe3\v\xaf\xe8\xda\xec\xcd\xe8\x19\xa7\x94\u0349\xe0\x95I\x89lk\x93[\x8b\xbd@\x00\x00\xe0\x94\xdaJ_U\u007f;\xab9\n\x92\xf4\x9b\x9b\x90\n\xf3\fF\xae\x80\x8a\x02\x1e\x19\xe0\u027a\xb2@\x00\x00\u07d4\xdaPU7S\u007f\xfb3\xc4\x15\xfe\xc6Ni\xba\xe0\x90\xc5\xf6\x0f\x89\b\xacr0H\x9e\x80\x00\x00\u07d4\xdai\x8dd\xc6\\\u007f+,rS\x05\x9c\xd3\u0441\u0619\xb6\xb7\x89\x10\x04\xe2\xe4_\xb7\xee\x00\x00\u07d4\xdaw2\xf0/.'.\xaf(\u07d7.\xcc\r\xde\xed\x9c\xf4\x98\x89\v \xbf\xbfig\x89\x00\x00\u07d4\xdaz\xd0%\xeb\xde%\xd2\"C\u02c3\x0e\xa1\xd3\xf6JVc#\x89\x1b\x1a\xe4\xd6\xe2\xefP\x00\x00\xe0\x94\u0685]SG\u007fP^\xc4\xc8\xd5\u8ed1\x80\u04c6\x81\x11\x9c\x8a\x01/\x93\x9c\x99\xed\xab\x80\x00\x00\u07d4\u0687^N/<\xab\xe4\xf3~\x0e\xae\xd7\xd1\xf6\xdc\xc6\xff\xefC\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\u068b\xbe\xe1\x82\xe4U\xd2\t\x8a\xcb3\x8amE\xb4\xb1~\u0636\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\u0698.\x96C\xff\xec\xe7#\aZ@\xfewnZ\xce\x04\xb2\x9b\x89\b\xb8\xb6\u0259\x9b\xf2\x00\x00\u07d4\u069fUF\tF\u05ff\xb5p\xdd\xecu|\xa5w;XB\x9a\x89\x1b\x84]v\x9e\xb4H\x00\x00\u07d4\u06a1\xbdz\x91H\xfb\x86\\\xd6\x12\xdd5\xf1b\x86\x1d\x0f;\u0709\xa68\xabr\xd9,\x13\x80\x00\xe0\x94\u06a6<\xbd\xa4]\u0507\xa3\xf1\xcdJtj\x01\xbb^\x06\v\x90\x8a\x01\x04\x16\u0670*\x89$\x00\x00\u07d4\u06a7v\xa6uDi\u05f9&z\x89\xb8g%\xe7@\xda\x0f\xa0\x89j\xcb=\xf2~\x1f\x88\x00\x00\u07d4\u06ac\x91\xc1\xe8Y\xd5\xe5~\xd3\bKP \x0f\x97f\xe2\xc5+\x89\x15\xaf\x1dx\xb5\x8c@\x00\x00\u07d4\u06ac\xda\xf4\"&\xd1\\\xb1\u03d8\xfa\x15\x04\x8c\u007fL\xee\xfei\x89\x10CV\x1a\x88)0\x00\x00\xe0\x94\u06b6\xbc\u06c3\xcf$\xa0\xae\x1c\xb2\x1b;[\x83\xc2\xf3\x82I'\x8a\n\x96\x81c\xf0\xa5{@\x00\x00\u07d4\u06bb\b\x89\xfc\x04)&\xb0^\xf5{% \x91\n\xbcKAI\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\u06bc\"PB\xa6Y,\xfa\x13\xeb\xe5N\xfaA\x04\bx\xa5\xa2\x89\x0e\x11\xfa\xd5\xd8\\\xa3\x00\x00\u07d4\xda\xc0\xc1w\xf1\x1c\\>>x\xf2\xef\xd6c\xd12!H\x85t\x8965\u026d\xc5\u07a0\x00\x00\u07d4\xda\xd16\xb8\x81x\xb4\x83zlx\x0f\xeb\xa2&\xb9\x85i\xa9L\x89\n\u05ce\xbcZ\xc6 \x00\x00\u07d4\xda\xdb\xfa\xfd\x8bb\xb9*$\xef\xd7RV\u0743\xab\xdb\u05fb\u06c9\x01\x11du\x9f\xfb2\x00\x00\u07d4\xda\xdc\x00\xaby'`</\xcf1\xce\xe3R\xf8\x0elMcQ\x89lf\xe9\xa5Sx\xb8\x00\x00\u07d4\xda\xe0\xd3>\xaa4\x15i\xfa\x9f\xf5\x98&\x84\x85JJ2\x8an\x8965\u026d\xc5\u07a0\x00\x00\u07d4\xda\xe7 \x1e\xab\x8c\x063\x02\x93\ri9)\xd0\u007f\x95\xe7\x19b\x89\x91\xae\xc0(\xb4\x19\x81\x00\x00\u07d4\xda\xed\u052d\x10{'\x1e\x89Hl\xbf\x80\xeb\xd6!\u0757Ex\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\xdb\x04\xfa\xd9\u011f\x9e\x88\v\xeb\x8f\xcf\x1d:8\x90\u4cc4o\x89CZ\xe6\xcc\fX\xe5\x00\x00\u07d4\xdb\f\u01cft\u0642{\u070ads'n\xb8O\u0717b\x12\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\xdb\x12\x93\xa5\x06\xe9\f\xad*Y\xe1\xb8V\x1f^f\x96\x1ag\x88\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\xdb\x19\xa3\x98\"06\x8f\x01w!\x9c\xb1\f\xb2Y\u0372%|\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\xdb#\xa6\xfe\xf1\xaf{X\x1ew,\xf9\x18\x82\u07b2Qo\xc0\xa7\x89\n\u05ce\xbcZ\xc6 \x00\x00\u07d4\xdb$O\x97\xd9\xc4K\x15\x8a@\xed\x96\x06\xd9\xf7\xbd8\x9131\x89\x05\x87\x88\u02d4\xb1\xd8\x00\x00\u07d4\xdb(\x8f\x80\xff\xe22\u00baG\u0314\xc7c\xcfo\u0278+\r\x89\x04\x9b\x9c\xa9\xa6\x944\x00\x00\u07d4\xdb*\f\x9a\xb6M\xf5\x8d\u07f1\u06ec\xf8\xba\r\x89\xc8[1\xb4\x89\xd8\xd7&\xb7\x17z\x80\x00\x00\u07d4\xdb4t^\u0785v\xb4\x99\xdb\x01\xbe\xb7\xc1\xec\u0685\xcfJ\xbe\x89\x04V9\x18$O@\x00\x00\u07d4\xdb?%\x8a\xb2\xa3\xc2\xcf3\x9cD\x99\xf7ZK\xd1\xd3G.\x9e\x89QP\xae\x84\xa8\xcd\xf0\x00\x00\u07d4\xdbK\xc8;\x0ek\xaa\xdb\x11V\xc5\xcf\x06\xe0\xf7!\x80\x8cR\u01c9/\xb4t\t\x8fg\xc0\x00\x00\u07d4\xdbc\x12-\xe7\x03}\xa4\x97\x151\xfa\u9bc5\x86x\x86\u0192\x89\x0f\x04%\xb0d\x1f4\x00\x00\u07d4\xdbl*s\xda\xc7BJ\xb0\xd01\xb6ga\x12%f\xc0\x10C\x89\xa2\xa1]\tQ\x9b\xe0\x00\x00\u07d4\xdbnV\f\x9b\xc6 \u053e\xa3\xa9MG\xf7\x88\v\xf4\u007f-_\x89\x04\xda\x0f\xdf\xcf\x05v\x00\x00\u07d4\xdbo\xf7\x1b=\xb0\x92\x8f\x83\x9e\x05\xa72;\xfbW\u049c\x87\xaa\x891T\xc9r\x9d\x05x\x00\x00\u07d4\xdbsF\vY\xd8\xe8PE\xd5\xe7R\xe6%Y\x87^BP.\x8963\x03\"\xd5#\x8c\x00\x00\u07d4\xdbw\xb8\x8d\xcbq/\xd1~\xe9\x1a[\x94t\x8dr\f\x90\xa9\x94\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\xdb}@7\b\x1fle\xf9Gk\x06\x87\xd9\u007f\x1e\x04M\n\x1d\x89#\xc7W\a+\x8d\xd0\x00\x00\xe0\x94\u06c8.\xac\xed\xd0\xef\xf2cQ\x1b1*\u06fcY\u01b8\xb2[\x8a\x01\xedO\xdez\"6\xb0\x00\x00\u07d4\u06d3q\xb3\fL\x84NY\xe0>\x92K\xe6\x06\xa98\xd1\xd3\x10\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\u06e4ym\f\xebM:\x83k\x84\xc9o\x91\n\xfc\x10?[\xa0\x89\t\b\xf4\x93\xf77A\x00\x00\u07d4\u06ed\xc6\x1e\xd5\xf0F\n\u007f\x18\xe5\x1b/\xb2aM\x92d\xa0\xe0\x89\x02+\x1c\x8c\x12'\xa0\x00\x00\u07d4\u06f6\xacH@'\x04\x16B\xbb\xfd\x8d\x80\xf9\xd0\xc1\xcf3\xc1\xeb\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\u06fc\xbby\xbfG\x9aB\xadq\xdb\u02b7{Z\u07ea\x87,X\x89]\u0212\xaa\x111\xc8\x00\x00\u07d4\xdb\xc1\xce\x0eI\xb1\xa7\x05\xd2. 7\xae\xc8x\xee\ru\xc7\x03\x89\r\x8drkqw\xa8\x00\x00\u07d4\xdb\xc1\xd0\xee+\xabS\x11@\xde\x13w\"\xcd6\xbd\xb4\xe4q\x94\x89\n\u05ce\xbcZ\xc6 \x00\x00\u07d4\xdb\u015e\u0609s\u07ad1\b\x84\":\xf4\x97c\xc0P0\xf1\x89\x01\x15\x8eF\t\x13\xd0\x00\x00\u0794\xdb\xc6ie\xe4&\xff\x1a\xc8z\xd6\xebx\xc1\xd9Rq\x15\x8f\x9f\x88\xfc\x93c\x92\x80\x1c\x00\x00\u07d4\xdb\xcb\xcdzW\ua7724\x9b\x87\x8a\xf3K\x1a\xd6B\xa7\xf1\u0449\n\u05ce\xbcZ\xc6 \x00\x00\u07d4\xdb\xd5\x1c\xdf,;\xfa\xcd\xff\x10b!\xde.\x19\xadmB\x04\x14\x89_h\xe8\x13\x1e\u03c0\x00\x00\u07d4\xdb\xd7\x1e\xfaK\x93\u0209\xe7e\x93\xde`\x9c;\x04\u02ef\xbe\b\x89\x01\x15\x8eF\t\x13\xd0\x00\x00\u07d4\xdb\xf5\xf0a\xa0\xf4\x8e^ia\x879\xa7}.\xc1\x97h\xd2\x01\x89\b=lz\xabc`\x00\x00\u07d4\xdb\xf8\xb19g\xf5Q%'-\xe0V%6\xc4P\xbaVU\xa0\x89n\xf5x\xf0n\f\xcb\x00\x00\u07d4\xdb\xfb\x1b\xb4d\xb8\xa5\x8eP\r.\xd8\u0797,E\xf5\xf1\xc0\xfb\x89V\xbcu\xe2\xd61\x00\x00\x00\xe0\x94\xdc\x06~\xd3\xe1-q\x1e\xd4u\xf5\x15n\xf7\xe7\x1a\x80\xd94\xb9\x8a\x02\x05\xb4\u07e1\xeetx\x00\x00\u07d4\xdc\b\u007f\x93\x90\xfb\x9e\x97j\xc2:\xb6\x89TJ\tB\xec !\x89b\xa9\x92\xe5:\n\xf0\x00\x00\u07d4\xdc\x1e\xb9\xb6\xe6CQ\xf5d$P\x96E\xf8>y\xee\xe7l\xf4\x89\xd8\xd7&\xb7\x17z\x80\x00\x00\u07d4\xdc\x1f\x19ya_\b!@\xb8\xbbx\xc6{'\xa1\x94'\x13\xb1\x89\x03@\xaa\xd2\x1b;p\x00\x00\u07d4\xdc#\xb2`\xfc\xc2n}\x10\xf4\xbd\x04J\xf7\x94W\x94`\xd9\u0689\x1b\x1bk\u05efd\xc7\x00\x00\u07d4\xdc)\x11\x97E\xd23s \xdaQ\xe1\x91\x00\xc9H\u0640\xb9\x15\x89\b\xacr0H\x9e\x80\x00\x00\u07d4\xdc-\x15\xa6\x9fk\xb3;$j\xef@E\aQ\xc2\xf6uj\u0489l4\x10\x80\xbd\x1f\xb0\x00\x00\u07d4\xdc=\xaeY\xed\x0f\xe1\x8bXQ\x1eo\xe2\xfbi\xb2\x19h\x94#\x89\x05k\xc7^-c\x10\x00\x00\xe0\x94\xdc?\x0evr\xf7\x1f\xe7R[\xa3\v\x97U\x18: \xb9\x16j\x8a\x02\b\x9c\xf5{[>\x96\x80\x00\xe0\x94\xdcCE\u0581.\x87\n\xe9\fV\x8cg\xd2\xc5g\u03f4\xf0<\x8a\x01k5-\xa5\xe0\xed0\x00\x00\u07d4\xdcD'[\x17\x15\xba\xea\x1b\x03EsZ)\xacB\xc9\xf5\x1bO\x89?\x19\xbe\xb8\xdd\x1a\xb0\x00\x00\u07d4\xdcF\xc13%\u034e\xdf\x020\xd0h\x89d\x86\xf0\a\xbfN\xf1\x89Hz\x9a0E9D\x00\x00\u07d4\xdcQ\xb2\u071d$z\x1d\x0e[\xc3l\xa3\x15oz\xf2\x1f\xf9\xf6\x8965\u026d\xc5\u07a0\x00\x00\xe0\x94\xdcS\x05\xb4\x02\n\x06\xb4\x9de||\xa3L5\xc9\x1c_,V\x8a\x01}\xf6\xc1\r\xbe\xba\x97\x00\x00\u07d4\xdcW4[8\xe0\xf0g\u0263\x1d\x9d\xea\xc5'Z\x10\x94\x93!\x89\n\u05ce\xbcZ\xc6 \x00\x00\u07d4\xdcWG}\xaf\xa4/p\\\u007f\xe4\x0e\xae\x9c\x81un\x02%\xf1\x89\x1b\x1b\x81(\xa7An\x00\x00\u07d4\xdc_Z\xd6c\xa6\xf2c2}d\xca\xc9\xcb\x13=,\x96\x05\x97\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\xdcp:_7\x94\xc8Ml\xb3TI\x18\xca\xe1J5\u00fdO\x89dI\xe8NG\xa8\xa8\x00\x00\xe0\x94\xdcs\x8f\xb2\x17\u03ad/iYL\b\x17\r\xe1\xaf\x10\xc4\x19\xe3\x8a\x15-\x02\xc7\xe1J\xf6\x80\x00\x00\u07d4\xdcv\xe8[\xa5\v\x9b1\xec\x1e& \xbc\xe6\xe7\xc8\x05\x8c\x0e\xaf\x89\x01\x15\x8eF\t\x13\xd0\x00\x00\u07d4\u0703\xb6\xfd\rQ!1 G\a\xea\xf7.\xa0\xc8\u027e\xf9v\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\u070c)\x12\xf0\x84\xa6\u0444\xaasc\x85\x13\u033c2n\x01\x02\x89F3\xbc6\xcb\xc2\xdc\x00\x00\u07d4\u0711\x1c\xf7\xdc]\u04016Vg\x05(\xe93\x8eg\x03G\x86\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\u0730;\xfal\x111#NV\xb7\xea|Or\x14\x87Tkz\x89Hz\x9a0E9D\x00\x00\xe0\x94\u0736M\xf47X\xc7\u03d7O\xa6`HO\xbbq\x8f\x8cg\xc1\x8a\x04<3\xc1\x93ud\x80\x00\x00\u07d4\xdc\xc5-\x8f\x8d\x9f\xc7B\xa8\xb8'g\xf0US\x87\xc5c\xef\xff\x89\x1b\x1a\xe4\xd6\xe2\xefP\x00\x00\u07d4\xdc\xcb7\x0e\u058a\xa9\"(0C\xef|\xad\x1b\x9d@?\xc3J\x89\xd8\xd7&\xb7\x17z\x80\x00\x00\u07d4\xdc\u0324 E\xec>\x16P\x8b`?\xd96\xe7\xfd}\xe5\xf3j\x89\x01\x11du\x9f\xfb2\x00\x00\u07d4\xdc\xd1\fU\xbb\x85OuD4\xf1!\x9c,\x9a\x98\xac\xe7\x9f\x03\x89\xd8\xd8X?\xa2\xd5/\x00\x00\u07d4\xdc\u057c\xa2\x00S\x95\xb6u\xfd\xe5\x03VY\xb2k\xfe\xfcI\xee\x89\n\xad\xec\x98?\xcf\xf4\x00\x00\u07d4\xdc\u06fdN&\x04\xe4\x0e\x17\x10\xccg0(\x9d\xcc\xfa\u04c9-\x89\xf9]\xd2\xec'\xcc\xe0\x00\x00\u07d4\xdc\xe3\f1\xf3\xcafr\x1e\xcb!<\x80\x9a\xabV\x1d\x9bR\xe4\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\xdc\xf39eS\x13\x80\x161h\xfc\x11\xf6~\x89\xc6\xf1\xbc\x17\x8a\x89\x12'v\x854\x06\xb0\x80\x00\u07d4\xdc\xf6\xb6W&n\x91\xa4\xda\xe6\x03=\xda\xc1S2\u074d+4\x89_h\xe8\x13\x1e\u03c0\x00\x00\u07d4\xdc\xf9q\x9b\xe8|oFum\xb4\x89\x1d\xb9\xb6\x11\xd2F\x9cP\x8965\u026d\xc5\u07a0\x00\x00\xe0\x94\xdc\xff\xf3\xe8\xd2<*4\xb5k\u0473\xbdE\u01d3tC\"9\x8a\x01\x0f\f\xf0d\xddY \x00\x00\u07d4\xdd\x04\xee\xe7N\v\xf3\f?\x8dl,\u007fR\xe0Q\x92\x10\u07d3\x89\x04V9\x18$O@\x00\x00\xe0\x94\xdd&\xb4)\xfdC\xd8N\xc1y\x82S$\xba\u057f\xb9\x16\xb3`\x8a\x01\x16\xbf\x95\xbc\x842\x98\x00\x00\u07d4\xdd*#:\xde\xdef\xfe\x11&\xd6\xc1h#\xb6*\x02\x1f\xed\u06c9lk\x93[\x8b\xbd@\x00\x00\u07d4\xdd+\u07e9\x17\xc1\xf3\x10\xe6\xfa5\xaa\x8a\xf1i9\xc23\xcd}\x89\x15\xaf\x1dx\xb5\x8c@\x00\x00\u07d4\xdd5\xcf\xdb\u02d93\x95Sz\xec\xc9\xf5\x90\x85\xa8\xd5\u0776\xf5\x8965\u026d\xc5\u07a0\x00\x00\u07d4\xddG\x18\x9a>d9qg\xf0b\x0eHEe\xb7b\xbf\xbb\xf4\x89dI\xe8NG\xa8\xa8\x00\x00\u07d4\xddM\xd6\xd3`3\xb0co\u030d\t8`\x9fM\xd6OJ\x86\x89\x03@\xaa\xd2\x1b;p\x00\x00\u07d4\xddO_\xa2\x11\x1d\xb6\x8fk\xde5\x89\xb60)9[i\xa9-\x89\b\x96=\xd8\xc2\xc5\xe0\x00\x00\xe0\x94\xddc\x04/%\xed2\x88J\xd2n:\xd9Y\xeb\x94\xea6\xbfg\x8a\x04\x84\xd7\xfd\xe7\u0553\xf0\x00\x00\u07d4\xdde\xf6\xe1qc\xb5\xd2\x03d\x1fQ\xcc{$\xb0\x0f\x02\xc8\xfb\x89\n\u05ce\xbcZ\xc6 \x00\x00\u07d4\xddl\x06!\x93\xea\xc2=/\xdb\xf9\x97\xd5\x06:4k\xb3\xb4p\x89\x01\x15\x8eF\t\x13\xd0\x00\x00\xe0\x94\xdd{\u0366Y$\xaa\xa4\x9b\x80\x98J\xe1su\x02X\xb9(G\x8a\x02\x1e\x19\xe0\u027a\xb2@\x00\x00\u07d4\xdd\u007f\xf4A\xbao\xfe6q\xf3\xc0\u06bb\xff\x18#\xa5\x043p\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\u0742T\x12\x1an\x94/\xc9\b(\xf2C\x1fQ\x1d\xad\u007f2\u6263\x9b)\xe1\xf3`\xe8\x00\x00\xe0\x94\u074a\xf9\xe7vR#\xf4DoD\xd3\xd5\t\x81\x9a==\xb4\x11\x8a\x02\x1e\x19\xe0\u027a\xb2@\x00\x00\xe0\x94\u0755\xdb\xe3\x0f\x1f\x18w\xc5\xddv\x84\xae\xef0*\xb6\x88Q\x92\x8a\x01\xc5\xd8\xd6\xeb>2P\x00\x00\xe0\x94\u0756|L_\x8a\xe4~&o\xb4\x16\xaa\u0456N\xe3\xe7\xe8\u00ca\x01\xa4 \xdb\x02\xbd}X\x00\x00\u07d4\u075bHZ;\x1c\xd3:j\x9cb\xf1\xe5\xbe\xe9'\x01\x85m%\x89\f3\x83\xed\x03\x1b~\x80\x00\xe0\x94\u0763q\xe6\x00\xd3\x06\x88\xd4q\x0e\b\x8e\x02\xfd\xf2\xb9RM_\x8a\x01w\"J\xa8D\xc7 \x00\x00\u07d4\u0764\xed*X\xa8\xdd \xa72u4{X\rq\xb9[\xf9\x9a\x89\x15\xa1<\xc2\x01\xe4\xdc\x00\x00\xe0\x94\u0764\xff}\xe4\x91\u0187\xdfEt\xdd\x1b\x17\xff\x8f$k\xa3\u044a\x04&\x84\xa4\x1a\xbf\xd8@\x00\x00\u07d4\u076bkQ\xa9\x03\v@\xfb\x95\xcf\vt\x8a\x05\x9c$\x17\xbe\u01c9lk\x93[\x8b\xbd@\x00\x00\xe0\x94\u076bu\xfb/\xf9\xfe\u02c8\xf8\x94vh\x8e+\x00\xe3g\xeb\xf9\x8a\x04\x1b\xad\x15^e\x12 \x00\x00\xe0\x94\u076b\xf1<<\x8e\xa4\xe3\xd7=x\xecqz\xfa\xfaC\x0eTy\x8a\b\xcf#\xf9\t\xc0\xfa\x00\x00\x00\u07d4\u076c1*\x96UBj\x9c\f\x9e\xfa?\xd8%Y\xefE\x05\xbf\x89\x15\xbeat\xe1\x91.\x00\x00\u07d4\u076ck\xf4\xbb\xdd}Y}\x9chm\x06\x95Y;\xed\xcc\xc7\xfa\x89.\xe4IU\b\x98\xe4\x00\x00\xe0\x94\u077d+\x93,v;\xa5\xb1\xb7\xae;6.\xac>\x8d@\x12\x1a\x8a\x02\x1e\x19\xe0\u027a\xb2@\x00\x00\u07d4\u077d\xdd\x1b\xbd8\xff\xad\xe00]0\xf0 (\xd9.\x9f:\xa8\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\u077e\xe6\xf0\x94\xea\xe64 \xb0\x03\xfbGW\x14*\xeal\xd0\xfd\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\xdd\u059c[\x9b\xf5\xebZ9\xce\xe7\xc34\x1a\x12\r\x97?\xdb4\x89k\xc1K\x8f\x8e\x1b5\x00\x00\xe0\x94\xdd\xdd{\x9en\xab@\x9b\x92&:\xc2r\u0680\x1bfO\x8aW\x8ai\xe1\r\xe7fv\u0400\x00\x00\u07d4\xdd\xe6p\xd0\x169fuv\xa2-\xd0]2F\xd6\x1f\x06\xe0\x83\x89\x01s\x17\x90SM\xf2\x00\x00\xe0\x94\xdd\xe7zG@\xba\b\xe7\xf7?\xbe:\x16t\x91)1t.\xeb\x8a\x044\xfeMC\x82\xf1\u0500\x00\u07d4\xdd\xe8\xf0\xc3\x1bt\x15Q\x1d\xce\xd1\xcd}F2>K\xd1\"2\x89WG=\x05\u06ba\xe8\x00\x00\u07d4\xdd\xe9i\xae\xf3N\xa8z\u0099\xb7Y~)+J\x01U\u030a\x89\x102\xf2YJ\x01s\x80\x00\u07d4\xdd\xf0\xcc\xe1\xfe\x99m\x91v5\xf0\a\x12\xf4\x05 \x91\xdf\xf9\xea\x89lk\x93[\x8b\xbd@\x00\x00\xe0\x94\xdd\xf3\xadv58\x10\xbej\x89\xd71\xb7\x87\xf6\xf1q\x88a+\x8a\x04<3\xc1\x93ud\x80\x00\x00\xe0\x94\xdd\xf5\x81\n\x0e\xb2\xfb.22;\xb2\u0255\t\xab2\x0f$\xac\x8a\x03\xca\\f\u067cD0\x00\x00\xe0\x94\xdd\xf9\\\x1e\x99\xce/\x9fV\x98\x05|\x19\xd5\xc9@'\xeeJn\x8a\x01EB\xba\x12\xa37\xc0\x00\x00\u0794\xdd\xfa\xfd\xbc|\x90\xf12\x0eT\xb9\x8f7F\x17\xfb\xd0\x1d\x10\x9f\x88\xb9\x8b\xc8)\xa6\xf9\x00\x00\u07d4\xdd\xfc\xca\x13\xf94\xf0\u03fe#\x1d\xa109\xd7\x04u\xe6\xa1\u040968\"\x16`\xa5\xaa\x80\x00\u07d4\xde\x02~\xfb\xb3\x85\x03\"n\xd8q\t\x9c\xb3\v\xdb\x02\xaf\x135\x8965\u026d\xc5\u07a0\x00\x00\xe0\x94\xde\x06\xd5\xeawzN\xb1G^`]\xbc\xbfCDN\x807\xea\x8a\n\x96\x81c\xf0\xa5{@\x00\x00\u07d4\xde\a\xfb[zFN;\xa7\xfb\xe0\x9e\x9a\xcb'\x1a\xf53\x8cX\x89\x02\xb5\xe3\xaf\x16\xb1\x88\x00\x00\u07d4\xde\x11!\x82\x9c\x9a\b(@\x87\xa4?\xbd/\xc1\x14*23\xb4\x8965\u026d\xc5\u07a0\x00\x00\u07d4\xde\x17kR\x84\xbc\xee:\x83\x8b\xa2Og\xfc|\xbfg\u05ce\xf6\x89\x02\t\xce\b\xc9b\xb0\x00\x00\u07d4\xde!\"\x93\xf8\xf1\xd21\xfa\x10\xe6\tG\rQ,\xb8\xff\xc5\x12\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\xde0\xe4\x9eZ\xb3\x13!M/\x01\u072b\u0389@\xb8\x1b\x1cv\x89\n\xad\xec\x98?\xcf\xf4\x00\x00\u07d4\xde3\xd7\b\xa3\xb8\x9e\x90\x9e\xafe;0\xfd\u00e5\xd5\u0334\xb3\x89\t\x9c\x88\"\x9f\xd4\xc2\x00\x00\u07d4\xde7B\x99\xc1\xd0}ySs\x85\x19\x0fD.\xf9\xca$\x06\x1f\x89\a?u\u0460\x85\xba\x00\x00\u07d4\xdeB\xfc\xd2L\xe4#\x93\x830CgY_\x06\x8f\fa\a@\x89\x02r*p\xf1\xa9\xa0\x00\x00\u07d4\xdeP\x86\x8e\xb7\xe3\xc7\x197\xecs\xfa\x89\u074b\x9e\xe1\rE\xaa\x8965\u026d\xc5\u07a0\x00\x00\u07d4\xdeU\xde\x04X\xf8P\xb3~Mx\xa6A\xdd.\xb2\u074f8\u0389\xd8\xd7&\xb7\x17z\x80\x00\x00\u07d4\xde[\x00_\xe8\u06ae\x8d\x1f\x05\xde>\xda\x04 f\xc6\xc4i\x1c\x89;\xa1\x91\v\xf3A\xb0\x00\x00\u07d4\xdea-\a$\xe8N\xa4\xa7\xfe\xaa=!B\xbd^\xe8-2\x01\x89\x01\x15\x8eF\t\x13\xd0\x00\x00\xe0\x94\xdem61\x06\xccb8\xd2\xf0\x92\xf0\xf07!6\xd1\xcdP\u018a\x01!\xeah\xc1\x14\xe5\x10\x00\x00\u07d4\xde}\xee\"\x0f\x04W\xa7\x18}V\xc1\xc4\x1f.\xb0\n\xc5`!\x89\"%\xf3\x9c\x85\x05*\x00\x00\u07d4\u0782\u030dJ\x1b\xb1\xd9CC\x92\x96[>\x80\xba\xd3\xc0=O\x89P\x18nu\u0797\xa6\x00\x00\u07d4\u0797\xf43\a\x00\xb4\x8cImC|\x91\xca\x1d\xe9\u0130\x1b\xa4\x89\x9d\xcc\x05\x15\xb5n\f\x00\x00\u07d4\u079e\xffLy\x88\x11\xd9h\xdc\xcbF\r\x9b\x06\x9c\xf3\x02x\xe0\x89\x15\xaf\x1dx\xb5\x8c@\x00\x00\u07d4\u07b1\xbc4\xd8mJM\xde%\x80\u063e\xaf\aN\xb0\xe1\xa2D\x89U\xa6\xe7\x9c\xcd\x1d0\x00\x00\u07d4\u07b2I]j\xca{*j-\x13\x8bn\x1aB\xe2\xdc1\x1f\u0749lk\x93[\x8b\xbd@\x00\x00\u07d4\u07b9rTGL\r/Zyp\xdc\xdb/R\xfb\x10\x98\xb8\x96\x8965\u026d\xc5\u07a0\x00\x00\u07d4\u07b9\xa4\x9aC\x870 \xf0u\x91\x85\xe2\v\xbbL\U000c1ecf\x89\vx\xed\xb0\xbf.^\x00\x00\u07d4\u07bb\u0743\x1e\x0f \xaen7\x82R\xde\xcd\xf9/|\xf0\xc6X\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\xde\xc3\xee\xc2d\nu,Fn+~~\u616f\xe9\xacA\xf4\x89G\u0257SYk(\x80\x00\u07d4\xde\xc8#s\xad\xe8\xeb\xcf*\xcbo\x8b\xc2AM\u05eb\xb7\rw\x89\n\u05ce\xbcZ\xc6 \x00\x00\u07d4\xde\u0221\xa8\x98\xf1\xb8\x95\xd80\x1f\xe6J\xb3\xad]\xe9A\xf6\x89\x89*\xb4\xf6~\x8as\x0f\x80\x00\u07d4\xde\u025e\x97/\xcaqwP\x8c\x8e\x1aG\xac\"\xd7h\xac\xab|\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\xde\xd8w7\x84\a\xb9Nx\x1cN\xf4\xaf|\xfc[\xc2 \xb5\x16\x89\x141y\xd8i\x11\x02\x00\x00\u07d4\xde\xe9B\xd5\xca\xf5\xfa\xc1\x14!\xd8k\x01\vE\x8e\\9)\x90\x89\xd8\xd7&\xb7\x17z\x80\x00\x00\u07d4\xde\xee&\x89\xfa\x90\x06\xb5\x9c\xf2\x85#}\xe5;:\u007f\xd0\x148\x89\x18ey\xf2\x9e %\x00\x00\u07d4\xde\xfd\xdf\u055b\x8d,\x15N\xec\xf5\xc7\xc1g\xbf\v\xa2\x90]>\x89\x05\x12\xcb^&GB\x00\x00\u07d4\xde\xfe\x91A\xf4pE\x99\x15\x9d{\"=\xe4+\xff\xd8\x04\x96\xb3\x89\x05k\xc7^-c\x10\x00\x00\u07d4\xdf\t\x8f^N=\xff\xa5\x1a\xf27\xbd\xa8e,Os\ud726\x89\x1b6\xa6DJ>\x18\x00\x00\xe0\x94\xdf\r\ba{\xd2R\xa9\x11\u07cb\xd4\x1a9\xb8=\u07c0\x96s\x8a\x02\x1e\x19\xe0\u027a\xb2@\x00\x00\u07d4\xdf\x0f\xf1\xf3\xd2z\x8e\xc9\xfb\x8fk\f\xb2T\xa6;\xba\x82$\xa5\x89\xec\xc5 )E\xd0\x02\x00\x00\u07d4\xdf\x1f\xa2\xe2\x0e1\x98^\xbe,\x0f\f\x93\xb5L\x0f\xb6z&K\x89\n\u05ce\xbcZ\xc6 \x00\x00\u07d4\xdf!\x1c\xd2\x12\x88\xd6\xc5o\xaef\xc3\xffTb]\u0531T'\x89\x87\x86\xcdvN\x1f,\x00\x00\u07d4\xdf#k\xf6\xab\xf4\xf3)7\x95\xbf\f(q\x8f\x93\u3c73k\x89Hz\x9a0E9D\x00\x00\u07d4\xdf1\x02_VI\xd2\xc6\xee\xa4\x1e\u04fd\xd3G\x1ay\x0fu\x9a\x89\x01\x15\x8eF\t\x13\xd0\x00\x00\xe0\x94\xdf7\xc2.`:\xed\xb6\nbrS\xc4}\x8b\xa8f\xf6\xd9r\x8a\x05\x15\n\xe8J\x8c\xdf\x00\x00\x00\u07d4\xdf;r\u017dq\u0501N\x88\xa6#!\xa9=@\x11\xe3W\x8b\x89\xd8\xd7&\xb7\x17z\x80\x00\x00\u07d4\xdf?W\xb8\xeed4\xd0G\"=\xeft\xb2\x0fc\xf9\xe4\xf9U\x89\r\x94b\xc6\xcbKZ\x00\x00\u07d4\xdfD\xc4\u007f\xc3\x03\xacv\xe7O\x97\x19L\xcag\xb5\xbb<\x02?\x89 \t\xc5\u023fo\xdc\x00\x00\u07d4\xdfG\xa6\x1brSQ\x93\xc5a\xcc\xccu\xc3\xf3\xce\b\x04\xa2\x0e\x89\x15\x93\\\vN=x\x00\x00\u07d4\xdfG\xa8\xef\x95\xf2\xf4\x9f\x8eoX\x18AT\x14]\x11\xf7'\x97\x89g\x8a\x93 b\xe4\x18\x00\x00\u07d4\xdfS\x003F\xd6\\^zdk\xc04\xf2\xb7\xd3/\xcb\xe5j\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\xdfW5:\xaf\xf2\xaa\xdb\n\x04\xf9\x01N\x8d\xa7\x88N\x86X\x9c\x89\bH\x86\xa6nO\xb0\x00\x00\u07d4\xdf`\xf1\x8c\x81*\x11\xedN'v\xe7\xa8\x0e\xcf^S\x05\xb3\u05890\xca\x02O\x98{\x90\x00\x00\u07d4\xdfd\x85\xc4)z\xc1R\xb2\x89\xb1\x9d\xde2\xc7~\xc4\x17\xf4}\x8965\u026d\xc5\u07a0\x00\x00\u07d4\xdff\n\x91\u06b9\xf70\xf6\x19\rP\xc89\x05aP\aV\u0289lk\x93[\x8b\xbd@\x00\x00\u07d4\xdfn\xd6\x00jj\xbe\x88n\xd3=\x95\xa4\xde(\xfc\x12\x189'\x891T\xc9r\x9d\x05x\x00\x00\u07d4\u07c5\x10y>\xee\x81\x1c-\xab\x1c\x93\xc6\xf4G?0\xfb\xef[\x8965\u026d\xc5\u07a0\x00\x00\u07d4\u07cdH\xb1\xeb\a\xb3\xc2\x17y\x0el-\xf0M\xc3\x19\xe7\xe8H\x89\x1b\x1a\xe4\xd6\xe2\xefP\x00\x00\u07d4\u07e6\xb8\xb8\xad1\x84\xe3W\xda()Q\u05d1a\u03f0\x89\xbc\x89\x15\xaf\x1dx\xb5\x8c@\x00\x00\xe0\x94\u07ef1\xe6\"\xc0=\x9e\x18\xa0\u0778\xbe`\xfb\xe3\xe6a\xbe\n\x8a\x02\x1e\x17\x1a>\xc9\xf7,\x00\x00\u07d4\u07f1bn\xf4\x8a\x1d}uR\xa5\xe0)\x8f\x1f\xc2:;H-\x89\\\xe8\x95\u0754\x9e\xfa\x00\x00\xe0\x94\u07f4\u052d\xe5/\u0301\x8a\xccz,k\xb2\xb0\x02$e\x8fx\x8a\x01\xa4 \xdb\x02\xbd}X\x00\x00\u07d4\u07fdB2\xc1|@z\x98\r\xb8\u007f\xfb\u036060\xe5\xc4Y\x89\x1d\xfc\u007f\x92I#S\x00\x00\u07d4\xdf\xcb\xdf\tEN\x1a^J@\xd3\xee\xf7\xc5\xcf\x1c\xd3\u0794\x86\x89\xd8\xd7&\xb7\x17z\x80\x00\x00\u07d4\xdf\xdb\xce\xc1\x01K\x96\xda!X\xcaQ>\x9c\x8d;\x9a\xf1\xc3\u0409lk\x93[\x8b\xbd@\x00\x00\xe0\x94\xdf\xde\xd2WK'\xd1a:}\x98\xb7\x15\x15\x9b\r\x00\xba\xab(\x8a\x04<3\xc1\x93ud\x80\x00\x00\u07d4\xdf\xdfC9<d\x9c\xae\xbe\x1b\xb1\x80Y\xde\xcb9\xf0\x9f\xb4\xe8\x89\x15\xaf\x1dx\xb5\x8c@\x00\x00\u07d4\xdf\xe3\xc5*\x92\xc3\x03\x96\xa4\xe3:P\x17\r\xc9\x00\xfc\xf8\xc9\u03c9\x02\xb5\xe3\xaf\x16\xb1\x88\x00\x00\u07d4\xdf\xe5I\xfe\x840\xe5R\xc6\xd0|\u00f9,\xcdC\xb1/\xb5\x0f\x89\x04\x88u\xea\xf6V*\x00\x00\u07d4\xdf\xe9)\xa6\x1c\x1b8\xed\xdb\xe8,%\xc2\xd6u<\xb1\xe1-h\x89\x15\xd1\xcfAv\xae\xba\x00\x00\u07d4\xdf\xf1\xb2 \xde=\x8e\x9c\xa4\xc1\xb5\xbe4\xa7\x99\xbc\xde\xd4\xf6\x1c\x89\x14\xe4\xe3S\xea9B\x00\x00\xe0\x94\xdf\xf4\x00y1xe\x93\xb2)\xef\u555f:N!\x9eQ\xaf\x8a\x01\n\xfc\x1a\xde;N\xd4\x00\x00\u07d4\xdf\xfc\xeaT!\xec\x15\x90\fn\xcf\xc7w\x18N\x14\x0e \x9e$\x89\x01\x15G8$4N\x00\x00\u07d4\xe0\x01\xab\xa7|\x02\xe1r\bl\x19P\xff\xfb\u02a3\v\x83H\x8f\x89j\xcb=\xf2~\x1f\x88\x00\x00\u07d4\xe0\x04\x84x\x8d\xb5\x0f\u01a4\x8e7\x9d\x12>P\x8b\x0fnZ\xb1\x8965\u026d\xc5\u07a0\x00\x00\u07d4\xe0\x06\x04b\xc4\u007f\xf9g\x9b\xae\xf0qY\xca\xe0\x8c)\xf2t\xa9\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\xe0\r\x15;\x106\x91C\xf9\u007fT\xb8\xd4\xca\"\x9e\xb3\xe8\xf3$\x89\b=lz\xabc`\x00\x00\u07d4\xe0\x12\xdbE8'\xa5\x8e\x16\xc16V\b\xd3n\xd6Xr\x05\a\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\xe0\x15G\xbaB\xfc\xaf\xaf\x93\x93\x8b\xec\xf7i\x9ft)\n\xf7O\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\xe0\x16\xdc\x13\x8e%\x81[\x90\xbe?\xe9\xee\xe8\xff\xb2\xe1\x05bO\x89\x1b\x1a\xe4\xd6\xe2\xefP\x00\x00\u07d4\xe0\x18Y\xf2B\xf1\xa0\xec`/\xa8\xa3\xb0\xb5v@\xec\x89\a^\x89\x1e\x16,\x17{\xe5\xcc\x00\x00\xe0\x94\xe0 \xe8cb\xb4\x87u(6\xa6\xde\v\xc0,\xd8\u061a\x8bj\x8a\x01EB\xba\x12\xa37\xc0\x00\x00\u07d4\xe0#\xf0\x9b(\x87a,|\x9c\xf1\x98\x8e::`+3\x94\u0249lk\x93[\x8b\xbd@\x00\x00\u07d4\xe0'\"\x13\xe8\xd2\xfd>\x96\xbdb\x17\xb2KK\xa0\x1bapy\x89\x01\x15\x8eF\t\x13\xd0\x00\x00\u07d4\xe0+t\xa4v(\xbe1[\x1fv\xb3\x15\x05J\xd4J\xe9qo\x89\xd8\xd7&\xb7\x17z\x80\x00\x00\xe0\x94\xe02 \u0197\xbc\u048f&\xef\vt@J\x8b\xeb\x06\xb2\xba{\x8a\x01\xb1\xaeMn.\xf5\x00\x00\x00\u07d4\xe05/\u07c1\x9b\xa2e\xf1L\x06\xa61\\J\xc1\xfe\x13\x1b.\x8965\u026d\xc5\u07a0\x00\x00\u07d4\xe08\x8a\xed\xdd?\xe2\xadV\xf8WH\xe8\x0eq\n4\xb7\xc9.\x89\x1b\x1a\xe4\xd6\xe2\xefP\x00\x00\u07d4\xe0<\x00\xd0\x03\x88\xec\xbfO&=\n\xc7x\xbbA\xa5z@\u064966\xc9yd6t\x00\x00\u07d4\xe0I \xdcn\xcc\x1dn\xcc\bO\x88\xaa\n\xf5\u06d7\xbf\x89:\x89\t\xdd\xc1\xe3\xb9\x01\x18\x00\x00\u07d4\xe0Ir\xa8<\xa4\x11+\xc8q\xc7-J\xe1al/\a(\u06c9\x0e\x81\xc7\u007f)\xa3/\x00\x00\u07d4\xe0O\xf5\xe5\xa7\u2bd9]\x88W\xce\x02\x90\xb5:+\x0e\xda]\x8965\u026d\xc5\u07a0\x00\x00\xe0\x94\xe0P)\xac\xeb\axg[\xef\x17A\xab,\u0493\x1e\xf7\xc8K\x8a\x01\x0f\r\xba\xe6\x10\tR\x80\x00\u07d4\xe0V\xbf?\xf4\x1c&%o\xefQqf\x12\xb9\u04da\u0799\x9c\x89\x05k\xe7W\xa1.\n\x80\x00\u07d4\xe0a\xa4\xf2\xfcw\xb2\x96\u045a\xda#\x8eI\xa5\u02ce\xcb\xfap\x89\xd8\xd7&\xb7\x17z\x80\x00\x00\u07d4\xe0f>\x8c\xd6g\x92\xa6A\xf5nP\x03f\x01G\x88\x0f\x01\x8e\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\xe0f\x8f\xa8,\x14\xd6\xe8\xd9:S\x11>\xf2\x86/\xa8\x15\x81\xbc\x89//9\xfclT\x00\x00\x00\u07d4\xe0i\xc0\x173R\xb1\v\xf6\x83G\x19\xdb[\xed\x01\xad\xf9{\xbc\x89\x01\x064\xf8\xe52;\x00\x00\u07d4\xe0l)\xa8\x15\x17\xe0\u0507\xb6\u007f\xb0\xb6\xaa\xbcOW6\x83\x88\x89\x15\xbeat\xe1\x91.\x00\x00\u07d4\xe0l\xb6)G\x04\xee\xa7C|/\xc3\xd3\as\xb7\xbf8\x88\x9a\x89\x01\x16\xdc:\x89\x94\xb3\x00\x00\u07d4\xe0q7\xae\r\x11m\x0353\xc4\uad16\xf8\xa9\xfb\tV\x9c\x89K\xe4\xe7&{j\xe0\x00\x00\xe0\x94\xe0v\xdb0\xabHoy\x19N\xbb\xc4]\x8f\xab\x9a\x92B\xf6T\x8a\x01\x06`~4\x94\xba\xa0\x00\x00\u07d4\xe0~\xbb\xc7\xf4\xdaAnB\xc8\xd4\xf8B\xab\xa1b3\xc1%\x80\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\xe0\x81\xca\x1fH\x82\xdb`C\u0569\x19\a\x03\xfd\xe0\xab;\xf5m\x89\x15\xaf\x1dx\xb5\x8c@\x00\x00\u07d4\xe0\x83\xd3Hc\xe0\xe1\u007f\x92ky(\xed\xff1~\x99\x8e\x9cK\x89\x15\xaf\x1dx\xb5\x8c@\x00\x00\u07d4\xe0\x8b\x9a\xbak\xd9\u048b\xc2\x05gy\xd2\xfb\xf0\xf2\x85Z=\x9d\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\xe0\x8b\u009c+H\xb1i\xff+\xdc\x16qLXnl\xb8\\\u03c9\x01\x15\x8eF\t\x13\xd0\x00\x00\u07d4\xe0\x8c`11\x06\xe3\xf93O\xe6\xf7\xe7bM!\x110\xc0w\x89\x02+\x1c\x8c\x12'\xa0\x00\x00\u07d4\xe0\x9ch\xe6\x19\x98\xd9\xc8\x1b\x14\xe4\xee\x80+\xa7\xad\xf6\xd7L\u06c9\xd8\xd7&\xb7\x17z\x80\x00\x00\u07d4\xe0\x9f\xeauZ\xee\x1aD\xc0\xa8\x9f\x03\xb5\u07b7b\xba3\x00o\x89;\xa2\x89\xbc\x94O\xf7\x00\x00\xe0\x94\xe0\xa2T\xac\t\xb9r[\xeb\xc8\xe4`C\x1d\xd0s.\xbc\xab\xbf\x8a\x01EB\xba\x12\xa37\xc0\x00\x00\xe0\x94\xe0\xaai6UU\xb7?(#3\xd1\xe3\f\x1b\xbd\a(T\xe8\x8a\x01{x\x83\xc0i\x16`\x00\x00\u07d4\xe0\xba\u064e\ue598\xdb\xf6\xd7`\x85\xb7\x92=\xe5uN\x90m\x89\t\r\x97/22<\x00\x00\u07d4\xe0\u012b\x90r\xb4\xe6\xe3eJI\xf8\xa8\xdb\x02jK3\x86\xa9\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\xe0\u0380\xa4a\xb6H\xa5\x01\xfd\v\x82F\x90\u0206\x8b\x0eM\xe8\x89\x1b\x1a\xe4\xd6\xe2\xefP\x00\x00\u07d4\xe0\xcfi\x8a\x053'\xeb\xd1k}w\x00\t/\xe2\xe8T$F\x89\x05*4\u02f6\x1fW\x80\x00\xe0\x94\xe0\xd21\xe1D\xec\x91\a8l|\x9b\x02\xf1p,\xea\xa4\xf7\x00\x8a\x01\x0f\r\xba\xe6\x10\tR\x80\x00\u07d4\xe0\xd7kqf\xb1\xf3\xa1+@\x91\xee+)\u078c\xaa}\a\u06c9lk\x93[\x8b\xbd@\x00\x00\u07d4\xe0\xe0\xb2\xe2\x9d\xdes\xafu\x98~\xe4Dl\x82\x9a\x18\x9c\x95\xbc\x89\b\x13\xcaV\x90m4\x00\x00\xe0\x94\xe0\xe9xu=\x98/\u007f\x9d\x1d#\x8a\x18\xbdH\x89\xae\xfeE\x1b\x8a\x02\r\u058a\xaf2\x89\x10\x00\x00\u07d4\xe0\xf3r4|\x96\xb5_}C\x06\x03K\xeb\x83&o\xd9\tf\x89\x15\xaf\x1dx\xb5\x8c@\x00\x00\u07d4\xe0\xf9\x03\xc1\xe4\x8a\xc4!\xabHR\x8f=J&H\b\x0f\xe0C\x897\b\xba\xed=h\x90\x00\x00\u07d4\xe0\xff\v\xd9\x15D9\u0125\xb7#>)\x1d}\x86\x8a\xf5?3\x89\x15y!jQ\xbb\xfb\x00\x00\xe0\x94\xe1\n\xc1\x9cTo\xc2T|a\xc19\xf5\xd1\xf4Zff\u0570\x8a\x01\x02\xdao\xd0\xf7:<\x00\x00\xe0\x94\xe1\fT\x00\x88\x11?\xa6\xec\x00\xb4\xb2\u0202O\x87\x96\xe9n\u010a2\x0fE\t\xab\x1e\xc7\xc0\x00\x00\xe0\x94\xe1\x17:$})\xd8#\x8d\xf0\x92/M\xf2Z\x05\xf2\xafw\u00ca\bx\xc9]V\x0f0G\x80\x00\xe0\x94\xe1 >\xb3\xa7#\xe9\x9c\" \x11|\xa6\xaf\xebf\xfaBOa\x8a\x02\x00\uf49e2V\xfe\x00\x00\xe0\x94\xe11\xf8~\xfc^\xf0~C\xf0\xf2\xf4\xa7G\xb5Q\xd7P\xd9\xe6\x8a\x04<%\xe0\xdc\xc1\xbd\x1c\x00\x00\u07d4\xe13N\x99\x83y\xdf\xe9\x83\x17pby\x1b\x90\xf8\x0e\xe2-\x8d\x89\x1b\x1a\xe4\xd6\xe2\xefP\x00\x00\u07d4\xe15@\xec\xee\x11\xb2\x12\xe8\xb7u\u070eq\xf3t\xaa\xe9\xb3\xf8\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\xe1;=+\xbf\u073c\x87r\xa23\x15rL\x14%\x16|V\x88\x897\xf3y\x14\x1e\xd0K\x80\x00\u07d4\xe1D=\xbd\x95\xccA#\u007fa:HEi\x88\xa0Oh2\x82\x89\xd8\xd8X?\xa2\xd5/\x00\x00\u07d4\xe1F\x17\xf6\x02%\x01\xe9~{>-\x886\xaaa\xf0\xff-\xba\x89\n\u05ce\xbcZ\xc6 \x00\x00\u07d4\xe1I\xb5rl\xafm^\xb5\xbf*\xccA\xd4\xe2\xdc2\x8d\u1089i*\xe8\x89p\x81\xd0\x00\x00\xe0\x94\xe1T\xda\xea\xdbTX8\xcb\u01aa\fUu\x19\x02\xf5(h*\x8a\x01\n\xfc\x1a\xde;N\xd4\x00\x00\u07d4\xe1l\xe3Ya\xcdt\xbdY\r\x04\u012dJ\x19\x89\xe0V\x91\u0189\a\xea(2uw\b\x00\x00\u07d4\xe1r\xdf\xc8\xf8\f\xd1\xf8\u03459\xdc&\b \x14\xf5\xa8\xe3\u8262\xa1]\tQ\x9b\xe0\x00\x00\u07d4\xe1w\xe0\xc2\x01\xd35\xba9V\x92\x9cW\x15\x88\xb5\x1cR#\xae\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\xe1x\x12\xf6l^e\x94\x1e\x18lF\x92+n{/\x0e\xebF\x89b\xa9\x92\xe5:\n\xf0\x00\x00\u07d4\xe1\x80\u079e\x86\xf5{\xaf\xac\u05d0O\x98&\xb6\xb4\xb2c7\xa3\x89-\x04\x1dpZ,`\x00\x00\xe0\x94\xe1\x92H\x9b\x85\xa9\x82\xc1\x882F\xd9\x15\xb2)\xcb\x13 \u007f8\x8a\x01\x0f\f\xf0d\xddY \x00\x00\u07d4\xe1\x95<n\x97X\x14\xc5q1\x1c4\xc0\xf6\xa9\x9c\xdfH\xab\x82\x89\x02\xb5\xe3\xaf\x16\xb1\x88\x00\x00\u07d4\xe1\xae\x02\x9b\x17\xe3s\xcd\xe3\xdeZ\x91R \x1a\x14\xca\xc4\xe1\x19\x89\x05kU\xaeX\xca@\x00\x00\u07d4\u1cac\xa1T\xb8\xe0vlN\xba0\xbc\x10\xc7\xf3P6\xf3h\x89\x01\x15G8$4N\x00\x00\u07d4\u1cdb\x88\u0650\r\xbcJl\xdcH\x1e\x10`\b\n\x8a\xec<\x89lk\x93[\x8b\xbd@\x00\x00\xe0\x94\xe1\xb62\x01\xfa\xe1\xf1)\xf9\\z\x11k\xd9\xdd\xe5\x15\x9cl\u068a\x04\xd6\x05s\xa2\xf0\xc9\xef\x00\x00\u07d4\u1feaZE\xc5\x04B\x89#\u0126\x11\x92\xa5[\x14\x00\xb4]\x89\x90\xf54`\x8ar\x88\x00\x00\u07d4\xe1\xc6\a\xc0\xa8\xa0`\u068f\x02\xa8\xeb8\xa0\x13\xea\x8c\xda[\x8c\x89+\xa3\x9e\x82\xed]t\x00\x00\xe0\x94\xe1\u02c3\xec^\xb6\xf1\xee\xb8^\x99\xb2\xfcc\x81/\u0795q\x84\x8a\x04<3\xc1\x93ud\x80\x00\x00\u07d4\xe1\xd9\x1b\tT\xce\xde\"\x1do$\u01d8_\u0159e\xfb\x98\xb8\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\xe1\u07f5\u0309\x0e\u8c87~\x88]&|%a\x87\xd0\x19\xe6\x89\x05k\xc7^-c\x10\x00\x00\u07d4\xe1\xe8\xc5\v\x80\xa3R\xb2@\xcesB\xbb\xfd\xf5i\f\xc8\xcb\x14\x89\x15[\xd90\u007f\x9f\xe8\x00\x00\u07d4\xe1\xf6>\xbb\xc6,{tD\x04\x0e\xb9\x96#\x96Ovg\xb3v\x89\x01\x15\x8eF\t\x13\xd0\x00\x00\u07d4\xe2\x06\xfbs$\xe9\u07b7\x9e\x19\x904\x96\u0596\x1b\x9b\xe5f\x03\x89\x05k\xc7^-c\x10\x00\x00\u07d4\xe2\aW\x8e\x1fM\u06cf\xf6\u0546{9X-q\xb9\x81*\u0149\xd2U\xd1\x12\xe1\x03\xa0\x00\x00\u07d4\xe2\b\x81*h@\x98\xf3\xdaN\xfej\xba%bV\xad\xfe?\xe6\x89lk\x93[\x8b\xbd@\x00\x00\xe0\x94\xe2\tT\xd0\xf4\x10\x8c\x82\xd4\u0732\x14\x8d&\xbb\xd9$\xf6\xdd$\x8a\x02\x1e\x19\xe0\u027a\xb2@\x00\x00\u07d4\xe2\v\xb9\xf3\x96d\x19\xe1K\xbb\xaa\xaag\x89\xe9$\x96\u03e4y\x89\xbb\xd8%\x03\aRv\x00\x00\u07d4\xe2\r\x1b\xcbq(m\xc7\x12\x8a\x9f\xc7\xc6\xed\u007fs8\x92\xee\xf5\x896d\xf8\xe7\xc2J\xf4\x00\x00\u0794\xe2\x19\x12\x15\x98?3\xfd3\xe2,\u0522I\x00T\xdaS\xfd\u0708\xdbD\xe0I\xbb,\x00\x00\u07d4\xe2\x19\x8c\x8c\xa1\xb3\x99\xf7R\x15a\xfdS\x84\xa7\x13/\xbaHk\x897\b\xba\xed=h\x90\x00\x00\xe0\x94\xe2\x1cw\x8e\xf2\xa0\xd7\xf7Q\xea\x8c\aM\x1f\x81\"C\x86>N\x8a\x01\x1f\xc7\x0e,\x8c\x8a\xe1\x80\x00\xe0\x94\xe2)\xe7F\xa8?,\xe2S\xb0\xb0>\xb1G$\x11\xb5~W\x00\x8a\x016\x9f\xb9a(\xacH\x00\x00\u07d4\xe2+ \xc7x\x94F;\xafwL\xc2V\u057d\u06ff}\xdd\t\x8965\u026d\xc5\u07a0\x00\x00\u07d4\xe20\xfe\x1b\xff\x03\x18m\x02\x19\xf1]LH\x1b}Y\xbe(j\x89\x01\xfdt\x1e\x80\x88\x97\x00\x00\u07d4\xe27\xba\xa4\xdb\u0252n2\xa3\xd8]\x12d@-T\xdb\x01/\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\xe2A\t\xbe/Q=\x87I\x8e\x92j(d\x99uO\x9e\u051e\x890\x0e\xa8\xad\x1f'\xca\x00\x00\u07d4\xe2Fh<\u025d\xb7\u0125+\u02ec\xaa\xb0\xb3/k\xfc\x93\u05c9lk\x93[\x8b\xbd@\x00\x00\xe0\x94\xe2Z\x16{\x03\x1e\x84am\x0f\x01?1\xbd\xa9]\xcccP\xb9\x8a\x02<upr\xb8\xdd\x00\x00\x00\u07d4\xe2[\x9fv\xb8\xad\x02?\x05~\xb1\x1a\xd9BW\xa0\x86.N\x8c\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\xe2fW\xf0\xed \x1e\xa29,\x92\"\xb8\np\x03`\x8d\xdf0\x89\x02+\x1c\x8c\x12'\xa0\x00\x00\u07d4\xe2k\xf3\"wN\x18(\x87i\xd6~1\a\u07b7Dw\a\xb8\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\xe2r\x8a>\x8c*\xaa\u0243\xd0]\u0187st\xa8\xf4F\xee\xe9\x89\n\xb6@9\x12\x010\x00\x00\u07d4\xe2\x8b\x06\"Y\xe9n\xeb<\x8dA\x04\x94?\x9e\xb3%\x89<\xf5\x89Hz\x9a0E9D\x00\x00\xe0\x94\u237c\x8e\xfd^Ajv.\xc0\xe0\x18\x86K\xb9\xaa\x83({\x8a\x051\xf2\x00\xab>\x03\n\x80\x00\u07d4\xe2\x90K\x1a\xef\xa0V9\x8bb4\xcb5\x81\x12\x88\xd76\xdbg\x89\x02+\x1c\x8c\x12'\xa0\x00\x00\u07d4\u274a\xe4R\xdc\xf3\xb6\xacd^c\x04\t8UQ\xfa\xae\n\x89\x04Z\r\xa4\xad\xf5B\x00\x00\u07d4\xe2\xbb\xf8FA\xe3T\x1fl3\xe6\xedh:cZp\xbd\xe2\xec\x89\x1bA<\xfc\xbfY\xb7\x80\x00\u07d4\xe2\xcf6\n\xa22\x9e\xb7\x9d+\xf7\xca\x04\xa2z\x17\xc52\xe4\u0609\x05\x87\x88\u02d4\xb1\xd8\x00\x00\u07d4\xe2\xdf#\xf6\xea\x04\xbe\xcfJ\xb7\x01t\x8d\xc0\x961\x84U\\\u06c9lk\x93[\x8b\xbd@\x00\x00\u07d4\xe2\xe1\\`\xdd8\x1e:K\xe2Pq\xab$\x9aL\\Rd\u0689\u007fk\u011b\x81\xb57\x00\x00\u07d4\xe2\xe2nN\x1d\xcf0\xd0H\xccn\u03ddQ\xec\x12\x05\xa4\xe9&\x89\xd8\xd7&\xb7\x17z\x80\x00\x00\xe0\x94\xe2\xeei\x1f#~\xe6R\x9beW\xf2\xfc\xdd=\xcf\fY\xecc\x8a\x01'r\x9c\x14h| \x00\x00\u07d4\xe2\xef\xa5\xfc\xa7\x958\xce`h\xbf1\xd2\xc5\x16\xd4\xd5<\b\xe5\x89\a\x1c\xc4\b\xdfc@\x00\x00\xe0\x94\xe2\xef\u0429\xbc@~\xce\x03\xd6~\x8e\xc8\xe9\u0483\xf4\x8d*I\x8a\x02\x99\xb3;\xf9\u0144\xe0\x00\x00\u07d4\xe2\xf4\r5\x8f^?\xe7F>\xc7\x04\x80\xbd.\u04d8\xa7\x06;\x89\x01\x15\x8eF\t\x13\xd0\x00\x00\u07d4\xe2\xf98=X\x10\xea{C\x18+\x87\x04\xb6+'\xf5\x92]9\x89\x15\xaf\x1dx\xb5\x8c@\x00\x00\u07d4\xe2\xff\x9e\xe4\xb6\xec\xc1AA\xcct\xcaR\xa9\xe7\xa2\xee\x14\xd9\b\x89K\xe4\xe7&{j\xe0\x00\x00\xe0\x94\xe3\x02\x12\xb2\x01\x1b\xb5k\xdb\xf1\xbc5i\x0f:N\x0f\xd9\x05\xea\x8a\x01\xb2\u07dd!\x9fW\x98\x00\x00\u07d4\xe3\x03\x16\u007f=I`\xfe\x88\x1b2\x80\n+J\xef\xf1\xb0\x88\u0509lk\x93[\x8b\xbd@\x00\x00\u07d4\xe3\x04\xa3/\x05\xa87btJ\x95B\x97o\xf9\xb7#\xfa1\xea\x89Ur\xf2@\xa3F \x00\x00\u07d4\xe3\bCR\x04y7d\xf5\xfc\xbee\xebQ\x0fZtJeZ\x89\n\u05ce\xbcZ\xc6 \x00\x00\u07d4\xe3\t\x97L\xe3\x9d`\xaa\xdf.ig2Q\xbf\x0e\x04v\n\x10\x89\r\xc5_\xdb\x17d{\x00\x00\u07d4\xe3\x1bN\xef\x18L$\xab\t\x8e6\xc8\x02qK\xd4t=\xd0\u0509\n\u05ce\xbcZ\xc6 \x00\x00\u07d4\xe3!\xbbJ\x94j\xda\xfd\xad\xe4W\x1f\xb1\\\x00C\u04de\xe3_\x89Udu8+L\x9e\x00\x00\u07d4\xe3&<\xe8\xafm\xb3\xe4gXE\x02\xedq\t\x12^\xae\"\xa5\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\xe3+\x1cG%\xa1\x87TI\u93d7\x0e\xb3\xe5@b\xd1X\x00\x89\n\u05ce\xbcZ\xc6 \x00\x00\u07d4\xe3/\x95vmW\xb5\xcdK\x172\x89\u0587o\x9edU\x81\x94\x89\x05k\xc7^-c\x10\x00\x00\u07d4\xe38@\u063c\xa7\u0698\xa6\xf3\u0416\xd8=\xe7\x8bp\xb7\x1e\xf8\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\xe38\xe8Y\xfe.\x8c\x15UHH\xb7\\\xae\u0368w\xa0\xe82\x89a\xac\xff\x81\xa7\x8a\xd4\x00\x00\u07d4\xe3=\x98\x02 \xfa\xb2Y\xafj\x1fK8\xcf\x0e\xf3\xc6\xe2\xea\x1a\x89lk\x93[\x8b\xbd@\x00\x00\xe0\x94\xe3=\xf4\u0380\u0336*v\xb1+\xcd\xfc\xec\xc4b\x89\x97:\xa9\x8a\x01EB\xba\x12\xa37\xc0\x00\x00\xe0\x94\xe3?\xf9\x87T\x1d\xde\\\xde\u0a29m\xcc?3\xc3\xf2L\u008a*Z\x05\x8f\u0095\xed\x00\x00\x00\u07d4\xe3A\v\xb7U|\xf9\x1dy\xfai\xd0\xdf\xea\n\xa0u@&Q\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\xe3Ad-@\u04af\xce.\x91\a\xc6py\xacz&`\bl\x89\x15\xaf\x1dx\xb5\x8c@\x00\x00\u07d4\xe3TS\xee\xf2\xcc<z\x04M\n\xc14\xbaaY\b\xfa\x82\xee\x89\a\xff\x1c\xcbua\xdf\x00\x00\u07d4\xe3j\x8e\xa8\u007f\x1e\x99\xe8\xa2\xdc\x1b&\b\xd1ff|\x9d\xfa\x01\x89\x05k\xc7^-c\x10\x00\x00\u07d4\xe3q'\x01a\x9c\xa7b<U\xdb:\n\xd3\x0e\x86}\xb0\x16\x8b\x89\x01\x15\x8eF\t\x13\xd0\x00\x00\xe0\x94\xe3\u007f_\xdcn\xc9}/\x86j\x1c\xfd\r:M\xa48{\"\xb5\x8a\x02\x1e\x19\xe0\u027a\xb2@\x00\x00\u07d4\u31cf\x91\u0286\x05?\xce\xd5DF\x86\xa30\xe0\x9c\u00c8\xfb\x89\n\x84Jt$\xd9\xc8\x00\x00\u07d4\u32d1\xb3Q\x90\xb6\xd9\xde\xed\x02\x1c0\xaf\tK\x95?\u072a\x89\x01\u03afy[k\x86\x00\x00\u07d4\xe3\x8e\xf2\x8a^\u0644\xa7\xdb$\xa1\xaex-\xfb\x87\xf3\x97\xdf\u0189\a\xc0\x86\x0eZ\x80\xdc\x00\x00\u07d4\xe3\x92U\t\xc8\u0432\xa6s\x8c_jr\xf3S\x14I\x12H\u03896\xe9\xa8f\x9aDv\x80\x00\xe0\x94\xe3\x93=a\xb7}\xcd\xc7\x16@\u007f\x82P\xbc\x91\xe4\xff\xae\xb0\x9d\x8a\x12V\x98l\x95\x89\x1c \x00\x00\u07d4\xe3\x95\x1d\xe5\xae\xfa\xf0E\x87h\xd7t\xc2T\xf7\x15w5\xe5\x05\x89V\xc9]\xe8\xe8\xca\x1d\x00\x00\u07d4\xe3\x99\xc8\x1a\x1dp\x1bD\xf0\xb6o3\x99\xe6k'Z\xaa\xf8\xc1\x8965\u026d\xc5\u07a0\x00\x00\u07d4\xe3\x9b\x11\xa8\xab\x1f\xf5\xe2.Z\xe6Qr\x14\xf7<[\x9bU\u0709lk\x93[\x8b\xbd@\x00\x00\xe0\x94\xe3\x9eF\xe1]\"\xceV\xe0\xc3/\x18w\xb7\u0462d\u03d4\xf3\x8a\x04<3\xc1\x93ud\x80\x00\x00\u07d4\xe3\xa4b\x1bf\x00E\x88\xe3\x12\x06\xf7\x18\xcb\x00\xa3\x19\x88\x9c\xf0\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\xe3\xa4\xf8<9\xf8Z\xf9\u0231\xb3\x12\xbf\xe5\xfc4#\xaf\xa64\x89\x01\x8d\x99?4\xae\xf1\x00\x00\u07d4\u3a1a\x19'\xccN-C\xfb\u0361\xe4\x14\xd3$\xa7\xd9\xe0W\x89\v#\xe2\xa96\xde\xc6\x00\x00\u07d4\xe3\xab<\xa9\xb8p\xe3\xf5HQs\x06\xbb\xa4\xde%\x91\xaf\xaf\u0089A\x0e4\xae\u030c\xd3\x00\x00\u07d4\xe3\xb3\xd2\u027fW\v\xe6\xa2\xf7*\u0721\x86,1\t6\xa4<\x89\x05m*\xa3\xa5\xc0\x9a\x00\x00\u07d4\xe3\xc0\xc1(2z\x9a\xd8\x01H\x13\x9e&\x97sB\x8ec\x8c\xb0\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\xe3\xc8\x12sz\xc6\x06\xba\xf7R*\xd8\x17B\x8a6\x05\x0ez4\x89i*\xe8\x89p\x81\xd0\x00\x00\u07d4\xe3\xcf\xfe#\x9cd\xe7\xe2\x03\x88\xe6\"\x11s\x910\x1b)\x86\x96\x89\x1b\x1a\xe4\xd6\xe2\xefP\x00\x00\u07d4\xe3\xd3\ua899\x88xeV\x9e\x88\xbe!\x9b\xe5\a\x18\x9b\xe1\u0249\x18\xbao\xa9.\x93\x16\x00\x00\u07d4\xe3\u063fN\xfe\x84\xb1am\x1b\x89\xe4'\xdd\xc6\u0203\x06\x85\xae\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\xe3\xd9\x15\xed\xa3\xb8%\xd6\xeeJ\xf92\x8d2\xac\x18\xad\xa3T\x97\x89\x1b\x1a\xe4\xd6\xe2\xefP\x00\x00\xe0\x94\xe3\xdaO2@\x84L\x9bc#\xb4\x99i! q\"EC\x99\x8a\x02q\x90\xa9R\xdfK\xe5\x80\x00\u07d4\xe3\xeb,\n\x13*ROr\xcc\xc0\xd6\x0f\xee\x8bAh]9\xe2\x89j\xcb=\xf2~\x1f\x88\x00\x00\u07d4\xe3\xec\x18\xa7N\xd48U@\x9a&\xad\xe7\x83\r\xe8\xe4&\x85\xef\x89\x01\x11du\x9f\xfb2\x00\x00\u07d4\xe3\xec\xe1\xf62q\x1d\x13\xbf\xff\xa1\xf8\xf6\x84\bq\xeeX\xfb'\x89\xd8\xd7&\xb7\x17z\x80\x00\x00\u07d4\xe3\xf8\v@\xfb\x83\xfb\x97\xbb\rR0\xafOn\u055b\x1c|\u0209Hz\x9a0E9D\x00\x00\u07d4\xe3\xff\xb0,\xb7\xd9\xeaRCp\x16\x89\xaf\xd5\xd4\x17\xd7\xed.\u0389\x04:w\xaa\xbd\x00x\x00\x00\u07d4\xe4\x00\xd6Q\xbb?-#\xd5\xf8I\xe6\xf9-\x9cW\x95\xc4:\x8a\x89\x90\xf54`\x8ar\x88\x00\x00\u07d4\xe4\x06\xf5\xddr\u02b6m\x8an\xcb\u05bf\xb4\x94\xa7\xb6\xb0\x9a\xfe\x89\x05k\xc7^-c\x10\x00\x00\u07d4\xe4\b\xaa\x99\x83S\a\ue926\xc5\xeb\x80\x1f\xe6\x94\x11\u007fp}\x89\x1b\x1a\xe4\xd6\xe2\xefP\x00\x00\xe0\x94\xe4\b\xfc\ua879\x8f<d\x0fH\xfc\xba9\xf0V\x06mc\b\x8a\x02\x1e\x19\xe0\u027a\xb2@\x00\x00\u07d4\xe4\n|\x82\xe1WT\n\v\x00\x90\x1d\xbb\x86\xc7\x16\xe1\xa0b\u0689\x02\xb3\x1d$%\xf6t\x00\x00\u07d4\xe4\x1a\xea%\v\x87}B:c\xba+\xce/:a\xc0$\x8dV\x89\x0e\x189\x8ev\x01\x90\x00\x00\u07d4\xe40\xc0\x02O\xdb\xf7:\x82\xe2\x1f\xcc\xf8\xcb\u04118B\x1c!\x89\xd8\xd7&\xb7\x17z\x80\x00\x00\u07d4\xe42I\x12\xd6N\xa3\xae\xf7k</\xf9\u07c2\xc7\xe1:\u9449lk\x93[\x8b\xbd@\x00\x00\u07d4\xe46\x8b\xc1B\v5\xef\u0695\xfa\xfb\xc70\x90R\x19\x16\xaa4\x89\xd8\xd7&\xb7\x17z\x80\x00\x00\u07d4\xe47\xac\xbe\x0fb'\xb0\xe3o6\xe4\xbc\xf7\xcfa35\xfbh\x89\n\u05ce\xbcZ\xc6 \x00\x00\xe0\x94\xe4Krd\u0743k\ue387\x97\x03@\xed+\x9a\xed\x8e\u0425\x8a\x018\xe7\xfa\xa0\x1a\x80:\x00\x00\u07d4\xe4N\xa5\x10c@QT\xaa\xe76\xbe+\xf1\xee;\x9b\xe69\xae\x89\xd8\xd7&\xb7\x17z\x80\x00\x00\u07d4\xe4bU\x01\xf5+z\xf5+\x19\xeda.\x9dT\xfd\xd0\x06\xb4\x92\x89\vZ\x90ZV\xdd\xd0\x00\x00\u07d4\xe4qYV\xf5/\x150n\xe9Pk\xf8+\xcc\xc4\x06\xb3\x89^\x89\x0e\xe7\x9dOH\xc5\x00\x00\x00\u07d4\xe4\u007f\xba\xed\x99\xfc \x99b`N\xbd \xe2@\xf7OE\x91\xf1\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\xe4\x82\xd2U\xed\xe5k\x04\xc3\xe8\xdf\x15\x1fV\xe9\xcab\xaa\xa8\u0089\x1b\x1a\xe4\xd6\xe2\xefP\x00\x00\u07d4\xe4\x8ee\x12T!\x88\rB\xbd\xf1\x01\x8a\xb9w\x8d\x96\x92\x8f?\x89\u3bb5sr@\xa0\x00\x00\u07d4\u4481\x8a\xa6\x84\xe5\xa6vV\x1br]B\xf3\xccV\xaeQ\x98\x89+^:\xf1k\x18\x80\x00\x00\u07d4\xe4\x996\xa9*\x8c\xcfq\x0e\xaa\xc3B\xbcEK\x9b\x14\xeb\ucc49lk\x93[\x8b\xbd@\x00\x00\u07d4\xe4\x9a\xf4\xf3J\u06a23\v\x0eI\xdct\xec\x18\xab/\x92\xf8'\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\u46e0\u0356\x81lF\aw<\xf8\xa5\x97\v\xb5\xbc\x16\xa1\xe6\x89Z\x87\xe7\xd7\xf5\xf6X\x00\x00\u07d4\xe4\xa4~93$l?\xd6)y\xa1\xea\x19\xff\u07ccr\xef7\x89\b\t\xb3\x83\xea}~\x80\x00\u07d4\u4dae\"\xc7s_[\x89\xf3M\xd7z\u0417_\n\u0311\x81\x8965\u026d\xc5\u07a0\x00\x00\u07d4\xe4\xca\nR8VM\xfc\x91\xe8\xbf\"\xba\xde)\x01a\x9a\x1c\u050965\u026d\xc5\u07a0\x00\x00\u07d4\xe4\xca\xfbr\u007f\xb5\u01b7\v\xb2u3\xb8\xa9\xcc\xc9\xefh\x88\xe1\x89\x10I{\xf4\xafL\xaf\x80\x00\u07d4\xe4\xdc\"\xedY[\xf0\xa37\xc0\x1e\x03\xcck\xe7D%_\xc9\xe8\x89\nZ\xa8P\t\xe3\x9c\x00\x00\u07d4\xe4\xfb&\xd1\xca\x1e\xec\xba=\x82\x98\xd9\xd1H\x11\x9a\u00bb\xf5\x80\x89\x15\xaf\x1dx\xb5\x8c@\x00\x00\u07d4\xe4\xfc\x13\xcf\u02ec\x1b\x17\xcew\x83\xac\xd4#\xa8E\x94?k:\x89\x01\x15\x8eF\t\x13\xd0\x00\x00\u07d4\xe5\vFJ\xc9\xde5\xa5a\x8b|\xbf%Ft\x18+\x81\xb9~\x89\xdeB\xee\x15D\u0750\x00\x00\u07d4\xe5\x10,;q\x1b\x81\x03D\x19t\x19\xb1\u034apY\xf1>2\x89\x10CR\x8d\t\x84i\x80\x00\xe0\x94\xe5\x10\xd6y\u007f\xba=f\x93\x83Z\x84N\xa2\xadT\x06\x91\x97\x1b\x8a\x03\xae9\xd4s\x83\xe8t\x00\x00\u07d4\xe5\x14!\xf8\xee\"\x10\xc7\x1e\xd8p\xfea\x82v\u0215J\xfb\xe9\x89Hz\x9a0E9D\x00\x00\u07d4\xe5\x1e\xb8~\u007f\xb71\x1fR(\xc4y\xb4\x8e\u0247\x881\xacL\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\xe5!V1\xb1BH\xd4Z%R\x96\xbe\xd1\xfb\xfa\x030\xff5\x89G\x03\xe6\xebR\x91\xb8\x00\x00\xe0\x94\xe5(\xa0\xe5\xa2g\xd6g\xe99:e\x84\xe1\x9b4\u071b\xe9s\x8a\x01/\x93\x9c\x99\xed\xab\x80\x00\x00\u07d4\xe54%\xd8\xdf\x1f\x11\xc3A\xffX\xae_\x148\xab\xf1\xcaS\u03c9\x11t\xa5\xcd\xf8\x8b\xc8\x00\x00\u07d4\xe5<hyb\x12\x03>No\x9c\xffV\xe1\x9cF\x1e\xb4T\xf9\x8965\u026d\xc5\u07a0\x00\x00\u07d4\xe5A\x02SM\xe8\xf2>\xff\xb0\x93\xb3\x12B\xad;#?\xac\xfd\x89\xd8\xd7&\xb7\x17z\x80\x00\x00\u07d4\xe5E\xee\x84\xeaH\xe5d\x16\x1e\x94\x82\u055b\xcf@j`,\xa2\x89dI\xe8NG\xa8\xa8\x00\x00\u07d4\xe5H\x1a\u007f\xedB\xb9\x01\xbb\xed x\x9b\u052d\xe5\r_\x83\xb9\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\xe5Y\xb5\xfd3{\x9cUr\xa9\xbf\x9e\x0f%!\xf7\xd4F\xdb\xe4\x89\n\u05ce\xbcZ\xc6 \x00\x00\u07d4\xe5\\\x80R\n\x1b\x0fu[\x9a,\xd3\xce!Ov%e>\x8a\x89lk\x93[\x8b\xbd@\x00\x00\xe0\x94\xe5mC\x13$\xc9)\x11\xa1t\x9d\xf2\x92p\x9c\x14\xb7ze\u034a\x01\xbc\x85\xdc*\x89\xbb \x00\x00\u07d4\xe5})\x95\xb0\xeb\xdf?<\xa6\xc0\x15\xeb\x04&\r\xbb\x98\xb7\u0189lk\x93[\x8b\xbd@\x00\x00\u07d4\u51f1j\xbc\x8at\b\x1e6\x13\xe1CB\xc03u\xbf\bG\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\xe5\x89\xfav\x98M\xb5\xec@\x04\xb4n\u8954\x92\xc3\aD\u0389\x97\xc9\xceL\xf6\xd5\xc0\x00\x00\u07d4\xe5\x8d\xd228\xeen\xa7\xc2\x13\x8d8]\xf5\x00\xc3%\xf3v\xbe\x89b\xa9\x92\xe5:\n\xf0\x00\x00\u07d4\xe5\x95?\xeaIq\x04\xef\x9a\xd2\xd4\xe5\x84\x1c'\x1f\a5\x19\u0089&)\xf6n\fS\x00\x00\x00\xe0\x94\u5587\x97F\x8e\xf7g\x10\x1bv\x1dC\x1f\xce\x14\xab\xff\u06f4\x8a\x01\xb3\xd9i\xfaA\x1c\xa0\x00\x00\u07d4\xe5\x97\xf0\x83\xa4i\xc4Y\x1c=+\x1d,w'\x87\xbe\xfe'\xb2\x89\x0f-\xc7\xd4\u007f\x15`\x00\x00\u07d4\xe5\x9b;\xd3\x00\x89?\x97#>\xf9G\xc4or\x17\xe3\x92\xf7\xe9\x8965\u026d\xc5\u07a0\x00\x00\u07d4\xe5\xa3e4<\xc4\xeb\x1ew\x03h\xe1\xf1\x14Jw\xb82\xd7\xe0\x89\x01\x15\x8eF\t\x13\xd0\x00\x00\u07d4\xe5\xa3\xd7\xeb\x13\xb1\\\x10\x01w#m\x1b\xeb0\xd1~\xe1T \x89lk\x93[\x8b\xbd@\x00\x00\u07d4\xe5\xaa\v\x83;\xb9\x16\xdc\x19\xa8\xddh?\x0e\xde$\x1d\x98\x8e\xba\x89\xa2\xa1]\tQ\x9b\xe0\x00\x00\u07d4\u5def\x14i\x86\xc0\xff\x8f\x85\xd2.l\xc34\a}\x84\xe8$\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\xe5\xb8&\x19l\x0e\x1b\xc1\x11\x9b\x02\x1c\xf6\xd2Y\xa6\x10\u0256p\x89\n\u05ce\xbcZ\xc6 \x00\x00\u07d4\xe5\xb9o\u026c\x03\xd4H\xc1a:\xc9\x1d\x15\x97\x81E\xdb\xdf\u0449\n\u05ce\xbcZ\xc6 \x00\x00\u07d4\u5e40\u048e\xec\xe2\xc0o\xcal\x94s\x06\x8b7\u0526\xd6\xe9\x89%\xaf\u058c\xac+\x90\x00\x00\u07d4\u5eb4\xf0\xaf\u0629\u0463\x81\xb4Wa\xaa\x18\xf3\xd3\xcc\xe1\x05\x89Q\xbf\xd7\xc18x\xd1\x00\x00\u07d4\xe5\xbc\u020c;%on\xd5\xfeU\x0eJ\x18\x19\x8b\x943V\xad\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\xe5\xbd\xf3OL\xccH>L\xa50\xcc|\xf2\xbb\x18\xfe\xbe\x92\xb3\x89\x06\xd85\xa1\v\xbc\xd2\x00\x00\u07d4\xe5\u0713I\xcbR\xe1a\x19a\"\u03c7\xa3\x896\xe2\xc5\u007f4\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\xe5\xe38\x00\xa1\xb2\xe9k\xde\x101c\n\x95\x9a\xa0\a\xf2nQ\x89Hz\x9a0E9D\x00\x00\u07d4\xe5\xe3~\x19@\x8f,\xfb\xec\x834\x9d\u0501S\xa4\xa7\x95\xa0\x8f\x89\u3bb5sr@\xa0\x00\x00\u07d4\xe5\xed\xc7>bo]4A\xa4U9\xb5\xf7\xa3\x98\u0153\xed\xf6\x89.\xe4IU\b\x98\xe4\x00\x00\u07d4\xe5\xed\xf8\x12?$\x03\xce\x1a\x02\x99\xbe\xcfz\xactM\a_#\x89\n\xdaUGK\x814\x00\x00\u07d4\xe5\xf8\xefm\x97\x066\xb0\u072aO \x0f\xfd\xc9\xe7Z\xf1t\x1c\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\xe5\xfb1\xa5\xca\xeej\x96\xde9;\xdb\xf8\x9f\xbee\xfe\x12[\xb3\x8965\u026d\xc5\u07a0\x00\x00\u07d4\xe5\xfb\xe3I\x84\xb67\x19o3\x1cg\x9d\f\fG\xd84\x10\xe1\x89llD\xfeG\xec\x05\x00\x00\u07d4\xe6\tU\xdc\v\xc1V\xf6\xc4\x18I\xf6\xbdwk\xa4K\x0e\xf0\xa1\x89\x10C\x16'\xa0\x93;\x00\x00\u07d4\xe6\nU\xf2\u07d9m\u00ee\xdbil\b\xdd\xe09\xb2d\x1d\xe8\x89lk\x93[\x8b\xbd@\x00\x00\xe0\x94\xe6\x11[\x13\xf9y_~\x95e\x02\xd5\aEg\u06b9E\xcek\x8a\x15-\x02\xc7\xe1J\xf6\x80\x00\x00\u07d4\xe6\x1f(\t\x15\xc7t\xa3\x1d\"<\xf8\f\x06\x92f\xe5\xad\xf1\x9b\x89/\xb4t\t\x8fg\xc0\x00\x00\u07d4\xe6/\x98e\a\x12\xeb\x15\x87S\xd8)r\xb8\u9723\xf6\x18w\x89lk\x93[\x8b\xbd@\x00\x00\xe0\x94\xe6/\x9d|d\xe8\xe2cZ\xeb\x88=\xd7;\xa6\x84\xee|\x10y\x8a\x01\xb1\xaeMn.\xf5\x00\x00\x00\u07d4\xe6>xt\x14\xb9\x04\x84x\xa5\a35\x9e\xcd\xd7\xe3dz\xa6\x89U\xa6\xe7\x9c\xcd\x1d0\x00\x00\u07d4\xe6FfXr\xe4\v\rz\xa2\xff\x82r\x9c\xaa\xba[\xc3\u8789\x15\xaf\x1dx\xb5\x8c@\x00\x00\u07d4\xe6N\xf0\x12e\x8dT\xf8\xe8`\x9cN\x90#\xc0\x9f\xe8e\xc8;\x89\x01\x84\x93\xfb\xa6N\xf0\x00\x00\u07d4\xe6On\x1dd\x01\xb5l\akd\xa1\xb0\x86}\v/1\rN\x89\x02\u02edq\xc5:\xe5\x00\x00\u07d4\xe6g\xf6R\xf9W\u008c\x0ef\u04364\x17\xc8\f\x8c\x9d\xb8x\x89 \x9d\x92/RY\xc5\x00\x00\xe0\x94\xe6w\xc3\x1f\xd9\xcbr\x00u\u0724\x9f\x1a\xbc\xcdY\xec3\xf74\x8a\x01\xa6\u05be\xb1\xd4.\xe0\x00\x00\u07d4\xe6|,\x16e\u02038h\x81\x87b\x9fI\xe9\x9b`\xb2\u04fa\x89\n\u05ce\xbcZ\xc6 \x00\x00\xe0\x94\xe6\x9al\xdb:\x8a}\xb8\xe1\xf3\f\x8b\x84\xcds\xba\xe0+\xc0\xf8\x8a\x03\x94\xfd\xc2\xe4R\xf6q\x80\x00\u07d4\xe6\x9d\x1c7\x8bw\x1e\x0f\xef\xf0Q\xdbi\xd9f\xacgy\xf4\xed\x89\x1d\xfaj\xaa\x14\x97\x04\x00\x00\u07d4\xe6\x9f\xcc&\xed\"_{.7\x984\xc5$\xd7\f\x175\u5f09lk\x93[\x8b\xbd@\x00\x00\u07d4\xe6\xa3\x01\x0f\x02\x01\xbc\x94\xffg\xa2\xf6\x99\xdf\xc2\x06\xf9\xe7gB\x89/\xa7\xcb\xf6dd\x98\x00\x00\u07d4\xe6\xa6\xf6\xddop\xa4V\xf4\xec\x15\xefz\xd5\xe5\u06f6\x8b\xd7\u0709\n\u05ce\xbcZ\xc6 \x00\x00\u07d4\xe6\xb2\x0f\x98\n\xd8S\xad\x04\xcb\xfc\x88|\xe6`\x1ck\xe0\xb2L\x89\xd8\xd7&\xb7\x17z\x80\x00\x00\u07d4\u6cec?]M\xa5\xa8\x85}\v?0\xfcK+i+w\u05c9O%\x91\xf8\x96\xa6P\x00\x00\u07d4\xe6\xb9T_~\u0406\xe5R\x92F9\xf9\xa9\xed\xbb\xd5T\v>\x89\xcb\xd4{n\xaa\x8c\xc0\x00\x00\xe0\x94\xe6\xbc\xd3\n\x8f\xa18\xc5\xd9\xe5\xf6\xc7\xd2\u0680i\x92\x81-\u034a7\x0e\xa0\xd4|\xf6\x1a\x80\x00\x00\u07d4\xe6\xc8\x1f\xfc\xec\xb4~\xcd\xc5\\\vq\xe4\x85_>^\x97\xfc\x1e\x89\x12\x1e\xa6\x8c\x11NQ\x00\x00\u07d4\xe6\xcb&\vqmL\n\xb7&\xee\xeb\a\xc8pr\x04\xe2v\xae\x8965\u026d\xc5\u07a0\x00\x00\u07d4\xe6\xcb?1$\xc9\xc9\xcc84\xb1'K\xc33dV\xa3\x8b\xac\x89\x17+\x1d\xe0\xa2\x13\xff\x00\x00\xe0\x94\xe6\xd2\"\t\xff\u0438u\t\xad\xe3\xa8\xe2\xefB\x98y\u02c9\xb5\x8a\x03\xa7\xaa\x9e\x18\x99\xca0\x00\x00\u07d4\xe6\u051f\x86\xc2(\xf4sg\xa3^\x88l\xaa\xcb'\x1eS\x94)\x89\x16^\xc0\x9d\xa7\xa1\x98\x00\x00\u07d4\xe6\xe6!\xea\xab\x01\xf2\x0e\xf0\x83k|\xadGFL\xb5\xfd<\x96\x89\x11!\x93B\xaf\xa2K\x00\x00\u07d4\xe6\xe8\x861{jf\xa5\xb4\xf8\x1b\xf1d\xc58\xc2d5\x17e\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\xe6\u98ddu\x0f\xe9\x949N\xb6\x82\x86\xe5\xeab\xa6\x99x\x82\x89 \x86\xac5\x10R`\x00\x00\xe0\x94\xe6\xec\\\xf0\u011b\x9c1~\x1epc\x15\uf7b7\xc0\xbf\x11\xa7\x8a\x03\xa4i\xf3F~\x8e\xc0\x00\x00\u07d4\xe6\xf5\xebd\x9a\xfb\x99Y\x9cAK'\xa9\xc9\xc8U5\u007f\xa8x\x89\x90\xf54`\x8ar\x88\x00\x00\xe0\x94\xe6\xfe\n\xfb\x9d\xce\xdd7\xb2\xe2,E\x1b\xa6\xfe\xabg4\x803\x8a\x02\x1e\x19\xe0\u027a\xb2@\x00\x00\u07d4\xe7\x10\xdc\u041b\x81\x01\xf9C{\xd9}\xb9\ns\xef\x99=\v\xf4\x89\x14\xee6\xc0Z\xc2R\x00\x00\u07d4\xe7'\xe6~\xf9\x11\xb8\x1fl\xf9\xc7?\xcb\xfe\xbc+\x02\xb5\xbf\u0189lk\x93[\x8b\xbd@\x00\x00\u07d4\xe7.\x1d3\\\u009a\x96\xb9\xb1\xc0/\x00:\x16\xd9q\xe9\v\x9d\x89U\xa6\xe7\x9c\xcd\x1d0\x00\x00\u07d4\xe71\x1c\x953\xf0\t,rH\xc9s\x9b[,\x86J4\xb1\u0389\x97\xf9}l\xc2m\xfe\x00\x00\u07d4\xe7;\xfe\xad\xa6\xf0\xfd\x01o\xbc\x84>\xbc\xf6\xe3p\xa6[\xe7\f\x89j\xcb=\xf2~\x1f\x88\x00\x00\u07d4\xe7<\xcfCg%\xc1Q\xe2U\xcc\xf5!\f\xfc\xe5\xa4?\x13\xe3\x89\x01\x15NS!}\xdb\x00\x00\u07d4\xe7B\xb1\xe6\x06\x9a\x8f\xfc<Gg#]\xef\xb0\u051c\xbe\xd2\"\x89+^:\xf1k\x18\x80\x00\x00\u07d4\xe7F\b\xf5\x06\x86j\xdak\xfb\xfd\xf2\x0f\xeaD\v\xe7i\x89\xef\x89lj\xccg\u05f1\xd4\x00\x00\u07d4\xe7S>'\f\xc6\x1f\xa1d\xac\x15SE\\\x10]\x04\x88~\x14\x89\x06\x96\xd8Y\x00 \xbb\x00\x00\u07d4\xe7\\\x1f\xb1w\b\x9f>X\xb1\x06y5\xa6Yn\xf1s\u007f\xb5\x89\x05j\x87\x9f\xa7uG\x00\x00\u07d4\xe7\\;8\xa5\x8a?3\xd5V\x90\xa5\xa5\x97f\xbe\x18^\x02\x84\x89\x1b\x1a\xe4\xd6\xe2\xefP\x00\x00\u07d4\xe7a\xd2\u007f\xa3P,\xc7k\xb1\xa6\bt\x0e\x14\x03\u03dd\xfci\x89\x0f-\xc7\xd4\u007f\x15`\x00\x00\u07d4\xe7f\xf3O\xf1o<\xfc\xc9s!r\x1fC\xdd\xf5\xa3\x8b\f\xf4\x89T\x06\x923\xbf\u007fx\x00\x00\u07d4\xe7m\x94Z\xa8\x9d\xf1\xe4W\xaa4+1\x02\x8a^\x910\xb2\u03897\b\xba\xed=h\x90\x00\x00\u07d4\xe7s^\xc7e\x18\xfcj\xa9-\xa8qZ\x9e\xe3\xf6%x\x8f\x13\x89lM\x16\v\xaf\xa1\xb7\x80\x00\xe0\x94\xe7z\x89\xbdE\xdc\x04\xee\xb4\xe4\x1d{Ykp~nQ\xe7L\x8a\x02\x8a\x85t%Fo\x80\x00\x00\u07d4\xe7}}\uac96\u0234\xfa\a\xca;\xe1\x84\x16=Zm`l\x89\x05\x049\x04\xb6q\x19\x00\x00\u07d4\xe7\u007f\xeb\xab\xdf\b\x0f\x0f]\xca\x1d?Wf\xf2\xa7\x9c\x0f\xfa|\x89K\"\x9d(\xa8Ch\x00\x00\xe0\x94\u7025c\x06\xba\x1ek\xb31\x95,\"S\x9b\x85\x8a\xf9\xf7}\x8a\n\x96\x81c\xf0\xa5{@\x00\x00\u07d4\xe7\x81\xecs-@\x12\x02\xbb\x9b\xd18`\x91\r\xd6\u009a\xc0\xb6\x89C8t\xf62\xcc`\x00\x00\u07d4\xe7\x84\xdc\xc8s\xaa\x8c\x15\x13\xec&\xff6\xbc\x92\xea\xc6\xd4\xc9h\x89\n\u05ce\xbcZ\xc6 \x00\x00\u07d4\xe7\x91-L\xf4V,W=\xdc[q\xe3s\x10\xe3x\xef\x86\u0249\x15[\xd90\u007f\x9f\xe8\x00\x00\u07d4\xe7\x91\u0545\xb8\x996\xb2])\x8f\x9d5\xf9\xf9\xed\xc2Z)2\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\xe7\x924\x9c\xe9\xf6\xf1O\x81\xd0g@\x96\xbe\xfa\x1f\x92!\xcd\xea\x89[]#J\r\xb48\x80\x00\u07d4\xe7\x96\xfdN\x83\x9bL\x95\xd7Q\x0f\xb7\xc5\xc7+\x83\xc6\xc3\xe3\u01c9\x1b\xc43\xf2?\x83\x14\x00\x00\xe0\x94\xe7\xa4/Y\xfe\xe0t\xe4\xfb\x13\xea\x9eW\xec\xf1\xccH(\"I\x8a\x04<3\xc1\x93ud\x80\x00\x00\u07d4\xe7\xa4V\f\x84\xb2\x0e\x0f\xb5LIg\f)\x03\xb0\xa9lB\xa4\x89 j\xea\u01e9\x03\x98\x00\x00\u07d4\xe7\xa8\xe4q\xea\xfby\x8fET\xccnRg0\xfdV\xe6,}\x8965\u026d\xc5\u07a0\x00\x00\u07d4\u7f82\xc6Y<\x1e\xed\xdd*\xe0\xb1P\x01\xff \x1a\xb5{/\x89\x01\t\x10\xd4\xcd\xc9\xf6\x00\x00\u07d4\xe7\u01b5\xfc\x05\xfct\x8e[C\x81rdI\xa1\xc0\xad\x0f\xb0\xf1\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\xe7\xd1u$\xd0\v\xad\x82I|\x0f'\x15jd\u007f\xf5\x1d'\x92\x89\x01\x15\x8eF\t\x13\xd0\x00\x00\u07d4\xe7\xd2\x13\x94\u007f\u02d0J\xd78H\v\x1e\xed/\\2\x9f'\xe8\x89\x01\x03\u00f1\xd3\xe9\xc3\x00\x00\u07d4\xe7\xd6$\x06 \xf4,^\u06f2\xed\xe6\xae\xc4=\xa4\xed\x9bWW\x8965\u026d\xc5\u07a0\x00\x00\u07d4\xe7\xda`\x9d@\xcd\xe8\x0f\x00\xce[O\xfbj\xa9\u04304\x94\xfc\x8965\u026d\xc5\u07a0\x00\x00\u07d4\xe7\xf0oi\x9b\xe3\x1cD\vC\xb4\xdb\x05\x01\xec\x0e%&\x16D\x89\x1b\x1a\xe4\xd6\xe2\xefP\x00\x00\u07d4\xe7\xf4\xd7\xfeoV\x1f\u007f\xa1\xda0\x05\xfd6TQ\xad\x89\u07c9\x89\n\u05ce\xbcZ\xc6 \x00\x00\u07d4\xe7\xfd\x8f\xd9Y\xae\xd2v~\xa7\xfa\x96\f\xe1\xdbS\xaf\x80%s\x8965\u026d\xc5\u07a0\x00\x00\u07d4\xe8\x0e\u007f\xef\x18\xa5\xdb\x15\xb0\x14s\xf3\xadkx\xb2\xa2\xf8\xac\u0649\x1b\x1a\xe4\xd6\xe2\xefP\x00\x00\u07d4\xe8\x13\u007f\xc1\xb2\xec|\xc7\x10:\xf9!\x89\x9bJ9\xe1\xd9Y\xa1\x89P\xc5\xe7a\xa4D\b\x00\x00\u07d4\xe8\x1c-4l\n\xdfL\xc5g\b\xf69K\xa6\xc8\u0226J\x1e\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\xe8,X\xc5yC\x1bg5F\xb5:\x86E\x9a\xca\xf1\u079b\x93\x8965\u026d\xc5\u07a0\x00\x00\u07d4\xe84\xc6C\x18 \\\xa7\xddJ!\xab\xcb\b&l\xb2\x1f\xf0,\x8965\xc6 G9\u0640\x00\u07d4\xe86\x04\xe4\xffk\xe7\xf9o`\x18\xd3\xec0r\xecR]\xffk\x89\t\xdd\xc1\xe3\xb9\x01\x18\x00\x00\xe0\x94\xe8E\xe3\x87\xc4\xcb\u07d8\"\x80\xf6\xaa\x01\xc4\x0eK\xe9X\u0772\x8a\x05K@\xb1\xf8R\xbd\xa0\x00\x00\u07d4\xe8H\xca~\xbf\xf5\xc2O\x9b\x9c1g\x97\xa4;\xf7\xc3V)-\x89\x06.\x11\\\x00\x8a\x88\x00\x00\u07d4\xe8KU\xb5%\xf1\x03\x9etK\x91\x8c\xb33$\x92\xe4^\xcaz\x89\n\u05ce\xbcZ\xc6 \x00\x00\u07d4\xe8O\x80v\xa0\xf2\x96\x9e\xcd3>\xef\x8d\xe4\x10B\x98b\x91\xf2\x89\x17k4O*x\xc0\x00\x00\u07d4\xe8d\xfe\xc0~\xd1!Je1\x1e\x11\xe3)\xde\x04\r\x04\xf0\xfd\x89Y\u0283\xf5\xc4\x04\x96\x80\x00\u07d4\xe8}\xba\xc66\xa3w!\xdfT\xb0\x8a2\xefIY\xb5\xe4\xff\x82\x89lk\x93[\x8b\xbd@\x00\x00\xe0\x94\xe8~\x9b\xbf\xbb\xb7\x1c\x1at\ft\xc7#Bm\xf5]\x06=\u064a\x01\xb1\x92\x8c\x00\u01e68\x00\x00\u07d4\xe8~\xacm`+A\t\xc9g\x1b\xf5{\x95\f,\xfd\xb9\x9dU\x89\x02\xb4\xf2\x19r\xec\xce\x00\x00\xe0\x94\u807b\xbeir-\x81\xef\xec\xaaH\u0455*\x10\xa2\xbf\xac\x8f\x8a\x03c\\\x9a\xdc]\xea\x00\x00\x00\u07d4\xe8\x92Is\x8b~\xce\xd7\xcbfjf<I\xcb\xf6\u0783C\xea\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\xe8\x9c\"\xf1\xa4\xe1\xd4tn\u03eaY\xed8o\xee\x12\xd5\x1e7\x89\x02o\x8e\x87\xf0\xa7\xda\x00\x00\u07d4\u8769n\x06\xbe\xafk\u0600\xb3x\xf0h\fC\xfd.\x9d0\x89 \x9a\x1a\x01\xa5o\xec\x00\x00\u07d4\xe8\xa9\x1d\xa6\xcf\x1b\x9de\xc7J\x02\xec\x1f\x96\xee\xcbm\xd2A\xf3\x89i*\xe8\x89p\x81\xd0\x00\x00\u07d4\u8a64\x17@\xf4OT\xc3h\x8bS\xe1\xdd\xd4.C\xc9\xfe\x94\x89\xd8\xd7&\xb7\x17z\x80\x00\x00\xe0\x94\u8c8a\u0369qrWi\u06cfV=(fmA\u076bl\x8a\x02\x1e\x19\xe0\u027a\xb2@\x00\x00\u07d4\xe8\xbe$\xf2\x89D>\xe4s\xbcv\x82/U\t\x8d\x89\xb9\x1c\u0149lk\x93[\x8b\xbd@\x00\x00\u07d4\xe8\xc3\u04f0\xe1\u007f\x97\xd1\xe7V\xe6\x84\xf9N\x14p\xf9\x9c\x95\xa1\x89\x15\xaf\x1dx\xb5\x8c@\x00\x00\xe0\x94\xe8\xc3\xf0E\xbb}8\xc9\xd2\U000d5c3a\x84\x92\xb2S#\t\x01\x8a\x01\xe7\xe4\x17\x1b\xf4\u04e0\x00\x00\u07d4\xe8\xccC\xbcO\x8a\xcf9\xbf\xf0N\xbf\xbfB\xaa\xc0j2\x84p\x89\x15\xaf\x1dx\xb5\x8c@\x00\x00\u07d4\xe8\xd9B\xd8/\x17^\xcb\x1c\x16\xa4\x05\xb1\x01C\xb3\xf4k\x96:\x89\x1e\xd2\xe8\xffm\x97\x1c\x00\x00\u07d4\xe8\u077e\xd72\xeb\xfeu@\x96\xfd\xe9\bk\x8e\xa4\xa4\xcd\xc6\x16\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\xe8\xder^\xca]\xef\x80_\xf7\x94\x1d1\xac\x1c.4-\xfe\x95\x89\x85~\ro\x1d\xa7j\x00\x00\u07d4\xe8\xe9\x85\x05\x86\xe9OR\x99\xabIK\xb8!\xa5\xf4\f\x00\xbd\x04\x89\xcf\x15&@\xc5\xc80\x00\x00\xe0\x94\xe8\xea\u047b\x90\xcc\u00ee\xa2\xb0\xdc\u0175\x80VUFU\xd1\u054a\x01\xa4\xab\xa2%\xc2\a@\x00\x00\u07d4\xe8\xea\xf1)D\t-\xc3Y\x9b9S\xfa|\xb1\xc9v\x1c\xc2F\x89a\x94\x04\x9f0\xf7 \x00\x00\xe0\x94\xe8\xedQ\xbb\xb3\xac\xe6\x9e\x06\x02K3\xf8hD\xc4sH\u06de\x8a\"\xf9\xea\x89\xf4\xa7\xd6\xc4\x00\x00\u07d4\xe8\xef\x10\r|\xe0\x89X2\xf2g\x8d\xf7-J\u03cc(\xb8\xe3\x89\x1b\x1bk\u05efd\xc7\x00\x00\u07d4\xe8\xf2\x99i\xe7\\e\xe0\x1c\xe3\xd8aT }\n\x9e|v\xf2\x89\xa2/\xa9\xa7:'\x19\x80\x00\u07d4\xe8\xfc6\xb0\x13\x1e\xc1 \xac\x9e\x85\xaf\xc1\f\xe7\vV\u0636\xba\x89\n\u05ce\xbcZ\xc6 \x00\x00\u07d4\xe9\n5L\xec\x04\u059e]\x96\xdd\xc0\xc5\x13\x8d=3\x15\n\xa0\x89\x1b\x1a}\u03caD\u04c0\x00\xe0\x94\xe9\x13>}1\x84]_+f\xa2a\x87\x92\xe8i1\x1a\xcff\x8a\x05\x17\xc0\xcb\xf9\xa3\x90\x88\x00\x00\u07d4\xe9\x1d\xac\x01\x95\xb1\x9e7\xb5\x9bS\xf7\xc0\x17\xc0\xb29[\xa4L\x89e\xea=\xb7UF`\x00\x00\u07d4\xe9\x1f\xa0\xba\xda\u0779\xa9~\x88\xd3\xf4\xdb|U\u05bbt0\xfe\x89\x14b\fW\xdd\xda\xe0\x00\x00\u07d4\xe9#\xc0aw\xb3B~\xa4H\xc0\xa6\xff\x01\x9bT\xccT\x8d\x95\x89\x01\xf7\x80\x01Fg\xf2\x80\x00\xe0\x94\xe9=G\xa8\u0288]T\fNRo%\xd5\xc6\xf2\xc1\b\u0138\x8a\x17\xda:\x04\u01f3\xe0\x00\x00\x00\u07d4\xe9E\x8fh\xbb',\xb5g:\x04\xf7\x81\xb4\x03Uo\u04e3\x87\x89\x03N\x8b\x88\xce\xe2\xd4\x00\x00\u07d4\xe9IA\xb6\x03`\x19\xb4\x01j0\xc1\x03}Zi\x03\xba\xba\xad\x89*H\xac\xabb\x04\xb0\x00\x00\u07d4\xe9I[\xa5\x84'(\xc0\ud5fe7\xd0\xe4\"\xb9\x8di ,\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\xe9M\xed\x99\u0735r\xb9\xbb\x1d\u02e3/m\xee\x91\xe0W\x98N\x89\x15[\xd90\u007f\x9f\xe8\x00\x00\xe0\x94\xe9QyR}\uc951l\xa9\xa3\x8f!\\\x1e\x9c\xe77\xb4\u024a\x02\x1e\x19\xe0\u027a\xb2@\x00\x00\xe0\x94\xe9U\x91\x85\xf1f\xfc\x95\x13\xccq\x11aD\xce-\xeb\x0f\x1dK\x8a\x04<3\xc1\x93ud\x80\x00\x00\u0794\xe9^\x92\xbb\xc6\xde\a\xbf:f\x0e\xbf_\xeb\x1c\x8a5'\xe1\u0148\xfc\x93c\x92\x80\x1c\x00\x00\xe0\x94\xe9e\u06a3@9\xf7\xf0\xdfb7Z7\u5acar\xb3\x01\xe7\x8a\x01\x03\xfd\xde\u0373\xf5p\x00\x00\u07d4\xe9i\xea\x15\x95\xed\xc5\u0127\a\xcf\xde8\t)c2Q\xa2\xb0\x89\n\u05ce\xbcZ\xc6 \x00\x00\u07d4\xe9k\x18N\x1f\x0fT\x92J\xc8t\xf6\v\xbfDptF\xb7+\x89\x9d\xcc\x05\x15\xb5n\f\x00\x00\xe0\x94\xe9m}L\xdd\x15U:NM1mmd\x80\xca<\xea\x1e8\x8a\x02\x95]\x02\xe1\xa15\xa0\x00\x00\u07d4\xe9n-8\x13\xef\xd1\x16_\x12\xf6\x02\xf9\u007fJb\x90\x9d<f\x89|\xae\xe9v\x13\xe6p\x00\x00\u07d4\xe9\u007f\xde\vgqc%\xcf\x0e\xcc\u8851\xa3v\x1b,y\x1d\x896w\x03n\xdf\n\xf6\x00\x00\u07d4\xe9\x82\xe6\xf2\x8cT\x8f_\x96\xf4^c\xf7\xabp\x87$\xf5?\xa1\x89\x15z\xe8)\xa4\x1f;\x00\x00\u07d4\xe9\x86L\x1a\xfc\x8e\xaa\xd3\u007f;\xa5o\xcbtw\xccb \t\xb7\x89\x04HXap\xa7\xdc\x00\x00\u07d4\xe9\x87\xe6\x13\x9eaF\xa7\x17\xfe\xf9k\xc2I4\xa5D\u007f\xe0]\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\xe9\x89s<\xa1\u054d\x9e{P)\xba]DHX\xbe\xc01r\x89\x1f\x87@\x83\x13\xdfO\x80\x00\u07d4\u9311\xca\u0752L\x92W\x9e\x11\xb4\x12\x17\xb2\x82\x95l\u06a1\x89\a\\\x9a\x84\x802\f\x00\x00\u07d4\xe9\x9a\xec\xe9\x05A\xca\xe2$\xb8}\xa6s\x96^\n\xeb)j\xfd\x891\u07d0\x95\xa1\x8f`\x00\x00\u07d4\xe9\x9d\xe2X\xa4\x17<\xe9\xac8\xed\xe2l\v;\xea<\ts\u0549Y\u0438\x05\xe5\xbb0\x00\x00\u07d4\u98b4\x91N\x85S\xbf\r|\x00\xcaS#i\xb8y\xf91\xbf\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\u98da\x8b\xac\x0f\x01\xc3I\xc6L\xed\xb6\x98\x97\xf63#N\u0489\xd7\xc1\x98q\x0ef\xb0\x00\x00\u07d4\u996e<\x9e\x05\x97}\xd1\x06\x9e\x9f\xd9\u04ee\xfb\xae\x04\xb8\u07c9j\xcb=\xf2~\x1f\x88\x00\x00\u07d4\xe9\xac67n\xfa\x06\x10\x9d@rc\a\xdd\x1aW\xe2\x13\uaa49\n\x84Jt$\xd9\xc8\x00\x00\u07d4\xe9\xb1\xf1\xfc\xa3\xfaG&\x9f!\xb0a\xc3S\xb7\xf5\xe9m\x90Z\x89\x1b\x1a\xe4\xd6\xe2\xefP\x00\x00\xe0\x94\xe9\xb3o\xe9\xb5\x14\x12\xdd\xca\x1aR\x1dn\x94\xbc\x90\x12\x13\u0768\x8a\x02\x1e\x19\xe0\u027a\xb2@\x00\x00\u07d4\u9d24\x855w\xa9\xdb\xcc.y[\xe01\r\x1b\xed(d\x1a\x8965\u026d\xc5\u07a0\x00\x00\u07d4\u9da7\x90\x00\x9b\xc1fB\xc8\xd8 \xb7\xcd\xe0\xe9\xfd\x16\xd8\xf5\x89\xc5S%\xcat\x15\xe0\x00\x00\u07d4\u9e62tu\x10\xe3\x10$\x1d.\u0398\xf5k3\x01\xd7W\xe0\x89lk\x93[\x8b\xbd@\x00\x00\xe0\x94\xe9\xc3\\\x91<\xa1\xfc\xea\xb4aX/\u1941Qd\xb4\xfd!\x8a\x01\xb1\xaeMn.\xf5\x00\x00\x00\u07d4\xe9\xc6\u07ee\x97\xf7\t\x9f\xc5\xf4\xe9KxM\xb8\x02\x92:\x14\x19\x89\x02\xa5<mrO\x10\x00\x00\u07d4\xe9\xc7X\xf8\xdaA\xe34nCP\xe5\xac9v4\\l\x10\x82\x89h\xa0\xd3\t(&\xad\x00\x00\u07d4\xe9\xca\xf8'\xbe\x9d`y\x15\xb3e\xc8?\r;~\xa8\u01dbP\x89\xa2\xa1]\tQ\x9b\xe0\x00\x00\u07d4\xe9\xca\xfeA\xa5\xe8\xbb\xd9\v\xa0-\x9e\x06X[N\xb5F\xc5\u007f\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\xe9\u0559Ek%C\xe6\u06c0\xea\x9b!\x0e\x90\x80&\xe2\x14n\x89\n\u05ce\xbcZ\xc6 \x00\x00\u07d4\xe9\xe1\xf7\xcb\x00\xa1\x10\xed\xd0\xeb\xf8\xb3w\xef\x8a{\xb8V\x11\u007f\x89\n\u05ce\xbcZ\xc6 \x00\x00\xe0\x94\xea\x14\xbf\xda\nnvf\x8f\x87\x882\x1f\a\xdf7\x82N\xc5\u07ca*Z\x05\x8f\u0095\xed\x00\x00\x00\u07d4\xea\x1e\xa0\u0159\xaf\xb9\xcd6\u02ac\xbb\xb5+[\xbb\x97Ysw\x899\xfb\xae\x8d\x04-\xd0\x00\x00\u07d4\xea\x1e\xfb<\u727e\xde\xc3\xd6|>\x1b;\xc0\xe9\xaa\"\u007f\x90\x89'\xcaK\xd7\x19\xf0\xb8\x00\x00\u07d4\xea,\x19}&\xe9\x8b\r\xa8>\x1br\u01c7a\x8c\x97\x9d=\xb0\x89\x01\x11du\x9f\xfb2\x00\x00\xe0\x94\xea7y\xd1J\x13\xf6\u01c5f\xbc\xde@5\x91A:b9\u06ca)\xb7d2\xb9DQ \x00\x00\u07d4\xeaN\x80\x9e&j\xe5\xf1<\xdb\u33dd\x04V\xe68m\x12t\x89\xf3\xf2\v\x8d\xfai\xd0\x00\x00\xe0\x94\xeaS\xc9T\xf4\xed\x97\xfdH\x10\x11\x1b\u06b6\x9e\xf9\x81\xef%\xb9\x8a\x03\xa9\u057a\xa4\xab\xf1\xd0\x00\x00\u07d4\xeaS\xd2ed\x85\x9d\x9e\x90\xbb\x0eS\xb7\xab\xf5`\xe0\x16,8\x89\x15\xaf\x1dx\xb5\x8c@\x00\x00\u07d4\xea`Ci\x12\xdek\xf1\x87\u04e4r\xff\x8fS3\xa0\xf7\xed\x06\x89\x01\x11du\x9f\xfb2\x00\x00\u07d4\xea`T\x9e\xc7U?Q\x1d!I\xf2\xd4fl\xbd\x92C\xd9<\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\xeaf\xe7\xb8M\u037f6\xee\xa3\xe7[\x858*u\xf1\xa1]\x96\x89]\xbc\x91\x91&o\x11\x80\x00\u07d4\xeahlPW\t<\x17\x1cf\u06d9\xe0\x1b\x0e\xce\xcb0\x86\x83\x89\x14\u0768],\xe1G\x80\x00\u07d4\xeaj\xfe,\xc9(\xac\x83\x91\xeb\x1e\x16_\xc4\x00@\xe3t!\u7262\u007f\xa0c\xb2\xe2\xe6\x80\x00\u07d4\xeay\x05}\xab\xef^d\xe7\xb4O\u007f\x18d\x8e~S7\x18\u0489\n\u05ce\xbcZ\xc6 \x00\x00\u07d4\xea|Mm\xc7)\xcdk\x15|\x03\xad#|\xa1\x9a \x93F\u00c9lk\x93[\x8b\xbd@\x00\x00\u07d4\xea\x81h\xfb\xf2%\xe7\x86E\x9c\xa6\xbb\x18\xd9c\xd2kPS\t\x89\x1b\x1a\xe4\xd6\xe2\xefP\x00\x00\u07d4\xea\x81\u02868T\f\xd9\xd4\xd7=\x06\x0f,\xeb\xf2$\x1f\xfc>\x89j\xcb=\xf2~\x1f\x88\x00\x00\u07d4\xea\x83\x17\x19yYB@A\xd9\xd7\xc6z>\xce\x1d\xbbx\xbbU\x89\x15[\xd90\u007f\x9f\xe8\x00\x00\u07d4\xea\x85'\xfe\xbf\xa1\xad\xe2\x9e&A\x93)\u04d3\xb9@\xbb\xb7\u0709lj\xccg\u05f1\xd4\x00\x00\u07d4\xea\x8f0\xb6\xe4\xc5\xe6R\x90\xfb\x98d%\x9b\u0159\x0f\xa8\ue289\x01\x15\x8eF\t\x13\xd0\x00\x00\u07d4\xea\x94\xf3(\b\xa2\uf29b\xf0\x86\x1d\x1d$\x04\xf7\xb7\xbe%\x8a\x89\x01\x15\x8eF\t\x13\xd0\x00\x00\u07d4\xea\xa4\\\xea\x02\xd8},\xc8\xfd\xa9CN-\x98[\xd4\x03\x15\x84\x89h\x1f\xc2\xccn+\x8b\x00\x00\xe0\x94\uac3d\x14\x83\t\x18l\xf8\xcb\xd1;r2\xd8\tZ\u02c3:\x8a\x02C\x9a\x88\x1cjq|\x00\x00\u07d4\uaed0\xd3y\x89\xaa\xb3\x1f\xea\xe5G\xe0\xe6\xf3\x99\x9c\xe6\xa3]\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\xea\xc0\x82~\xff\fn?\xf2\x8a}JT\xf6\\\xb7h\x9d{\x99\x89\x9a\xd9\u67ddGR\x00\x00\u07d4\xea\xc1H(&\xac\xb6\x11\x1e\x19\xd3@\xa4_\xb8QWk\xed`\x89\x01\xbe\x8b\xab\x04\u067e\x80\x00\xe0\x94\xea\xc1{\x81\xedQ\x91\xfb\b\x02\xaaT3s\x13\x83A\a\xaa\xa4\x8a\x01\xb1\xaeMn.\xf5\x00\x00\x00\u07d4\xea\u00efW\x84\x92\u007f\u9958\xfcN\xec8\xb8\x10/7\xbcX\x8965\u026d\xc5\u07a0\x00\x00\xe0\x94\xea\u01b9\x88BT.\xa1\v\xb7O&\xd7\xc7H\x8fi\x8bdR\x8a\x04<3\xc1\x93ud\x80\x00\x00\xe0\x94\xea\xc7h\xbf\x14\xb8\xf9C.i\xea\xa8*\x99\xfb\xeb\x94\xcd\f\x9c\x8a\x14\u06f2\x19\\\xa2(\x90\x00\x00\u07d4\xea\xd2\x1c\x1d\xec\u03ff\x1c\\\xd9f\x88\xa2Gki\xba\a\xceJ\x89\x03\xf2M\x8eJ\x00p\x00\x00\u07d4\xea\xd4\xd2\xee\xfbv\xab\xaeU3\x96\x1e\xdd\x11@\x04\x06\xb2\x98\xfc\x89\xd2U\xd1\x12\xe1\x03\xa0\x00\x00\u07d4\xea\xd6Rb\xed]\x12-\xf2\xb2u\x14\x10\xf9\x8c2\xd1#\x8fQ\x89\x05\x83\x17\xedF\xb9\xb8\x00\x00\u07d4\xea\xd7P\x16\u3801Pr\xb6\xb1\b\xbc\xc1\xb7\x99\xac\xf08>\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\xea\xea#\xaa\x05r\x00\xe7\xc9\xc1^\x8f\xf1\x90\xd0\xe6l\f\x0e\x83\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\xea\xed\x16\xea\xf5\u06ab[\xf0)^^\a\u007fY\xfb\x82U\x90\v\x89\xd8\xd7&\xb7\x17z\x80\x00\x00\u07d4\xea\xed\xcck\x8bib\xd5\xd9(\x8c\x15lW\x9dG\xc0\xa9\xfc\xff\x89\x04\x9b\x9c\xa9\xa6\x944\x00\x00\u07d4\xea\xf5#\x88Tn\xc3Z\xcaolc\x93\xd8\xd6\t\xde:K\xf3\x89\x01\x15\x8eF\t\x13\xd0\x00\x00\u07d4\xeb\x10E\x8d\xac\xa7\x9eJk$\xb2\x9a\x8a\x8a\xdaq\x1b\u007f.\xb6\x89\u063beI\xb0+\xb8\x00\x00\u07d4\xeb\x1c\xea{E\u047dM\x0e*\x00{\u04ff\xb3Tu\x9e,\x16\x89\n\xbb\xcdN\xf3wX\x00\x00\u07d4\xeb%H\x1f\u035c\"\x1f\x1a\xc7\xe5\xfd\x1e\u0353\a\xa1b\x15\xb8\x89\n\xad\xec\x98?\xcf\xf4\x00\x00\xe0\x94\xeb.\xf3\u04cf\xe6R@<\xd4\xc9\xd8^\xd7\xf0h,\xd7\xc2\u078a\t\x0fSF\b\xa7(\x80\x00\x00\xe0\x94\xeb;\xddY\xdc\u0765\xa9\xbb*\xc1d\x1f\xd0!\x80\xf5\xf3e`\x8a\x01e\xc9fG\xb3\x8a \x00\x00\u07d4\xeb<\xe7\xfc8\x1cQ\xdb}_\xbdi/\x8f\x9e\x05\x8aLp=\x89\n\u05ce\xbcZ\xc6 \x00\x00\u07d4\xebE?Z:\xdd\u074a\xb5gP\xfa\xdb\x0f\xe7\xf9M\x9c\x89\xe7\x89\x01\x15\x8eF\t\x13\xd0\x00\x00\u07d4\xebO\x00\xe2\x836\xea\t\x94%\x88\ueb12\x18\x11\xc5\"\x14<\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\xebR\xab\x10U4\x922\x9c\x1cT\x83:\xe6\x10\xf3\x98\xa6[\x9d\x89\b=lz\xabc`\x00\x00\u07d4\xebW\r\xba\x97R'\xb1\xc4-n\x8d\xea,V\u026d\x96\x06p\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\xebc\x94\xa7\xbf\xa4\u0489\x11\u0565\xb2>\x93\xf3^4\f\"\x94\x89\x04:w\xaa\xbd\x00x\x00\x00\u07d4\xebh\x10i\x1d\x1a\xe0\u045eG\xbd\"\u03be\u0cfa'\xf8\x8a\x89\x87\x85c\x15\xd8x\x15\x00\x00\u07d4\xebvBL\x0f\u0557\xd3\xe3A\xa9d*\xd1\xee\x11\x8b+W\x9d\x89\xd8\xd7&\xb7\x17z\x80\x00\x00\u07d4\xeb| +F+|\u0145]t\x84u_n&\xefC\xa1\x15\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\xeb\x83\\\x1a\x91\x18\x17\x87\x8a3\xd1gV\x9e\xa3\xcd\u04c7\xf3(\x8965\u026d\xc5\u07a0\x00\x00\u07d4\ub268\x82g\t\t\xcf7~\x9ex(n\xe9{\xa7\x8dF\u0089+|\xc2\xe9\xc3\"\\\x00\x00\xe0\x94\xeb\x90\u01d3\xb3S\x97a\xe1\xc8\x14\xa2\x96q\x14\x86\x92\x19>\xb4\x8a\x02\x8a\x85t%Fo\x80\x00\x00\u07d4\xeb\x9c\xc9\xfe\bi\xd2\u06b5,\u01ea\xe8\xfdW\xad\xb3_\x9f\xeb\x89j\x93\xbb\x17\xaf\x81\xf8\x00\x00\xe0\x94\ub8c8\xb0\xda'\xc8{\x1c\xc0\xea\xc6\xc5{,Z\vE\x9c\x1a\x8a\x01p\xa0\xf5\x04\x0eP@\x00\x00\u07d4\xeb\xaa!m\xe9\xccZC\x03\x17\a\xd3o\xe6\u057e\xdc\x05\xbd\xf0\x89j\xc5\xc6-\x94\x86\a\x00\x00\u07d4\xeb\xac+D\b\xefT1\xa1;\x85\b\xe8bP\x98!\x14\xe1E\x89\xd8\xd7&\xb7\x17z\x80\x00\x00\u07d4\xeb\xb6,\xf8\xe2,\x88K\x1b(\xc6\xfa\x88\xfb\xbc\x17\x93\x8a\xa7\x87\x89+By\x84\x03\u0278\x00\x00\u07d4\xeb\xb7\xd2\xe1\x1b\u01b5\x8f\n\x8dE\xc2\xf6\xde0\x10W\n\u0211\x89\x01s\x17\x90SM\xf2\x00\x00\u07d4\xeb\xbbO,=\xa8\xbe>\xb6-\x1f\xfb\x1f\x95\x02a\u03d8\xec\u0689lk\x93[\x8b\xbd@\x00\x00\u07d4\xeb\xbdM\xb9\x01\x99R\u058b\x1b\x0fm\x8c\xf0h<\x008{\xb5\x89\x12\x04\x01V=}\x91\x00\x00\u07d4\xeb\xbe\xeb%\x91\x84\xa6\xe0\x1c\xcc\xfc\"\a\xbb\u0603xZ\xc9\n\x89!\x9b\xc1\xb0G\x83\xd3\x00\x00\u07d4\xeb\xd3V\x15j81#4=H\x84;\xff\xeda\x03\xe8f\xb3\x89j\xcb=\xf2~\x1f\x88\x00\x00\u07d4\xeb\xd3{%ec\xe3\fo\x92\x89\xa8\xe2p/\bR\x88\b3\x89lj\xccg\u05f1\xd4\x00\x00\u07d4\xeb\xe4l\xc3\xc3L2\xf5\xad\xd6\xc3\x19[\xb4\x86\xc4q>\xb9\x18\x8965\u026d\xc5\u07a0\x00\x00\xe0\x94\xeb\xff\x84\xbb\xefB0q\xe6\x04\xc3a\xbb\xa6w\xf5Y=\xefN\x8a\x02\x1e\x19\xe0\u027a\xb2@\x00\x00\u07d4\xec\t'\xba\xc7\xdc6f\x9c(5J\xb1\xbe\x83\xd7\xee\xc3\t4\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\xec\x0e\x18\xa0\x1d\xc4\xdc]\xaa\xe5g\xc3\xfaL\u007f\x8f\x9bY\x02\x05\x89\x11\x1f\xfe@JA\xe6\x00\x00\xe0\x94\xec\x116,\xec\x81\t\x85\xd0\xeb\xbd{sE\x14D\x98[6\x9f\x8a\x06ZNIWpW1\x80\x00\u07d4\xec,\xb8\xb97\x8d\xff1\xae\xc3\xc2.\x0em\xad\xff1J\xb5\u0749lk\x93[\x8b\xbd@\x00\x00\u07d4\xec0\xad\u0749[\x82\xee1\x9eT\xfb\x04\xcb+\xb09q\xf3k\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\xec;\x8bX\xa1'\x03\xe5\x81\xce_\xfd~!\xc5}\x1e\\f?\x89\\(=A\x03\x94\x10\x00\x00\u07d4\xecHg\xd2\x17Z\xb5\xb9F\x93aYUFUF\x84\u0364`\x89\xa2\xa1]\tQ\x9b\xe0\x00\x00\u07d4\xecM\b\xaa.GIm\u0287\"]\xe3?+@\xa8\xa5\xb3o\x89\b\x90\xb0\xc2\xe1O\xb8\x00\x00\u07d4\xecX\xbc\r\f \xd8\xf4\x94efAS\xc5\xc1\x96\xfeY\u6f89\x15\xaf\x1dx\xb5\x8c@\x00\x00\u07d4\xec[\x19\x8a\x00\u03f5Z\x97\xb5\xd56D\xcf\xfa\x8a\x04\u04abE\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\xec]\xf2'\xbf\xa8]z\xd7kBn\x1c\xee\x96;\xc7\xf5\x19\u074965\u026d\xc5\u07a0\x00\x00\xe0\x94\xec_\xea\xfe!\f\x12\xbf\u0265\xd0Y%\xa1#\xf1\xe7?\xbe\xf8\x8a`\x8f\xcf=\x88t\x8d\x00\x00\x00\u07d4\xeci\x04\xba\xe1\xf6\x97\x90Y\x17\t\xb0`\x97\x83s?%s\xe3\x89\x1b\x1a\xe4\xd6\xe2\xefP\x00\x00\xe0\x94\xecs\x11L^@o\u06fe\t\xb4\xfab\x1b\xd7\x0e\xd5N\xa1\xef\x8a\x050%\xcd!o\xceP\x00\x00\u07d4\xecs\x83=\xe4\xb8\x10\xbb\x02x\x10\xfc\x8fi\xf5D\xe8<\x12\u044965\u026d\xc5\u07a0\x00\x00\u07d4\xecu\xb4\xa4u\x13\x12\v\xa5\xf8`9\x81O\x19\x98\xe3\x81z\u00c9\t\xb0\xbc\xe2\xe8\xfd\xba\x00\x00\u07d4\xecv\xf1.W\xa6U\x04\x03?,\v\xceo\xc0;\xd7\xfa\n\u0109\xc2\x12z\xf8X\xdap\x00\x00\u0794\xec\x80\x14\xef\xc7\xcb\xe5\xb0\xceP\xf3V,\xf4\xe6\u007f\x85\x93\xcd2\x88\xf0\x15\xf2W6B\x00\x00\u07d4\xec\x82\xf5\r\x06G_hM\xf1\xb3\x92\xe0\r\xa3A\xaa\x14TD\x89lk\x93[\x8b\xbd@\x00\x00\xe0\x94\xec\x83\xe7\x98\u00d6\xb7\xa5^*\"$\xab\u0343K'\xeaE\x9c\x8a\x02\x8a\x85t%Fo\x80\x00\x00\u07d4\xec\x89\xf2\xb6x\xa1\xa1[\x914\xec^\xb7\fjb\a\x1f\xba\xf9\x89\n\u05ce\xbcZ\xc6 \x00\x00\u07d4\xec\x8c\x1d{j\xac\xcdB\x9d\xb3\xa9\x1e\xe4\xc9\xeb\x1c\xa4\xf6\xf7<\x89\xe6d\x99\"\x88\xf2(\x00\x00\xe0\x94\xec\x98Q\xbd\x91rpa\x02g\xd6\x05\x18\xb5M<\xa2\xb3[\x17\x8a\bxg\x83&\xea\xc9\x00\x00\x00\u07d4\xec\x99\xe9]\xec\xe4o\xff\xfb\x17^\xb6@\x0f\xbe\xbb\b\ue6d5\x89\x05k\xc7^-c\x10\x00\x00\u07d4\xec\xa5\xf5\x87\x92\xb8\xc6-*\xf5Vq~\xe3\xee0(\xbeM\u0389lk\x93[\x8b\xbd@\x00\x00\u07d4\xec\xabZ\xba[\x82\x8d\xe1pS\x81\xf3\x8b\xc7D\xb3+\xa1\xb47\x892\xf5\x1e\u06ea\xa30\x00\x00\u07d4\xec\xaf3P\xb7\xce\x14M\x06\x8b\x18`\x10\x85,\x84\xdd\f\xe0\xf0\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\xec\xb9LV\x8b\xfeY\xad\xe6Pd_O&0lsl\xac\xe4\x89\x0e~\xeb\xa3A\vt\x00\x00\xe0\x94\xec\xbeB^g\r9\tN \xfbVC\xa9\xd8\x18\xee\xd26\u078a\x01\x0f\f\xf0d\xddY \x00\x00\xe0\x94\xec\xbe^\x1c\x9a\u04b1\xdc\xcf\n0_\xc9R/Fi\xdd:\xe7\x8a\x01\x0f\f\xf0d\xddY \x00\x00\u07d4\xec\xcfz\x04W\xb5f\xb3F\xcag:\x18\x0fDA0!j\u00c9\x05k\xc7^-c\x10\x00\x00\u07d4\xec\u0466(\x025\x1aAV\x8d#\x030\x04\xac\xc6\xc0\x05\xa5\u04c9\x02\xb5\xe3\xaf\x16\xb1\x88\x00\x00\u07d4\xec\xd2v\xafd\u01dd\x1b\u0669+\x86\xb5\u835a\x95\xeb\x88\xf8\x89\x01\x15\x8eF\t\x13\xd0\x00\x00\xe0\x94\xec\u0506\xfc\x19g\x91\xb9,\xf6\x12\xd3HaO\x91VH\x8b~\x8a\x02\x8a\x85t%Fo\x80\x00\x00\u07d4\xec\xda\xf92)\xb4^\xe6r\xf6]\xb5\x06\xfb^\xca\x00\xf7\xfc\xe6\x89W\x01\xf9m\xcc@\xee\x80\x00\u07d4\xec\xe1\x11g\vV<\u037e\xbc\xa5#\x84)\x0e\xcdh\xfe\\\x92\x89\x01\x15\x8eF\t\x13\xd0\x00\x00\u07d4\xec\xe1\x15&\x82\xb7Y\x8f\xe2\xd1\xe2\x1e\xc1U3\x88T5\xac\x85\x89\xd8\xd7&\xb7\x17z\x80\x00\x00\u07d4\xec\xe1)\bw\xb5\x83\xe3a\xa2\xd4\x1b\x00\x93F\xe6'N%8\x89\x10CV\x1a\x88)0\x00\x00\u07d4\xec\xf0]\a\xea\x02n~\xbfIA\x00#5\xba\xf2\xfe\xd0\xf0\x02\x89\n\u05ce\xbcZ\xc6 \x00\x00\u07d4\xec\xf2L\xdd|\"\x92\x8cD\x1eiM\xe4\xaa1\xb0\xfa\xb5\x97x\x89 \x86\xac5\x10R`\x00\x00\xe0\x94\xec\xfd\x00M\x02\xf3l\xd4\u0634\xa8\xc1\xa9S;j\xf8\\\xd7\x16\x8a\x01\x0fA\xac\xb4\xbb;\x9c\x00\x00\xe0\x94\xed\x02\x06\xcb#1Q(\xf8\xca\xff&\xf6\xa3\v\x98Tg\xd0\"\x8a\bxg\x83&\xea\xc9\x00\x00\x00\u07d4\xed\x10e\xdb\u03dds\xc0O\xfcy\b\x87\r\x88\x14h\xc1\xe12\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\xed\x12vQ;o\u0186(\xa7A\x85\xc2\xe2\f\xbb\xcax\x17\xbf\x89\nZ\xa8P\t\xe3\x9c\x00\x00\xe0\x94\xed\x12\xa1\xba\x1f\xb8\xad\xfc\xb2\r\xfa\x19X.RZ\xa3\xb7E$\x8a\x01je\x02\xf1Z\x1eT\x00\x00\u07d4\xed\x16\xce9\xfe\xef;\xd7\xf5\xd1b\x04^\x0fg\xc0\xf0\x00F\xbb\x89\x01\x15\x8eF\t\x13\xd0\x00\x00\u07d4\xed\x1a\\C\xc5t\xd4\xe94)\x9b$\xf1G,\u071f\xd6\xf0\x10\x89\n\u05ce\xbcZ\xc6 \x00\x00\u07d4\xed\x1b$\xb6\x91-Q\xb34\xac\r\xe6\xe7q\xc7\xc0EF\x95\xea\x89\x02+\x1c\x8c\x12'\xa0\x00\x00\u07d4\xed\x1f\x1e\x11Z\r`\xce\x02\xfb%\xdf\x01M(\x9e:\f\xbe}\x89\x1b\x1a\xe4\xd6\xe2\xefP\x00\x00\u07d4\xed10\\1\x9f\x92s\u04d3m\x8f[/q\u9c72)c\x89\x05k\xc7^-c\x10\x00\x00\u07d4\xed2z\x14\xd5\u03ed\u0641\x03\xfc\t\x99q\x8d~\xd7\x05(\xea\x89N\x10\x03\xb2\x8d\x92\x80\x00\x00\u07d4\xed<\xbc7\x82\u03bdg\x98\x9b0\\A3\xb2\xcd\xe3\"\x11\xeb\x89\x15\xaf\x1dx\xb5\x8c@\x00\x00\u07d4\xed@\x14S\x8c\xeefJ/\xbc\xb6\xdcf\x9fz\xb1m\v\xa5|\x89\n\u05ce\xbcZ\xc6 \x00\x00\u07d4\xedA\u188f\\\xaa\x848\x80\xefN\x8b\b\xbdl3\x14\x1e\u07c9*\xd5\xdd\xfaz\x8d\x83\x00\x00\xe0\x94\xedK\xe0J\x05-z\u0333\xdc\u03901\x9d\xba@ \xab,h\x8a\a\xf3zp\xea\xf3b\x17\x80\x00\xe0\x94\xedR\xa2\xcc\bi\u071e\x9f\x84+\u0415|G\xa8\xe9\xb0\xc9\xff\x8a\x02\x05\xb4\u07e1\xeetx\x00\x00\u07d4\xed[LA\xe7b\xd9B@Cs\xca\xf2\x1e\xd4a]%\xe6\xc1\x89m-O=\x95%\xb4\x00\x00\u07d4\xed`\u012bnT\x02\x061~5\x94zc\xa9\xcak\x03\xe2\u02c9\x03\x1a\u066d\vF\u007f\x80\x00\u07d4\xedd\x1e\x066\x8f\xb0\xef\xaa\x17\x03\xe0\x1f\xe4\x8fJhS\t\xeb\x89\n\u05ce\xbcZ\xc6 \x00\x00\u07d4\xedfC\xc0\xe8\x88K-2\x11\x857\x85\xa0\x8b\xf8\xf3>\u049f\x89Hz\x9a0E9D\x00\x00\xe0\x94\xedp\xa3|\xdd\x1c\xbd\xa9tm\x93\x96X\xae*a\x81(\x85x\x8a\x02\bj\xc3Q\x05&\x00\x00\x00\u07d4\xedsFvn\x1agm\r\x06\xec\x82\x18g\xa2v\xa0\x83\xbf1\x89\u064a\t1\xcc-I\x00\x00\u07d4\xed\x86&\x16\xfc\xbf\xb3\xbe\xcbt\x06\xf7<\\\xbf\xf0\f\x94\aU\x89\\(=A\x03\x94\x10\x00\x00\u07d4\xed\x9e\x03\f\xa7\\\xb1\u049e\xa0\x1d\rL\xdf\xdc\xcd8D\xb6\xe4\x89\x01\xac\xc1\x16\u03ef\xb1\x80\x00\xe0\x94\ud7bc\u02e4/\x98\x15\xe7\x823&m\xd6\xe85\xb6\xaf\xc3\x1b\x8a\x01EB\xba\x12\xa37\xc0\x00\x00\u07d4\ud7f1\xf5\xaf/\xbf\u007f\xfcP)\xce\xe4+p\xff\\'[\xf5\x89\x0f-\xc7\xd4\u007f\x15`\x00\x00\u07d4\xed\xa4\xb2\xfaY\u0584\xb2z\x81\r\xf8\x97\x8as\xdf0\x8ac\u0089\xd8\xd7&\xb7\x17z\x80\x00\x00\xe0\x94\xed\xb4s59y\xa2\x06\x87\x9d\xe1D\xc1\n<Q\xd7\xd7\b\x1a\x8a\x01EB\xba\x12\xa37\xc0\x00\x00\u07d4\xed\xb7\x1e\xc4\x1b\xda}\u0386\xe7f\xe6\xe8\xc3\xe9\x90w#\xa6\x9b\x89\x01\x15\x8eF\t\x13\xd0\x00\x00\u07d4\xed\xba\xc9R{T\xd6\xdfz\xe2\xe0\x00\u0323a;\xa0\x15\xca\xe3\x89j\xcb=\xf2~\x1f\x88\x00\x00\u07d4\xed\xc2/\xb9,c\x8e\x1e!\xff\\\xf09\u06a6\xe74\xda\xfb)\x89\x10'\x94\xad \xdah\x00\x00\xe0\x94\xed\xda\u0354\uc262\uf58f\u03d7z\b\xf1\xfa\xe2uxi\x8a\x01\xb1\xaeMn.\xf5\x00\x00\x00\u07d4\xed\u06ea\xfb\xc2\x1b\xe8\xf2Ub\xf1\xedm\x05\u05af\xb5\x8f\x02\u0089lk\x93[\x8b\xbd@\x00\x00\u07d4\xed\xe0\x14~\xc02\xc3a\x83\x10\xc1\xff%i\v\xf1r\x19=\xac\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\xed\xe5\xde|\u007f\xb7\xee\xe0\xf3ndS\nAD\x0e\u07fe\xfa\u03c9!u^\xe1\xef+\x18\x00\x00\u07d4\xed\xe7\x9a\xe1\xffO\x16\x06\u0552p!o\xa4j\xb2\xdd\xd4\uca89\a\xea(2uw\b\x00\x00\xe0\x94\xed\xe8\xc2\u02c7o\xbe\x8aL\u0282\x906\x1a~\xa0\x1ai\xfd\xf8\x8a\x01\xa7\x8ckD\xf8A\x83\x80\x00\u07d4\xed\xebH\x94\xaa\xdd\x00\x81\xbb\xdd\xd3\xe8\x84h\x04\xb5\x83\u045f'\x89lk\x93[\x8b\xbd@\x00\x00\xe0\x94\xed\xf6\x03\x89\x02(\xd7\xd5\u0793\t\x94+\\\xadB\x19\xef\x9a\u05ca\x01\x0f\f\xf0d\xddY \x00\x00\u07d4\xed\xf8\xa3\xe1\xd4\x0f\x13\xb7\x9e\xc8\xe3\xe1\xec\xf2b\xfd\x92\x11bc\x89\b\x90\xb0\xc2\xe1O\xb8\x00\x00\u07d4\xed\xfd\xa2\xd5\u06d8\xf98\a\x14fMT\xb4\xee\x97\x1a\x1c\xae\x03\x89\x02+\xb8\xdd\xd6y\xbe\x00\x00\u07d4\xee\x00\a\xb0\x96\r\x00\x90\x8a\x94C*suW\x87j\xac|1\x89\x02\xe0B\x1ei\xc4\u0300\x00\u07d4\xee\x04\x9a\xf0\x05\x97M\xd1\u01f3\xa9\u028d\x9a\xa7qu\xbaS\xaa\x89\x12\x11\xec\xb5m\x13H\x80\x00\u07d4\xee%\xb9\xa7\x03&y\xb1\x13X\x8e\xd5,\x13}\x1a\x05:\x1e\x94\x89\n\xd5\x0f?N\xea\x8e\x00\x00\u07d4\xee1\x16\u007f\x9c\xc9;<de`\x9dy\xdb\f\u0790\xe8HL\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\xee4\xc7\xe7\x99]\xb9\xf1\x87\xcf\xf1V\x91\x8c\xfbo\x13\xf6\xe0\x03\x89j@v\xcfy\x95\xa0\x00\x00\u07d4\xee5d\xf5\xf1\xba\x0f\x94\xec{\xac\x16K\u077f1\u0188\x8bU\x89\x05k\xc7^-c\x10\x00\x00\xe0\x94\xeeX\xfb=\xb2\x90p\xd0\x13\x01\x88\xceG+\xe0\xa1r\xb8\x90U\x8a\x02\x1fB\xdc\xdcX\xe3\x9c\x00\x00\u07d4\xeee[\xb4\xee\x0e\x8dTxRo\xb9\xf1^@d\xe0\x9f\xf3\u0749\n\u05ce\xbcZ\xc6 \x00\x00\u07d4\xeeiY\xde+g\x96{q\x94\x8c\x89\x1a\xb0\r\x8c\x8f8\xc7\u0709\x06hZ\xc1\xbf\xe3,\x00\x00\u07d4\xeel\x03B\x99i\xca\x12b\xcb?\nJT\xaf\xa7\xd3H\xd7\xf5\x89\r\xe2\x19\xf9\x1f\xc1\x8a\x00\x00\u07d4\xeeqy>:\xcf\x12\xa7'OV9a\xf57R\x9d\x89\xc7\u0789lk\x93[\x8b\xbd@\x00\x00\u07d4\xeer\x88\xd9\x10\x86\xd9\xe2\xeb\x91\x00\x14\u066b\x90\xa0-x\u00a0\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\xee|=\xed|(\xf4Y\xc9/\xe1;M\x95\xba\xfb\xab\x026}\x89%\xf2s\x93=\xb5p\x00\x00\xe0\x94\xee\x86} \x91k\xd2\xe9\xc9\xec\xe0\x8a\xa0C\x85\xdbf|\x91.\x8a\n\x96\x81c\xf0\xa5{@\x00\x00\u07d4\ue25b\x02\xcb\xcb99\xcda\xde\x13B\xd5\x04\x82\xab\xb6\x852\x89_h\xe8\x13\x1e\u03c0\x00\x00\u07d4\xee\x90m}_\x17H%\x81t\xbeL\xbc8\x93\x03\x02\xab{B\x89\n\u05ce\xbcZ\xc6 \x00\x00\u07d4\ue5ea\x8a\u019e\xdfz\x98}mp\x97\x9f\x8e\xc1\xfb\xcaz\x94\x89\x14b\fW\xdd\xda\xe0\x00\x00\u07d4\xee\xa1\xe9y\x88\xdeu\xd8!\xcd(\xadh\"\xb2,\u0398\x8b1\x89\x1c0s\x1c\xec\x03 \x00\x00\xe0\x94\xee\u048c?\x06\x8e\tJ0K\x85<\x95\nh\t\xeb\xcb\x03\xe0\x8a\x03\xa9\u057a\xa4\xab\xf1\xd0\x00\x00\u07d4\xee\u04c4\xef-A\xd9\xd2\x03\x97NW\xc1#(\xeav\x0e\b\xea\x8965\u026d\xc5\u07a0\x00\x00\u07d4\xee\xdflB\x80\xe6\xeb\x05\xb94\xac\xe4(\xe1\x1dB1\xb5\x90[\x89\n\u05ce\xbcZ\xc6 \x00\x00\u07d4\xee\xe7a\x84~3\xfda\u0653\x87\xee\x14b\x86\x94\u047f\xd5%\x89lk\x93[\x8b\xbd@\x00\x00\xe0\x94\xee\xe9\xd0Rn\xda\x01\xe41\x16\xa3\x952-\u0689pW\x8f9\x8a\x02\x1e\x19\x99\xbb\xd5\u04be\x00\x00\u07d4\xee\xf1\xbb\xb1\xe5\xa8?\u0782H\xf8\x8e\xe3\x01\x8a\xfa-\x132\xeb\x89\n\u05ce\xbcZ\xc6 \x00\x00\u07d4\xee\xfb\xa1-\xfc\x99gB\xdby\x04d\xca}';\xe6\xe8\x1b>\x8965\u026d\xc5\u07a0\x00\x00\u07d4\xee\xfd\x05\xb0\xe3\xc4\x17\xd5[3C\x06\x04\x86\xcd\xd5\xe9*\xa7\xa6\x89M\x85<\x8f\x89\b\x98\x00\x00\u07d4\xef\r\xc7\xddzS\xd6\x12r\x8b\xcb\u04b2|\x19\xddM}fo\x89&A\x1c[5\xf0Z\x00\x00\u07d4\xef\x11RR\xb1\xb8E\u0345\u007f\x00-c\x0f\x1bo\xa3zNP\x89j\xcb=\xf2~\x1f\x88\x00\x00\u07d4\xef\x1c\x04w\xf1\x18M`\xac\u02b3t\xd3tUz\n>\x10\xf3\x89\b=lz\xabc`\x00\x00\u07d4\xef,4\xbbH}7b\xc3\u0327\x82\xcc\xddz\x8f\xbb\n\x991\x89\t\xc2\x00vQ\xb2P\x00\x00\u07d4\xef5\xf6\u0531\a^j\xa19\x15\x1c\x97K/FX\xf7\x058\x89<;\xc3?\x94\xe5\r\x80\x00\u07d4\xef9\u0291s\xdf\x15S\x1ds\xe6\xb7*hKQ\xba\x0f+\xb4\x89V\xa0\xb4un\xe28\x00\x00\u07d4\xefF<&y\xfb'\x91d\xe2\f=&\x915\x87s\xa0\xad\x95\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\xefG\xcf\a>6\xf2q\xd5\"\xd7\xfaNq \xadP\a\xa0\xbc\x89\x87\x86x2n\xac\x90\x00\x00\u07d4\xefa\x15[\xa0\t\xdc\u07be\xf1\v(\xd9\xda=\x1b\xc6\xc9\xce\u0509\x034-`\xdf\xf1\x96\x00\x00\u0794\xefix\x1f2\xff\xce34o,\x9a\xe3\xf0\x84\x93\xf3\xe8/\x89\x88\xfc\x93c\x92\x80\x1c\x00\x00\u07d4\xefv\xa4\u034f\xeb\xcb\u0278\x18\xf1x(\xf8\xd94s\xf3\xf3\u02c9\xd8\xd7&\xb7\x17z\x80\x00\x00\u07d4\uf4c1\x8fhM\xb0\xc3g^\xc8\x132\xb3\x18>\xcc(\xa4\x95\x89T\x06\x923\xbf\u007fx\x00\x00\xe0\x94\xef\x9fY\xae\xdaA\x8c\x14\x94h-\x94\x1a\xabI$\xb5\xf4\x92\x9a\x8a\x15-\x02\xc7\xe1J\xf6\x80\x00\x00\u07d4\uf9b1\xf0\xdb`57\x82h\x91\xb8\xb4\xbc\x169\x84\xbb@\u03495e\x9e\xf9?\x0f\xc4\x00\x00\u07d4\xef\xbdR\xf9}\xa5\xfd:g:F\xcb\xf30D{~\x8a\xad\\\x89\x05l<\x9b\x80\xa0\xa6\x80\x00\xe0\x94\xef\xc8\xcf\x19c\u0269Rg\xb2(\xc0\x86#\x98\x89\xf4\xdf\xd4g\x8a\x02\x1e\x19\xe0\u027a\xb2@\x00\x00\u07d4\xef\u02ae\x9f\xf6M,\xd9[RI\xdc\xff\xe7\xfa\xa0\xa0\xc0\xe4M\x89\x15\xbeat\xe1\x91.\x00\x00\u07d4\xef\xcc\xe0k\xd6\b\x9d\x0eE\x8e\xf5a\xf5\xa6\x89H\n\xfep\x00\x89 \x86\xac5\x10R`\x00\x00\u07d4\xef\xe0g]\xa9\x8a]\xdap\u0356\x19k\x87\xf4\xe7&\xb43H\x89?\x19\xbe\xb8\xdd\x1a\xb0\x00\x00\u07d4\xef\xe8\xff\x87\xfc&\x0e\agc\x8d\xd5\xd0/\xc4g.\x0e\xc0m\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\xef\xeb\x19\x97\xaa\xd2w\xcc3C\x0ea\x11\xed\tCY@H\xb8\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\xef\xee\xa0\x10uo\x81\xdaK\xa2[r\x17\x87\xf0X\x17\v\uff49\x01\u009c\x9c\xf7p\xef\x00\x00\u07d4\xef\xf5\x1dr\xad\xfa\xe1C\xed\xf3\xa4+\x1a\xecU\xa2\xcc\xdd\v\x90\x89\x10CV\x1a\x88)0\x00\x00\u07d4\xef\xf8kQ#\xbc\xdc\x17\xedL\xe8\xe0[~\x12\xe5\x13\x93\xa1\xf7\x89\x1b\x1a\xe4\xd6\xe2\xefP\x00\x00\u07d4\xef\xfc\x15\u41f1\xbe\xda\n\x8d\x13%\xbd\xb4\x17\"@\xdcT\n\x89\x03\x8599\xee\xe1\xde\x00\x00\xe0\x94\xf0\x11\x95\xd6W\xef<\x94.l\xb89I\xe5\xa2\v\\\xfa\x8b\x1e\x8a\x05ts\xd0]\xab\xae\x80\x00\x00\u07d4\xf0'\x96)Q\x01gB\x88\xc1\xd94g\x05=\x04\"\x19\xb7\x94\x89(\x1d\x90\x1fO\xdd\x10\x00\x00\u07d4\xf09h={=\"[\xc7\xd8\u07ed\xefc\x164A\xbeA\xe2\x89\x01\xdd\x1eK\xd8\xd1\xee\x00\x00\u07d4\xf0Jj7\x97\b\xb9B\x8dr*\xa2\xb0kw\xe8\x895\u03c9\x89\x10CV\x1a\x88)0\x00\x00\u07d4\xf0M,\x91\xef\xb6\xe9\xc4_\xfb\xe7KCL\x8c_+\x02\x8f\x1f\x8965\u026d\xc5\u07a0\x00\x00\u07d4\xf0W\xaaf\xcav~\xde\x12J\x1c[\x9c\xc5\xfc\x94\xef\v\x017\x89p\xa2K\u02b6\xf4]\x00\x00\u07d4\xf0[\xa8\u05f6\x859\xd930\v\xc9(\x9c=\x94t\xd0A\x9e\x89\x06\xda'\x02M\xd9`\x00\x00\u07d4\xf0\\\xee\xabeA\x05dp\x99Qw<\x84E\xad\x9fN\u01d7\x89\x10C\x16'\xa0\x93;\x00\x00\xe0\x94\xf0_\xcdL\rs\xaa\x16~US\xc8\xc0\xd6\xd4\xf2\xfa\xa3\x97W\x8a\x02\xd2\xd6l1p\xb2\x98\x00\x00\u07d4\xf0g\xe1\xf1\u0583UjL\xc4\xfd\f\x03\x13#\x9f2\xc4\xcf\u060965\u026d\xc5\u07a0\x00\x00\u07d4\xf0g\xfb\x10\u07f2\x93\u962b\xe5d\xc0U\xe34\x8f\x9f\xbf\x1e\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\xf0h\xdf\xe9]\x15\xcd:\u007f\x98\xff\xa6\x88\xb44hB\xbe&\x90\x89D\n\xd8\x19\xe0\x97L\x00\x00\xe0\x94\xf0j\x85J<]\xc3m\x1cI\xf4\xc8}m\xb33\xb5~J\u074a\x02\x1e\x19\xe0\u027a\xb2@\x00\x00\u07d4\xf0y\xe1\xb1&_P\xe8\u0229\x8e\xc0\u01c1^\xb3\xae\xac\x9e\xb4\x89\x01\x16\xdc:\x89\x94\xb3\x00\x00\xe0\x94\xf0{\xd0\xe5\xc2\xcei\xc7\u0127$\xbd&\xbb\xfa\x9d*\x17\xca\x03\x8a\x01@a\xb9\xd7z^\x98\x00\x00\xe0\x94\xf0\x83*k\xb2U\x03\xee\xcaC[\xe3\x1b\v\xf9\x05\xca\x1f\xcfW\x8a\x01je\x02\xf1Z\x1eT\x00\x00\u07d4\xf0\x9b>\x87\xf9\x13\xdd\xfdW\xae\x80I\xc71\u06e9\xb66\xdf\u00c9 \xf5\xb1\uab4d\x80\x00\x00\u07d4\xf0\xb14\v\x99oo\v\xf0\xd9V\x1c\x84\x9c\xaf\u007fD0\xbe\xfa\x89\x05k\xc7^-c\x10\x00\x00\u07d4\xf0\xb1\xf9\xe2x2\xc6\xdei\x14\xd7\n\xfc#\x8ct\x99\x95\xac\xe4\x89lk\x93[\x8b\xbd@\x00\x00\xe0\x94\xf0\xb4i\xea\xe8\x9d@\f\xe7\xd5\xd6j\x96\x95\x03p6\xb8\x89\x03\x8a\x04<3\xc1\x93ud\x80\x00\x00\u07d4\xf0\xb9\u0583\u03a1+\xa6\x00\xba\xac\xe2\x19\xb0\xb3\xc9~\x8c\x00\xe4\x89\x05k\xc7^-c\x10\x00\x00\u07d4\xf0\xbe\x0f\xafMy#\xfcDF\"\u0458\f\xf2\u0650\xaa\xb3\a\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\xf0\xc0\x81\xdaR\xa9\xae6d*\xdf^\b _\x05\xc5Ah\xa6\x89\x06\x04o7\xe5\x94\\\x00\x00\u07d4\xf0\xc7\r\rm\xabvc\xaa\x9e\xd9\xce\xeaV~\xe2\u01b0'e\x89qC\x8a\u0167\x91\xa0\x80\x00\u07d4\xf0\xcb\xef\x84\xe1ic\x00\x98\xd4\xe3\x01\xb2\x02\b\xef\x05\x84j\u0249\x0e\v\x83EPkN\x00\x00\u07d4\xf0\xd2\x16c\u0630\x17n\x05\xfd\xe1\xb9\x0e\xf3\x1f\x850\xfd\xa9_\x89lj\xccg\u05f1\xd4\x00\x00\xe0\x94\xf0\xd5\xc3\x1c\xcbl\xbe0\xc7\xc9\xea\x19\xf2h\xd1Y\x85\x1f\x8c\x9c\x8a\x03\x89O\x0eo\x9b\x9fp\x00\x00\u07d4\xf0\xd6L\xf9\xdf\tt\x113\xd1pH_\xd2K\x00P\x11\xd5 \x89\x1b\b\x93A\xe1O\xcc\x00\x00\u07d4\xf0\xd8X\x10^\x1bd\x81\x01\xac?\x85\xa0\xf8\"+\xf4\xf8\x1dj\x89 \x86\xac5\x10R`\x00\x00\u07d4\xf0\xdcC\xf2\x05a\x91'P{+\x1c\x1c\xfd\xf3-(1\t \x89\x10^\xb7\x9b\x94\x17\b\x80\x00\u07d4\xf0\xe1\u07e4*\u07ac/\x17\xf6\xfd\xf5\x84\xc9Hb\xfdV3\x93\x89\x1b\x1a\xe4\xd6\xe2\xefP\x00\x00\u07d4\xf0\xe2d\x9c~j?,]\xfe3\xbb\xfb\xd9'\xca<5\nX\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\xf0\xe7\xfb\x9eB\nS@\xd56\xf4\x04\b4O\xea\xef\xc0j\xef\x8965\u026d\xc5\u07a0\x00\x00\u07d4\xf1\x04b\xe5\x8f\xcc\a\U000d5121\x87c\x94Q\x16~\x85\x92\x01\x89\t4\xdd]3\xbc\x97\x00\x00\xe0\x94\xf1\x06a\xff\x94\x14\x0f >zH%rCy8\xbe\xc9\xc3\xf7\x8a\x04<3\xc1\x93ud\x80\x00\x00\u0794\xf1\x14\xff\r\x0f$\xef\xf8\x96\xed\xdeTq\u07a4\x84\x82J\x99\xb3\x88\xbe -j\x0e\xda\x00\x00\u07d4\xf1\x16\xb0\xb4h\x0fS\xabr\xc9h\xba\x80.\x10\xaa\x1b\xe1\x1d\u0209\x01\x15\x8eF\t\x13\xd0\x00\x00\xe0\x94\xf1\x1c\xf5\xd3cto\xeehd\xd3\xca3m\xd8\x06y\xbb\x87\xae\x8a\bxg\x83&\xea\xc9\x00\x00\x00\u07d4\xf1\x1e\x01\u01e9\xd1$\x99\x00_M\xaew\x16\tZ4\x17bw\x89\x15\xaf\x1dx\xb5\x8c@\x00\x00\u07d4\xf1;\b0\x93\xbaVN-\xc61V\x8c\xf7T\r\x9a\x0e\xc7\x19\x89lj\xccg\u05f1\xd4\x00\x00\u07d4\xf1O\x0e\xb8m\xb0\xebhu?\x16\x91\x8e]K\x80t7\xbd>\x89\n\u05ce\xbcZ\xc6 \x00\x00\u07d4\xf1Qx\xff\xc4:\xa8\a\x0e\xce2~\x93\x0f\x80\x9a\xb1\xa5O\x9d\x89\n\xb6@9\x12\x010\x00\x00\u07d4\xf1V\xdc\v*\x98\x1e[U\xd3\xf2\xf0;\x814\xe31\u06ed\xb7\x89\x05k\xc7^-c\x10\x00\x00\u07d4\xf1]\x9dZ!\xb1\x92\x9ey\x03q\xa1\u007f\x16\xd9_\fie\\\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\xf1^\x18,O\xbb\xady\xbd\x934\"B\xd4\xdc\xcf+\xe5\x89%\x89i*\xe8\x89p\x81\xd0\x00\x00\u07d4\xf1bM\x98\ve3o\xea\u0166\xd5A%\x00\\\xfc\xf2\xaa\u02c9lk\x93[\x8b\xbd@\x00\x00\u07d4\xf1g\xf5\x86\x8d\xcfB3\xa7\x83\x06\th,\xaf-\xf4\xb1\xb8\a\x89\x81\xe5B\xe1\xa78?\x00\x00\u07d4\xf1m\xe1\x89\x1d\x81\x96F\x13\x95\xf9\xb16&[;\x95F\xf6\xef\x89\x01\xb2\x8e\x1f\x98\xbb\u0380\x00\u07d4\xf1z\x92\xe06\x1d\xba\xce\xcd\xc5\xde\r\x18\x94\x95Z\xf6\xa9\xb6\x06\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\xf1z\xdbt\x0fE\u02fd\xe3\tN~\x13qo\x81\x03\xf5c\xbd\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\xf1\x8b\x14\xcb\xf6iC6\xd0\xfe\x12\xac\x1f%\xdf-\xa0\xc0]\xbb\x89\xd8\xd4`,&\xbfl\x00\x00\u07d4\xf1\x9b98\x9dG\xb1\x1b\x8a,?\x1d\xa9\x12M\xec\xff\xbe\xfa\xf7\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\xf1\x9f\x195\b9>M*\x12{ \xb2\x03\x1f9\xc8%\x81\u0189\xbd\xbdz\x83\xbd/l\x00\x00\u07d4\xf1\xa1\xf3 @yd\xfd<\x8f.,\u0224X\r\xa9O\x01\xea\x89ll!wU|D\x00\x00\u07d4\xf1\xb4\xec\xc65%\xf7C,=\x83O\xfe+\x97\x0f\xbe\xb8r\x12\x89\xa2\xa2@h\xfa\u0340\x00\x00\u07d4\U000753ef\xfa\x87\x94\xf5\n\xf8\xe8\x83\t\u01e6&TU\xd5\x1a\x8963\x03\"\xd5#\x8c\x00\x00\u07d4\xf1\xc8\u0129A\xb4b\x8c\rl0\xfd\xa5dR\u065c~\x1bd\x89N\x8c\xea\x1e\xdeu\x04\x00\x00\u07d4\xf1\xda@so\x99\xd5\xdf;\x06\x8a]t_\xaf\xc6F?\u0271\x89\x06\x96\xca#\x05\x8d\xa1\x00\x00\u07d4\xf1\u070a\xc8\x10B\xc6z\x9c<g\x92\xb20\xc4j\xc0\x16\xca\x10\x89\n\u05ce\xbcZ\xc6 \x00\x00\u07d4\xf1\xdfU\xdc\xc3J\x05\x10\x12\xb5u\u02d6\x8b\xc9\xc4X\xea\t\u0249\xd8\xd7&\xb7\x17z\x80\x00\x00\xe0\x94\xf1\xe9\x80\xc5Y\xa1\xa8\xe5\xe5\nG\xf8\xff\xfd\xc7s\xb7\xe0jT\x8a\x06_\xfb\xcd\xea\x04\xb7H\x00\x00\xe0\x94\xf1\xf3\x91\u0292\x80\x88\x17\xb7U\xa8\xb8\xf4\xe2\xca\b\xd1\xfd\x11\b\x8a\x01EB\xba\x12\xa37\xc0\x00\x00\xe0\x94\xf1\xf7f\xb0\xe4ms\xfc\xd4\xd5.zr\xe1\xb9\x19\f\xc62\xb3\x8a\x01\xb1\xaeMn.\xf5\x00\x00\x00\u07d4\xf2\x04\x952\xfdE\x8a\x83\xca\x1b\xff.\ubb36\xd5\xcac\xf4\xa4\x89\u010c\x99\x1d\xc1T\\\x80\x00\u07d4\xf2\x06\xd3(\xe4q\xd0\x11{$m*F\x19\x82w\t\xe9m\U000c98af=\xc0\x05CD\x00\x00\u07d4\xf2\f\x9a\x99\xb7GY\u05c2\xf2\\\x1c\xec\xa8\x02\xa2~\vCl\x89Z\x87\xe7\xd7\xf5\xf6X\x00\x00\xe0\x94\xf2\x12}T\x18\x8f\xed\xef\x0f3\x8a_8\xc7\xffs\xad\x9foB\x8a\x04<3\xc1\x93ud\x80\x00\x00\u07d4\xf2\x1341\xd1\u0663{\xa2\xf0v+\xc4\fZ\u030a\xa6\x97\x8e\x89lk\x93[\x8b\xbd@\x00\x00\xe0\x94\xf2\x15I\xbd\xd1Hy\x12\xf9\x00\xa7R=\xb5\xf7ba!\xbb\xa3\x8a\x02\x1e\x19\xe0\u027a\xb2@\x00\x00\u07d4\xf2\x18\xbd\x84\x8e\xe7\xf9\u04cb\xfd\xd1\xc4\xeb.\xd2Ij\xe40_\x89\x1b\x1a\xe4\xd6\xe2\xefP\x00\x00\u07d4\xf2$\xeb\x90\v7\xb4I\x0e\xeej\vd \xd8\\\x94}\x873\x894\x95tD\xb8@\xe8\x00\x00\u07d4\xf2)J\u06f6\xf0\xdc\xc7nc.\xbe\U0010ad1f\x12M\xbb\xa4\x89NC96\x00\xa7\xb1\x00\x00\u07d4\xf2/@x\xfe\xbb\xba\xa8\xb0\xe7\x8ed,\x8aB\xf3]C9\x05\x89lj\xccg\u05f1\xd4\x00\x00\u07d4\xf27\xef\x05&\x1c4\u05dc\xc2+\x86\r\xe0\xf1\u007fy<8`\x89\n\u05ce\xbcZ\xc6 \x00\x00\u07d4\xf2<{\f\xb8\xcdY\xb8+\u0610dJW\xda\xf4\f\x85\xe2x\x89\x02\xb6j\xaf\xe3&\xff\x00\x00\u07d4\xf2=\x01X\x9e\xb1-C\x9ftH\xffT0u)\U0005114d\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\xf2>\\c2!\xa8\xf76>e\x87\f\x9f(t$\u04a9`\x89J\xcfX\xe0rW\x10\x00\x00\u07d4\xf2B\u0684]B\u053fw\x9a\x00\xf2\x95\xb4\aP\xfeI\xea\x13\x8965\u026d\xc5\u07a0\x00\x00\u07d4\xf2RY\xa5\xc99\xcd%\x96l\x9bc\x03\xd3s\x1cS\u077cL\x89\n\u05ce\xbcZ\xc6 \x00\x00\u07d4\xf2^Lp\xbcFV2\u021eV%\xa82\xa7r/k\xff\xab\x89\xf3K\x82\xfd\x8e\x91 \x00\x00\u07d4\xf2k\xce\xdc\xe3\xfe\xad\u03a3\xbc>\x96\xeb\x10@\xdf\xd8\xff\u1809*\x03I\x19\u07ff\xbc\x00\x00\u07d4\xf2py%v\xf0]QD\x93\xff\xd1\xf5\xe8K\xecK-\xf8\x10\x8965\u026d\xc5\u07a0\x00\x00\u07d4\xf2s,\xf2\xc1;\x8b\xb8\xe7I*\x98\x8f_\x89\xe3\x82s\xdd\u0209 \x86\xac5\x10R`\x00\x00\xe0\x94\xf2t.hY\xc5i\xd5\xf2\x10\x83Q\xe0\xbfM\xca5*H\xa8\x8a\x02\x1e\x19\xe0\u027a\xb2@\x00\x00\u07d4\xf2\x81:d\xc5&]\x02\x025\u02dc1\x9bl\x96\xf9\x06\xc4\x1e\x89\x12\xf99\u025e\u06b8\x00\x00\u07d4\xf2\x87\xffR\xf4a\x11z\xdb>\x1d\xaaq\x93-\x14\x93\xc6_.\x89\xc5S%\xcat\x15\xe0\x00\x00\u07d4\xf2\xab\x11au\x02D\xd0\xec\xd0H\xee\r>Q\xab\xb1C\xa2\xfd\x89B\xfe+\x90ss\xbc\x00\x00\u07d4\xf2\xb4\xab,\x94'\xa9\x01^\xf6\xee\xff\xf5\xed\xb6\x019\xb7\x19\u0449&\u06d9*;\x18\x00\x00\x00\u07d4\xf2\xc0>*8\x99\x8c!d\x87`\xf1\xe5\xae~\xa3\a}\x85\"\x89\x8f?q\x93\xab\a\x9c\x00\x00\u0794\xf2\u0090N\x9f\xa6d\xa1\x1e\xe2VV\xd8\xfd,\xc0\u0665\"\xa0\x88\xb9\x8b\xc8)\xa6\xf9\x00\x00\u07d4\xf2\xc3b\xb0\xef\x99\x1b\xc8/\xb3nf\xffu\x93*\xe8\u0742%\x89\x04\x02\xf4\xcf\xeeb\xe8\x00\x00\u07d4\xf2\xd0\xe9\x86\xd8\x14\xea\x13\xc8\xf4f\xa0S\x8cS\u0712&Q\xf0\x89J\xcfX\xe0rW\x10\x00\x00\xe0\x94\xf2\u04775w$\xecL\x03\x18[\x87\x9bc\xf5~&X\x91S\x8a\x01EB\xba\x12\xa37\xc0\x00\x00\xe0\x94\xf2\xd5v<\xe0s\x12~,\xed\xdeo\xab\xa7\x86\xc7<\xa9AA\x8a\x01\xacB\x86\x10\x01\x91\xf0\x00\x00\xe0\x94\xf2\u055c\x89#u\x90s\xd6\xf4\x15\xaa\xf8\xeb\x06_\xf2\U000f614a\x01\xab,\xf7\xc9\xf8~ \x00\x00\u07d4\xf2\xe9\x9f\\\xbb\x83kz\xd3bGW\x1a0,\xbeKH\x1ci\x89j\xcb=\xf2~\x1f\x88\x00\x00\u07d4\xf2\xed>w%J\u02c3#\x1d\xc0\x86\x0e\x1a\x11$+\xa6'\u06c9kV\x05\x15\x82\xa9p\x00\x00\xe0\x94\xf2\xed\xde7\xf9\xa8\u00dd\u07a2My\xf4\x01WW\xd0k\xf7\x86\x8a\x15-\x02\xc7\xe1J\xf6\x80\x00\x00\u07d4\xf2\xef\xe9e`\xc9\xd9{r\xbd6DxC\x88\\\x1d\x90\xc21\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\xf2\xfb\xb6\u0607\xf8\xb8\xcc:\x86\x9a\xba\x84\u007f=\x1fd<S\u0589\xd8\xc9F\x00c\xd3\x1c\x00\x00\u07d4\xf3\x03Cg\xf8}$\xd3\a\u007f\xa9\xa2\u328b\f\xcb\x11\x04\xef\x8965\u026d\xc5\u07a0\x00\x00\u07d4\xf3\x03\u0568\x16\xaf\xfd\x97\xe8=\x9eM\xac/y\a+\xb0\t\x8f\x894\n\xad!\xb3\xb7\x00\x00\x00\u07d4\xf3\x15\x98f\u00bc\x86\xbb\xa4\x0f\x9ds\xbb\x99\xf1\xee\xe5{\xb9\u05c965\u026d\xc5\u07a0\x00\x00\u07d4\xf3\x16\xef\x1d\xf2\xffMl\x18\b\u06e6c\uc013iyh\xe0\x89aFMl\u0700\xf0\x00\x00\xe0\x94\xf3-%\xeb\x0e\xa2\xb8\xb3\x02\x8aLz\x15]\xc1\xaa\xe8exM\x8a\x015\x93\xa9)\u007f\xda\xd6\x00\x00\xe0\x94\xf32\xc0\xf3\xe0Z'\xd9\x12o\u0436A\xa8\xc2\xd4\x06\x06\b\xfd\x8a\x01\x0f\x1bb\xc4\xd9dN\x80\x00\xe0\x94\xf38E\x9f2\xa1Y\xb2=\xb3\n\xc35v\x9a\xb25\x1a\xa6<\x8a\x06ZM\xa2]0\x16\xc0\x00\x00\u07d4\xf3>\xfcc\x97\xaae\xfbS\xa8\xf0z\x0f\x89:\xae0\xe8\xbc\xee\x89|\xf28\x1fa\x9f\x15\x00\x00\u07d4\xf3@\x83\xec\xea8P\x17\xaa@\xbd\xd3^\xf7\xef\xfbL\xe7v-\x89\x15\xaf\x1dx\xb5\x8c@\x00\x00\u07d4\xf3F\xd7\u0792t\x1c\b\xfcX\xa6M\xb5[\x06-\xde\x01-\x14\x89\x0f\xffk\x1fv\x1em\x00\x00\xe0\x94\xf3U\xd3\xec\f\xfb\x90}\x8d\xbb\x1b\xf3FNE\x81(\x19\v\xac\x8a\x01\v\x04n\u007f\r\x80\x10\x00\x00\u07d4\xf3m\xf0/\xbd\x89`sG\xaf\xce)i\xb9\xc4#jX\xa5\x06\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\xf3s\xe9\u06ac\f\x86u\xf5;yz\x16\x0fo\xc04\xaek#\x89\x05k\xc7^-c\x10\x00\x00\u07d4\xf3{BeG\xa1d-\x8032H\x14\xf0\xed\xe3\x11O\xc2\x12\x89\x15\xbeat\xe1\x91.\x00\x00\u07d4\xf3{\xf7\x8cXu\x15G\x11\xcbd\r7\xeam(\xcf\xcb\x12Y\x89\n\u05ce\xbcZ\xc6 \x00\x00\xe0\x94\xf3\x82\xdfX1U\xd8T\x8f?\x93D\f\xd5\xf6\x8c\xb7\x9d`&\x8a8u}\x02\u007f\xc1\xfd\\\x00\x00\xe0\x94\xf3\x82\xe4\xc2\x04\x10\xb9Q\b\x9e\x19\xba\x96\xa2\xfe\xe3\xd9\x1c\xce~\x8a\x01\x11\xfaV\xee\u00a88\x00\x00\xe0\x94\xf3\x8al\xa8\x01hS~\x97M\x14\xe1\xc3\xd19\x90\xa4L,\x1b\x8a\x01EB\xba\x12\xa37\xc0\x00\x00\u07d4\xf3\x9a\x9dz\xa3X\x1d\xf0~\xe4'\x9a\xe6\xc3\x12\xef!\x036X\x89\xd8\xd7&\xb7\x17z\x80\x00\x00\u07d4\xf3\xb6h\xb3\xf1M\x92\x0e\xbc7\x90\x92\u06d8\x03\x1bg\xb2\x19\xb3\x89\n\xd6\xee\xdd\x17\xcf;\x80\x00\u07d4\U000fe679\x10<\xe7U\n\xa7O\xf1\xdb\x18\xe0\x9d\xfe2\xe0\x05\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\xf3\xc1\xab\u049d\xc5{A\xdc\x19-\x0e8M\x02\x1d\xf0\xb4\xf6\u0509\x97\xae\f\u07cf\x86\xf8\x00\x00\u07d4\xf3\xc4qm\x1e\xe5'\x9a\x86\xd0\x16:\x14a\x81\x81\xe1a6\u01c965\u026d\xc5\u07a0\x00\x00\xe0\x94\xf3\u030b\xcbU\x94e\xf8\x1b\xfeX;\u05eb\n#\x06E;\x9e\x8a\x04<3\xc1\x93ud\x80\x00\x00\u07d4\xf3\u0588\xf0k\xbd\xbfP\xf9\x93,AE\xcb\xe4\x8e\xcd\xf6\x89\x04\x89\x01\x15\x8eF\t\x13\xd0\x00\x00\u07d4\xf3\xdb\xcf\x13Z\u02dd\xee\x1aH\x9cY<\x02O\x03\u00bb\xae\u0389lk\x93[\x8b\xbd@\x00\x00\u07d4\xf3\xde_&\xefj\xde\xd6\xf0m;\x91\x13F\xeep@\x1d\xa4\xa0\x89\x13:\xb3}\x9f\x9d\x03\x00\x00\u07d4\xf3\xdfc\xa9q\x99\x93308;>\xd7W\v\x96\u0101#4\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\xf3\xe7OG\f}:?\x003x\x0fv\xa8\x9f>\xf6\x91\xe6\u02c9\xa3\xcf\xe61\xd1Cd\x00\x00\u07d4\xf3\xeb\x19H\xb9Q\xe2-\xf1ax)\xbf;\x8d\x86\x80\xeckh\x89\xd8\xd7&\xb7\x17z\x80\x00\x00\u07d4\xf3\xf1\xfa9\x18\xca4\xe2\xcf~\x84g\v\x1fM\x8e\xca\x16\r\xb3\x89$\xdc\xe5M4\xa1\xa0\x00\x00\u07d4\xf3\xf2O\u009e @?\xc0\xe8\xf5\xeb\xbbU4&\xf7\x82p\xa2\x89\x05k\xc7^-c\x10\x00\x00\u07d4\xf3\xfar5R\xa5\xd0Q.+b\xf4\x8d\xca{+\x81\x050[\x89\amA\xc6$\x94\x84\x00\x00\u07d4\xf3\xfeQ\xfd\xe3D\x13\xc73\x18\xb9\xc8T7\xfe~\x82\x0fV\x1a\x896b2\\\u044f\xe0\x00\x00\u07d4\xf4\x00\xf9=_\\~?\xc3\x03\x12\x9a\xc8\xfb\f/xd\a\xfa\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\xf4\v\x13O\xea\"\u01b2\x9c\x84W\xf4\x9f\x00\x0f\x9c\xdax\x9a\u06c9 \x86\xac5\x10R`\x00\x00\u07d4\xf4\x15W\xdf\u07f1\xa1\xbd\xce\xfe\xfe.\xba\x1e!\xfe\nJ\x99B\x89j\xcb=\xf2~\x1f\x88\x00\x00\u07d4\xf4\x17z\r\x85\u050b\x0e&B\x11\xce*\xa2\xef\xd3\xf1\xb4\u007f\b\x89\xc2\xcc\xca&\xb7\xe8\x0e\x80\x00\u07d4\xf4/\x90R1\xc7p\xf0\xa4\x06\xf2\xb7h\x87\u007f\xb4\x9e\xee\x0f!\x89\n\xad\xec\x98?\xcf\xf4\x00\x00\u07d4\xf42\xb9\u06ef\x11\xbd\xbds\xb6Q\x9f\xc0\xa9\x04\x19\x87q\xaa\u0189\b=lz\xabc`\x00\x00\u07d4\xf4=\xa3\xa4\xe3\xf5\xfa\xb1\x04\u029b\xc1\xa0\xf7\xf3\xbbJV\xf3Q\x89lj\xccg\u05f1\xd4\x00\x00\xe0\x94\xf4G\x10\x8b\x98\xdfd\xb5~\x87\x103\x88\\\x1a\xd7\x1d\xb1\xa3\xf9\x8a\x01v\xf4\x9e\xad4\x83P\x80\x00\u07d4\xf4O\x85Q\xac\xe93r\a\x12\xc5\u0111\u0376\xf2\xf9Qsl\x89\xd8\xd7&\xb7\x17z\x80\x00\x00\u0794\xf4V\x05Z\x11\xab\x91\xfff\x8e.\xc9\"\x96\x1f*#\xe3\xdb%\x88\xfc\x93c\x92\x80\x1c\x00\x00\u07d4\xf4V\xa7[\xb9\x96U\xa7A,\xe9}\xa0\x81\x81m\xfd\xb2\xb1\xf2\x89\n\u05ce\xbcZ\xc6 \x00\x00\u07d4\xf4[\x1d\xcb.A\xdc'\xff\xa0$\u06ad\xf6\x19\xc1\x11u\xc0\x87\x89\x01\x11du\x9f\xfb2\x00\x00\u07d4\xf4c\xa9\f\xb3\xf1>\x1f\x06CB66\xbe\xab\x84\xc1#\xb0m\x89\x02+\x1c\x8c\x12'\xa0\x00\x00\u07d4\xf4h\x90n~\xdffJ\xb0\u063e=\x83\xebz\xb3\xf7\xff\xdcx\x89\\(=A\x03\x94\x10\x00\x00\u07d4\xf4i\x80\u3929\u049ajn\x90`E7\xa3\x11K\xcb(\x97\x89\x1b\x1a\xe4\xd6\xe2\xefP\x00\x00\u07d4\xf4kk\x9c|\xb5R\x82\x9c\x1d=\xfd\x8f\xfb\x11\xaa\xba\xe7\x82\xf6\x89\x01#n\xfc\xbc\xbb4\x00\x00\u07d4\xf4v\xe1&\u007f\x86$|\xc9\b\x81o.z\xd58\x8c\x95-\xb0\x89\xd8\xd7&\xb7\x17z\x80\x00\x00\u07d4\xf4v\xf2\xcbr\b\xa3.\x05\x1f\xd9N\xa8f)\x92c\x82\x87\xa2\x89\x05k\xc7^-c\x10\x00\x00\xe0\x94\xf4{\xb14\xda0\xa8\x12\xd0\x03\xaf\x8d\u0338\x88\xf4K\xbfW$\x8a\x01\x19Y\xb7\xfe3\x95X\x00\x00\u07d4\xf4\x83\xf6\a\xa2\x1f\xcc(\x10\n\x01\x8cV\x8f\xfb\xe1@8\x04\x10\x8965\u026d\xc5\u07a0\x00\x00\u07d4\xf4\x8e\x1f\x13\xf6\xafM\x84\xb3q\xd7\xdeK'=\x03\xa2c'\x8e\x89 \x86\xac5\x10R`\x00\x00\xe0\x94\xf4\x9cG\xb3\xef\xd8knj[\xc9A\x8d\x1f\x9f\xec\x81Ki\xef\x8a\x04<3\xc1\x93ud\x80\x00\x00\xe0\x94\xf4\x9fo\x9b\xaa\xbc\x01\x8c\x8f\x8e\x11\x9e\x01\x15\xf4\x91\xfc\x92\xa8\xa4\x8a\x02\x1e\x19\xe0\u027a\xb2@\x00\x00\u07d4\xf4\xa3g\xb1f\u0499\x1a+\xfd\xa9\xf5dc\xa0\x9f%,\x1b\x1d\x89j\xcb=\xf2~\x1f\x88\x00\x00\u07d4\xf4\xa5\x1f\xceJ\x1d[\x94\xb0q\x83\x89\xbaNx\x14\x13\x9c\xa78\x89\x10CV\x1a\x88)0\x00\x00\u07d4\xf4\xa9\xd0\f\xef\xa9{zX\xef\x94\x17\xfcbg\xa5\x06\x909\xee\x89\x01.\x89(\u007f\xa7\x84\x00\x00\u07d4\xf4\xaa\xa3\xa6\x16>7\x06W{I\xc0v~\x94\x8ah\x1e\x16\xee\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\xf4\xb1bn$\xf3\v\xca\xd9'<R\u007f\xccqK]\x00{\x8f\x89\n\u05ce\xbcZ\xc6 \x00\x00\xe0\x94\xf4\xb4\x91\x00uwr\xf3<\x17{\x9av\xba\x95\"l\x8f=\u060a\x01k5-\xa5\xe0\xed0\x00\x00\xe0\x94\xf4\xb6\xcd\xcf\xcb$#\v3}w\r\xf6\x03M\xfb\xd4\xe1P?\x8a\x04\x05\xfd\xf7\u5bc5\xe0\x00\x00\u07d4\xf4\xb7Y\u030a\x1cu\xf8\bI\xeb\xbc\u0687\x8d\xc8\xf0\xd6m\xe4\x89\x15\xaf\x1dx\xb5\x8c@\x00\x00\u07d4\xf4\xbajF\xd5Q@\xc49\xcb\xcf\al\xc6W\x13bb\xf4\xf8\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\xf4\xd6z\x90D\xb45\xb6n\x89w\xff9\xa2\x8d\u013dSr\x9a\x89\n\u05ce\xbcZ\xc6 \x00\x00\u07d4\xf4\xd9vd\xccN\xec\x9e\xdb\xe7\xfa\t\xf4u\nf;P}y\x89\xd8\xd7&\xb7\x17z\x80\x00\x00\xe0\x94\xf4\xdc{\xa8T\x80\xbb\xb3\xf55\xc0\x95h\xaa\xa3\xafo7!\u018a\x01\x87\x1f\xb60~5\xe5\x00\x00\xe0\x94\xf4\xeb\xf5\v\xc7\xe5O\x82\u9e7d$\xba\xef)C\x8e%\x9c\xe6\x8a\x02\x1e\x19\xe0\u027a\xb2@\x00\x00\u07d4\xf4\uc397\xa2\n\xa5\xf8\xdd oU ~\x06\xb8\x13\xdf,\xc0\x89\n\u05ce\xbcZ\xc6 \x00\x00\u07d4\xf4\ud10e\xc9as\x9c,~5/C[\xa7\n|\xd5\xdb8\x89j\xcb=\xf2~\x1f\x88\x00\x00\u07d4\xf4\xfcM9\xbc\f,@h\xa3m\xe5\x0eJ\xb4\xd4\xdb~4\n\x89\x01`7\u07c7\xefj\x00\x00\xe0\x94\xf5\x04\x94:\xaf\x16yn\v4\x1b\xbc\xdf!\xd1\x1c\u0146\xcd\u044a\x01\xe7\xe4\x17\x1b\xf4\u04e0\x00\x00\u07d4\xf5\x06\x1e\xe2\xe5\xee&\xb8\x15P6w\x13\x0e\x1d\xe0zR\xdb\a\x89\x05k\xc7^-c\x10\x00\x00\u07d4\xf5\tU~\x90\x18?\xbf\x0f\x06Q\xa7\x86H{\xccB\x8b\xa1u\x89\n\x84Jt$\xd9\xc8\x00\x00\xe0\x94\xf5\n\xbb\u052aE\xd3\xeb\x88QTe\xa8\xba\v1\x0f\u0675!\x8a\x01je\x02\xf1Z\x1eT\x00\x00\u07d4\xf5\n\xe7\xfa\xb4\u03f5\xa6F\xee\x04\u03ad\xf9\xbf\x9d\u0568\xe5@\x89\xd8\xd6|/X\x95H\x00\x00\u07d4\xf5\f\xba\xfd9~\xddUl\x06x\x98\x8c\xb2\xaf\\&\x17\u0889&\xd0~\xfex+\xb0\x00\x00\xe0\x94\xf5\x1f\xde\xd8\n\xcbP(\x90\xe8sit\x1f7\"QL\xef\xff\x8a\x04<4V\xca<m\x11\x00\x00\xe0\x94\xf5*X\x82\xe8\x92}\x94K5\x9b&6k\xa2\xb9\xca\u03fa\xe8\x8a\x05KA\xce/\xe6;\xa8\x00\x00\xe0\x94\xf5,\nxw4_\xe0\xc23\xbb\x0f\x04\xfdj\xb1\x8bo\x14\xba\x8aT\xcb\xe5Y\x89\xf3\x8d\xe0\x00\x00\u07d4\xf5C~\x15\x80\x90\xb2\xa2\u058f\x82\xb5JXd\xb9]\xd6\xdb\xea\x89\xd9l\x16p;+\xfe\x00\x00\xe0\x94\xf5L\x19\xd9\xef8s\xbf\xd1\xf7\xa6\"\xd0-\x86$\x9a2\x8f\x06\x8a\t`\xae\x12z\xf3/\xb2\x80\x00\u07d4\xf5P\x01x\u02d9\x8f\x12d\x17\x83\x1a\b\xc2\u05eb\xff\xf6\xab_\x89F\xf4\xf4\xa5\x87Z\x9f\x80\x00\u07d4\xf5SH\x15\xdcc^\xfa\\\xc8K*\xc74r>!\xb2\x93r\x89U\xa6\xe7\x9c\xcd\x1d0\x00\x00\u07d4\xf5U\xa2{\xb1\xe2\xfdN,\u01c4\xca\ue493\x9f\xc0n/\u0249lk\x93[\x8b\xbd@\x00\x00\u07d4\xf5X\xa2\xb2\xdd&\u0755\x93\xaa\xe0E1\xfd<<\u00c5Kg\x89\n\xbb\xcdN\xf3wX\x00\x00\u07d4\xf5`H\xdd!\x81\u0523od\xfc\xec\xc6!T\x81\xe4*\xbc\x15\x89\n\u05ce\xbcZ\xc6 \x00\x00\u07d4\xf5dB\xf6\x0e!i\x13\x95\u043f\xfa\xa9\x19M\xca\xff\x12\u2dc9\x0e\x189\x8ev\x01\x90\x00\x00\u07d4\xf5yqJE\xeb\x8fR\xc3\xd5{\xbd\xef\xd2\xc1[./\x11\u07c9T\x91YV\xc4\t`\x00\x00\u07d4\xf5\x93\xc6R\x85\xeek\xbdf7\U000fe3c9\xad@\u0509\xf6U\x89\xa2\xa1]\tQ\x9b\xe0\x00\x00\u07d4\xf5\x98\xdb.\t\xa8\xa5\xee}r\r+\\C\xbb\x12m\x11\xec\u0089\n\u05ce\xbcZ\xc6 \x00\x00\xe0\x94\xf5\x9d\xab\x1b\xf8\xdf\x112~a\xf9\xb7\xa1KV:\x96\xec5T\x8a\x01EB\xba\x12\xa37\xc0\x00\x00\xe0\x94\xf5\x9f\x9f\x02\xbb\u024e\xfe\t~\xab\xb7\x82\x10\x97\x90!\x89\x8b\xfd\x8a\x02\x1e\x17\x1a>\xc9\xf7,\x00\x00\u07d4\xf5\xa5E\x9f\xcd\xd5\xe5\xb2s\x83\r\xf8\x8e\xeaL\xb7}\xda\u07f9\x89\x04\t\xe5+H6\x9a\x00\x00\u07d4\xf5\xa7gj\xd1H\xae\x9c\x1e\xf8\xb6\xf5\xe5\xa0\xc2\xc4s\xbe\x85\v\x89\n\u05ce\xbcZ\xc6 \x00\x00\u07d4\xf5\xb0h\x98\x9d\xf2\x9c%5w\xd0@Z\xden\x0eu(\xf8\x9e\x89WG=\x05\u06ba\xe8\x00\x00\u07d4\xf5\xb6\xe9\x06\x1aN\xb0\x96\x16\aw\xe2gb\xcfH\xbd\u0635]\x89\r\xc5_\xdb\x17d{\x00\x00\u07d4\xf5\xcf\xfb\xbabN~\xb3!\xbc\x83\xc6\f\xa6\x81\x99\xb4\xe3fq\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\xf5\xd1ER\xb1\xdc\xe0\xd6\xdc\x1f2\r\xa6\xff\u02231\xcdo\f\x89Hz\x9a0E9D\x00\x00\xe0\x94\xf5\xd6\x1a\xc4\u0295G^[{\xff\xd5\xf2\xf6\x90\xb3\x16u\x96\x15\x8a\x06\x92\xae\x88\x97\b\x1d\x00\x00\x00\u07d4\xf5\xd9\xcf\x00\xd6X\xddEQzH\xa9\xd3\xf5\xf63T\x1aS=\x89\x06O_\xdfIOx\x00\x00\u07d4\xf5\xea\xdc\xd2\u0478ez\x12\x1f3\xc4X\xa8\xb1>v\xb6U&\x89\r\x8b\x0fZZ\xc2J\x00\x00\u07d4\xf6\a\xc2\x15\r>\x1b\x99\xf2O\xa1\xc7\xd5@\xad\xd3\\N\xbe\x1e\x89\xa7\xf1\xaa\a\xfc\x8f\xaa\x00\x00\u07d4\xf6\v\xd75T>k\xfd.\xa6\xf1\x1b\xffbs@\xbc\x03Z#\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\xf6\f\x1bE\xf1d\xb9X\x0e 'Z\\9\xe1\xd7\x1e5\xf8\x91\x89lk\x93[\x8b\xbd@\x00\x00\xe0\x94\xf6\x0fb\xd797\x95?\xef5\x16\x9e\x11\xd8r\xd2\xea1~\xec\x8a\x01!\xeah\xc1\x14\xe5\x10\x00\x00\u07d4\xf6\x12\x83\xb4\xbd\x85\x04\x05\x8c\xa3`\u94d9\x9bb\xcb\xc8\xcdg\x89\r\xd2\xd5\xfc\xf3\xbc\x9c\x00\x00\u07d4\xf6\x17\xb9g\xb9\xbdH_v\x95\xd2\xefQ\xfbw\x92\u0618\xf5\x00\x89\x1b\x1a\xe4\xd6\xe2\xefP\x00\x00\u07d4\xf6\x18\u0671\x04A\x14\x80\xa8c\xe6#\xfcU#-\x1aOH\xaa\x89\x0eh\x9emD\xb1f\x80\x00\u07d4\xf6\"\u5126b>\xaa\xf9\x9f+\xe4\x9eS\x80\xc5\xcb\xcf\\\u0609\n\u05ce\xbcZ\xc6 \x00\x00\u07d4\xf62\xad\xffI\r\xa4\xb7-\x126\xd0KQ\x0ft\xd2\xfa\xa3\u0349K\xe4\xe7&{j\xe0\x00\x00\u07d4\xf69\xac1\u069fg'\x1b\xd1\x04\x02\xb7eN\\\xe7c\xbdG\x89\x15\xaf\x0fB\xba\xf9&\x00\x00\u07d4\xf6:W\x9b\xc3\xea\u00a9I\x04\x10\x12\x8d\xbc\xeb\xe6\xd9\u0782C\x89P\xc5\xe7a\xa4D\b\x00\x00\u07d4\xf6E\xdd|\x89\x00\x93\xe8\xe4\u022a\x92\xa6\xbb55\"\xd3\u0718\x89\aC\x9f\xa2\t\x9eX\x00\x00\xe0\x94\xf6H\xea\x89\xc2u%q\x01r\x94Ny\xed\xff\x84x\x03\xb7u\x8a\x15-\x02\xc7\xe1J\xf6\x80\x00\x00\u07d4\xf6JJ\xc8\xd5@\xa9(\x9ch\xd9`\xd5\xfb|\xc4Zw\x83\x1c\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\xf6N\xcf!\x17\x93\x1cmSZ1\x1eO\xfe\xae\xf9\u0514\x05\xb8\x89\x90\xf54`\x8ar\x88\x00\x00\u07d4\xf6O\xe0\x93\x9a\x8d\x1e\xea*\x0e\u035a\x970\xfdyX\xe31\t\x89\x01\x1d\xe1\xe6\xdbE\f\x00\x00\u07d4\xf6V\x16\xbe\x9c\x8by~t\x15\"|\x918\xfa\xa0\x89\x17B\u05c9*\xd3s\xcef\x8e\x98\x00\x00\u07d4\xf6W\xfc\xbeh.\xb4\xe8\xdb\x15.\u03c9$V\x00\vQ=\x15\x89i*\xe8\x89p\x81\xd0\x00\x00\u07d4\xf6X\x19\xacL\xc1L\x13\u007f\x05\xddyw\xc7\xda\xe0\x8d\x1aJ\xb5\x89\x05\x87\x88\u02d4\xb1\xd8\x00\x00\u07d4\xf6{\xb8\xe2\x11\x8b\xbc\u0550'fn\xed\xf6\x94>\xc9\xf8\x80\xa5\x89\xd8\xd7&\xb7\x17z\x80\x00\x00\u07d4\xf6\x84d\xbfd\xf2A\x13V\xe4\xd3%\x0e\xfe\xfe\\P\xa5\xf6[\x89\x01\x15\x8eF\t\x13\xd0\x00\x00\u07d4\xf6\x86x[\x89r\va\x14_\ua017\x8dj\u030e\v\xc1\x96\x89\xd8\xd7&\xb7\x17z\x80\x00\x00\u07d4\xf6\x8c^3\xfa\x97\x13\x9d\xf5\xb2\xe68\x86\xce4\xeb\xf3\u45dc\x89\xb3\xfaAi\xe2\xd8\xe0\x00\x00\u07d4\xf6\xa8cWW\xc5\xe8\xc14\xd2\r\x02\x8c\xf7x\u03c6\t\xe4j\x89O\x1dw/\xae\xc1|\x00\x00\u07d4\xf6\xb7\x82\xf4\xdc\xd7E\xa6\xc0\xe2\xe00`\x0e\x04\xa2K%\xe5B\x89\x15\xaf\x1dx\xb5\x8c@\x00\x00\xe0\x94\xf6\xbc7\xb1\u04a3x\x8dX\x9bm\xe2\x12\xdc\x17\x13\xb2\xf6\u738a\x01\x0f\f\xf0d\xddY \x00\x00\u07d4\xf6\xc3\u010a\x1a\xc0\xa3G\x99\xf0M\xb8n\u01e9u\xfewh\xf3\x89j\xcb=\xf2~\x1f\x88\x00\x00\u07d4\xf6\xd2]?=\x84m#\x9fR_\xa8\xca\xc9{\xc45x\u06ec\x890\x92\u007ft\xc9\xde\x00\x00\x00\u07d4\xf6\xea\xacp2\u0512\xef\x17\xfd`\x95\xaf\xc1\x1dcOV\xb3\x82\x89\x1b\x1bk\u05efd\xc7\x00\x00\xe0\x94\xf6\xea\xd6}\xbf[~\xb13X\xe1\x0f6\x18\x9dS\xe6C\xcf\u03ca\bxg\x83&\xea\xc9\x00\x00\x00\u07d4\xf6\xf1\xa4C\t\x05\x1ck%\xe4}\xff\x90\x9b\x17\x9b\xb9\xabY\x1c\x89i*\xe8\x89p\x81\xd0\x00\x00\u07d4\xf7\x03(\xef\x97b_\xe7E\xfa\xa4\x9e\xe0\xf9\u052a;\r\xfbi\x8965\u026d\xc5\u07a0\x00\x00\u07d4\xf7\n\x99\x8aq{3\x8d\x1d\u0658T@\x9b\x1a3\x8d\ue930\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\xf7\rcz\x84\\\x06\xdbl\u0711\xe67\x1c\xe7\xc48\x8ab\x8e\x89\x01\x15\x8eF\t\x13\xd0\x00\x00\u07d4\xf7\x15R\x13D\x98\x92tK\xc6\x0f.\x04@\a\x88\xbd\x04\x1f\u0749\x03\x9f\xba\xe8\xd0B\xdd\x00\x00\xe0\x94\xf7\x1bE4\xf2\x86\xe40\x93\xb1\xe1^\xfe\xa7I\xe7Y{\x8bW\x8a\x16\x1c\x13\xd34\x1c\x87(\x00\x00\u07d4\xf74\xec\x03rM\xde\xe5\xbbRy\xaa\x1a\xfc\xf6\x1b\f\xb4H\xa1\x89\xe5\xbf,\u0270\x97\x80\x00\x00\u07d4\xf76\u0716v\x00\x128\x8f\xe8\x8bf\xc0n\xfeW\xe0\xd7\xcf\n\x89q\xd7Z\xb9\xb9 P\x00\x00\u07d4\xf7:\xc4l ;\xe1S\x81\x11\xb1Q\xec\x82 \u01c6\xd8AD\x89\x0f\xf77x\x17\xb8+\x80\x00\u07d4\xf7=\xd9\xc1B\xb7\x1b\xce\x11\xd0n0\xe7\xe7\xd02\xf2\uc71e\x89j\xcb=\xf2~\x1f\x88\x00\x00\u07d4\xf7A\x8a\xa0\xe7\x13\xd2H\"\x87v\xb2\xe7CB\"\xaeu\u3949lk\x93[\x8b\xbd@\x00\x00\u07d4\xf7Nn\x14S\x82\xb4\u06c2\x1f\xe0\xf2\u0643\x88\xf4V\t\u019f\x89\x05k\xc7^-c\x10\x00\x00\u07d4\xf7P\f\x16o\x8b\xea/\x824v\x06\xe5\x02K\xe9\xe4\xf4\u0399\x89\x01\x15\x8eF\t\x13\xd0\x00\x00\u07d4\xf7W\xfc\x87 \xd3\xc4\xfaRw\a^`\xbd\\A\x1a\xeb\xd9w\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\xf7[\xb3\x9cy\x97y\xeb\xc0J3m&\r\xa61F\xed\x98\u0409\x01Z\xf1\u05cbX\xc4\x00\x00\xe0\x94\xf7h\xf3!\xfdd3\xd9kO5M<\xc1e,\x172\xf5\u007f\x8a\x02\x1e\x19\xe0\u027a\xb2@\x00\x00\u07d4\xf7oi\xce\xe4\xfa\xa0\xa6;0\xae\x1ex\x81\xf4\xf7\x15ep\x10\x89\n\u05ce\xbcZ\xc6 \x00\x00\u07d4\xf7w6\x1a=\u062bb\xe5\xf1\xb9\xb0GV\x8c\xc0\xb5UpL\x8965\u026d\xc5\u07a0\x00\x00\u07d4\xf7|{\x84QI\xef\xba\x19\xe2a\xbc|u\x15y\b\xaf\xa9\x90\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\xf7\u007f\x95\x87\xffz-r\x95\xf1\xf5q\u0206\xbd3\x92jR|\x89lh\xcc\u041b\x02,\x00\x00\u07d4\xf7\x82X\xc1$\x81\xbc\xdd\u06f7*\x8c\xa0\xc0C\tra\xc6\u0149\x01\x15\x8eF\t\x13\xd0\x00\x00\u07d4\xf7\x98\xd1m\xa4\xe4`\xc4`\xcdH_\xae\x0f\xa0Y\x97\b\ub08965\u026d\xc5\u07a0\x00\x00\u07d4\xf7\xa1\xad\xe2\xd0\xf5)\x12=\x10U\xf1\x9b\x17\x91\x9fV!Ng\x89\x1b\x1a\xe4\xd6\xe2\xefP\x00\x00\u07d4\xf7\xac\xff\x93K\x84\xda\ti\xdc7\xa8\xfc\xf6C\xb7\xd7\xfb\xedA\x89lj\xccg\u05f1\xd4\x00\x00\u07d4\xf7\xb1Q\xcc^W\x1c\x17\xc7e9\xdb\xe9\x96L\xbbo\xe5\xdey\x89tq|\xfbh\x83\x10\x00\x00\u07d4\xf7\xb2\x9b\x82\x19\\\x88-\xabx\x97\u00ae\x95\xe7w\x10\xf5xu\x89w5Aa2\xdb\xfc\x00\x00\u07d4\xf7\xbcLD\x91\rZ\xed\xd6n\xd25U8\xa6\xb1\x93\xc3a\xec\x89\x05A\xde,-\x8db\x00\x00\u07d4\xf7\xc0\f\xdb\x1f\x02\x03\x10\u056c\xab{Ij\xaaD\xb7y\b^\x89Z\x87\xe7\xd7\xf5\xf6X\x00\x00\u07d4\xf7\xc1\xb4C\x96\x8b\x11{]\u0677UW/\xcd9\xca^\xc0K\x89\x18\xb9h\u0092\xf1\xb5\x00\x00\xe0\x94\xf7\xc5\x0f\x92*\xd1ka\xc6\u047a\xa0E\xed\x81h\x15\xba\u010f\x8a\x02\xa99j\x97\x84\xad}\x00\x00\u07d4\xf7\xc7\b\x01Pq\xd4\xfb\n:*\t\xa4]\x15c\x96\xe34\x9e\x89\xa2\xa1]\tQ\x9b\xe0\x00\x00\u07d4\xf7\xcb\u06e6\xbel\xfeh\xdb\xc2<+\x0f\xf50\xee\x05\"o\x84\x89\x01\x15\x8eF\t\x13\xd0\x00\x00\u07d4\xf7\xd0\xd3\x10\xac\xea\x18@a8\xba\xaa\xbb\xfe\x05q\xe8\r\xe8_\x89Hz\x9a0E9D\x00\x00\u07d4\xf7\u05ef LV\xf3\x1f\xd9C\x98\xe4\r\xf1\x96K\u063f\x12<\x89\b!\xd2!\xb5)\x1f\x80\x00\u07d4\xf7\xdc%\x11\x96\xfb\u02f7|\x94}|\x19F\xb0\xffe\x02\x1c\xea\x8965\u026d\xc5\u07a0\x00\x00\xe0\x94\xf7\xe4Z\x12\xaaq\x1cp\x9a\xce\xfe\x95\xf3;xa-*\xd2*\x8a\x0e\x06U\xe2\xf2k\xc9\x18\x00\x00\u07d4\xf7\xf4\x89\x8cLRm\x95_!\xf0U\xcbnG\xb9\x15\xe5\x19d\x89|\b`\xe5\xa8\r\xc0\x00\x00\u07d4\xf7\xf9\x1ez\xcb[\x81)\xa3\x06\x87|\xe3\x16\x8eoC\x8bf\xa1\x89\t\x8a}\x9b\x83\x14\xc0\x00\x00\u07d4\xf7\xfcE\xab\xf7oP\x88\xe2\u5d68\xd12\xf2\x8aMN\xc1\xc0\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\xf8\x06:\xf4\xcc\x1d\xd9a\x9a\xb5\u063f\xf3\xfc\xd1\xfa\xa8H\x82!\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\xf8\bnBf\x1e\xa9)\xd2\u0761\xablt\x8c\xe3\x05]\x11\x1e\x8965\u026d\xc5\u07a0\x00\x00\xe0\x94\xf8\bw\x86\xb4-\xa0N\xd6\xd1\xe0\xfe&\xf6\xc0\xee\xfe\x1e\x9fZ\x8a\x02\x1e\x19\xe0\u027a\xb2@\x00\x00\u07d4\xf8\r6\x19p/\xa5\x83\x8cH9\x18Y\xa89\xfb\x9c\xe7\x16\x0f\x89l\a\xa7\u0471np\x00\x00\u07d4\xf8\x14y\x9fm\xdfM\xcb)\xc7\xee\x87\x0eu\xf9\xcc-52m\x8965\u026d\xc5\u07a0\x00\x00\u07d4\xf8\x15\xc1\n\x03-\x13\xc3K\x89v\xfan;\xd2\xc9\x13\x1a\x8b\xa9\x89Hz\x9a0E9D\x00\x00\u07d4\xf8\x16\"\xe5WW\xda\xeafu\x97]\xd958\xda}\x16\x99\x1e\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\xf8$\xee3\x1eJ\xc3\xccXv\x939[W\xec\xf6%\xa6\xc0\u0089V\xc9]\xe8\xe8\xca\x1d\x00\x00\u07d4\xf8'\xd5n\xd2\xd3' \u052b\xf1\x03\xd6\xd0\xefM;\xcdU\x9b\x89\x01l\x80\x06W\x91\xa2\x80\x00\u07d4\xf8)\x85\x91R>P\xb1\x03\xf0\xb7\x01\xd6#\xcb\xf0\xf7EV\xf6\x89\n\u05ce\xbcZ\xc6 \x00\x00\u07d4\xf8H\xfc\xe9\xaba\x1c}\x99 n#\xfa\u019a\u0508\xb9O\xe1\x89\x02\xa1\x12\x9d\t6r\x00\x00\u07d4\xf8O\t\n\xdf?\x8d\xb7\u1533P\xfb\xb7u\x00i\x9ff\xfd\x89j\xcb=\xf2~\x1f\x88\x00\x00\u07d4\xf8Q\xb0\x10\xf63\xc4\n\xf1\xa8\xf0js\ubeabe\az\xb5\x89\xee\x86D/\xcd\x06\xc0\x00\x00\u07d4\xf8X\x17\x1a\x04\xd3W\xa1;IA\xc1n~U\xdd\u0514\x13)\x89\x02F\xa5!\x8f*\x00\x00\x00\u07d4\xf8[\xab\x1c\xb3q\x0f\xc0_\xa1\x9f\xfa\xc2.gR\x1a\v\xa2\x1d\x89l\x955\u007f\xa6\xb3l\x00\x00\u07d4\xf8j>\xa8\a\x1fp\x95\xc7\u06ca\x05\xaePz\x89)\u06f8v\x89\x126\xef\xcb\u02f3@\x00\x00\u07d4\xf8pL\x16\xd2\xfd[\xa3\xa2\xc0\x1d\x0e\xb2\x04\x84\xe6\xec\xfa1\t\x89\n\u05ce\xbcZ\xc6 \x00\x00\u07d4\xf8p\x99_\xe1\xe5\"2\x1duC7\xa4\\\f\x9d{8\x95\x1c\x89\x01\x15\x8eF\t\x13\xd0\x00\x00\u07d4\xf8s\xe5ze\xc9;n\x18\xcbu\xf0\xdc\a}[\x893\xdc\\\x89\n\xad\xec\x98?\xcf\xf4\x00\x00\u07d4\xf8ua\x9d\x8a#\xe4]\x89\x98\u0444\u0500\xc0t\x89p\x82*\x89\xd8\xd7&\xb7\x17z\x80\x00\x00\u07d4\xf8{\xb0{(\x9d\xf70\x1eT\xc0\xef\xdaj,\xf2\x91\xe8\x92\x00\x89K\xe4\xe7&{j\xe0\x00\x00\u0794\xf8\x89\x00\xdbsyU\xb1Q\x9b\x1a}\x17\n\x18\x86L\xe5\x90\xeb\x88\xfc\x93c\x92\x80\x1c\x00\x00\u07d4\xf8\x8bX\xdb7B\vFL\v\xe8\x8bE\xee+\x95)\x0f\x8c\xfa\x89\x02+\x1c\x8c\x12'\xa0\x00\x00\u07d4\xf8\x96+u\xdb]$\xc7\xe8\xb7\xce\xf1\x06\x8c>g\u03bb0\xa5\x89\x0f-\xc7\xd4\u007f\x15`\x00\x00\u07d4\xf8\xa0e\xf2\x87\xd9\x1dw\xcdbj\xf3\x8f\xfa\"\r\x9bU*+\x89g\x8a\x93 b\xe4\x18\x00\x00\u07d4\xf8\xa4\x9c\xa29\f\x1fm\\\x0ebQ;\a\x95qt?|\u0189\xa2\xa1]\tQ\x9b\xe0\x00\x00\u07d4\xf8\xa5\f\xee.h\x8c\xee\u3b24\u0522\x97%\xd4\a,\u0103\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\xf8\xacJ9\xb5<\x110x \x97;D\x13e\xcf\xfeYof\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\xf8\xae\x85{g\xa4\xa2\x89:?\xbe|z\x87\xff\x1c\x01\u01a6\xe7\x89\xd8\xd7&\xb7\x17z\x80\x00\x00\u07d4\xf8\xbf\x9c\x04\x87NZw\xf3\x8fL8R~\x80\xc6v\xf7\xb8\x87\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\xf8\xc7\xf3J8\xb3\x18\x01\xdaC\x064w\xb1+'\xd0\xf2\x03\xff\x89\x1a\u04ba\xbao\xefH\x00\x00\u07d4\xf8\xca3l\x8e\x91\xbd \xe3\x14\xc2\v-\xd4`\x8b\x9c\x8b\x94Y\x89-\u071b\u0173,x\x00\x00\u07d4\xf8\xd1t$\xc7g\xbe\xa3\x12\x05s\x9a+W\xa7'r\x14\uef89\x02F\xdd\xf9yvh\x00\x00\u07d4\xf8\xd5-\xcc_\x96\xcc(\x00{>\u02f4\t\xf7\xe2*dl\xaa\x89\b\x16\x90\xe1\x81(H\x00\x00\u07d4\xf8\xdc\xe8g\xf0\xa3\x9c[\xef\x9e\xeb\xa6\t\"\x9e\xfa\x02g\x8bl\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\xf8\xf2&\x14*B\x844\xab\x17\xa1\x86J%\x97\xf6J\xab/\x06\x89\tY\x8b/\xb2\xe9\xf2\x80\x00\u07d4\xf8\xf6d^\r\xeedK=\xad\x81\xd5q\uf6ef\x84\x00!\xad\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\xf9\x01\xc0\x0f\xc1\u06c8\xb6\x9cK\xc3%+\\\xa7\x0e\xa6\xee\\\xf6\x89\x15\xaf\x1dx\xb5\x8c@\x00\x00\u07d4\xf9=[\xcb\x06D\xb0\xcc\xe5\xfc\u0763C\xf5\x16\x8f\xfa\xb2\x87}\x89\vb\a\xb6}&\xf9\x00\x00\u07d4\xf9W\x0e\x92L\x95\u07bbpa6\x97\x92\xcf.\xfe\u00a8-^\x89\x01\x15\x8eF\t\x13\xd0\x00\x00\u07d4\xf9d \x86\xb1\xfb\xaea\xa6\x80M\xbe_\xb1^\xc2\u04b57\xf4\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\xf9d\x88i\x85\x90\xdc;,UVB\xb8q4\x8d\xfa\x06z\u0549\x1b\x1a\xe4\xd6\xe2\xefP\x00\x00\u07d4\xf9d\u064d(\x170\xba5\xb2\xe3\xa3\x14yn{B\xfe\xdfg\x89S\xb0\x87`\x98\xd8\f\x00\x00\u07d4\xf9e\ri\x89\xf1\x99\xab\x1c\xc4ycm\xed0\xf2A\x02\x1fe\x89.\x14\x1e\xa0\x81\xca\b\x00\x00\xe0\x94\xf9h\x83X$Y\x90\x8c\x82v'\xe8o(\xe6F\xf9\xc7\xfcz\x8a\x01\u0127\x877\xcd\u03f8\x00\x00\u07d4\xf9kL\x00voSsj\x85t\xf8\"\xe6GL/!\xda-\x89\x15\xaf\x1dx\xb5\x8c@\x00\x00\u07d4\xf9r\x9dH(,\x9e\x87\x16m^\xef-\x01\xed\xa9\xdb\xf7\x88!\x89\x05k\x83\xdd\xc7(T\x80\x00\u07d4\xf9v~N\xcbJY\x80Ru\b\u05fe\xc3\xd4^Ld\x9c\x13\x89g\x8a\x93 b\xe4\x18\x00\x00\xe0\x94\xf9x\xb0%\xb6B3U\\\xc3\xc1\x9a\xda\u007fA\x99\xc94\x8b\xf7\x8aT\xb4\v\x1f\x85+\xda\x00\x00\x00\u07d4\xf9{V\xeb\u0577z\xbc\x9f\xba\u02eb\u0514\xb9\xd2\xc2!\xcd\x03\x89j\xcb=\xf2~\x1f\x88\x00\x00\u07d4\xf9\x81\x1f\xa1\x9d\xad\xbf\x02\x9f\x8b\xfeV\x9a\xdb\x18\"\x8c\x80H\x1a\x89\n\u05ce\xbcZ\xc6 \x00\x00\u07d4\xf9\x82Ps\fLa\xc5\u007f\x12\x985\xf2h\b\x94yEB\xf3\x89\xd8\xd7&\xb7\x17z\x80\x00\x00\xe0\x94\xf9\x894gr\x99^\xc1\x90o\xaf\xfe\xba*\u007f\xe7\u079ck\xab\x8a\x01je\x02\xf1Z\x1eT\x00\x00\u07d4\xf9\x98\xca4\x11s\nl\xd1\x0etU\xb0A\x0f\xb0\xf6\xd3\xff\x80\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\xf9\x9a\xeeDKW\x83\xc0\x93\xcf\xff\xd1\xc4c,\xf9<o\x05\f\x89\x15\xaf\x1dx\xb5\x8c@\x00\x00\u07d4\xf9\x9e\xee\xce9\xfa~\xf5\am\x85Pa8@\ty,\xf2\xe0\x89\x1b\x1a\xe4\xd6\xe2\xefP\x00\x00\u07d4\xf9\xa5\x9c<\xc5\xff\xac\xbc\xb6{\xe0\xfcrV\xf6L\x9b\x12|\xb4\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\xf9\xa9K\xd5a\x98\xda$^\xd0\x1d\x1ed0\xb2K'\b\xdc\xc0\x89(\xa7z\xfd\xa8~\xe5\x00\x00\u07d4\xf9\xb3x%\xf00s\xd3\x1e$\x93x\xc3\fy\\3\xf8:\xf2\x89\n\u066a\xbf\x8c\x9b\xfc\x00\x00\u07d4\xf9\xb6\x17\xf7R\xed\xec\xae>\x90\x9f\xbb\x91\x1d/\x81\x92\xf8B\t\x89\x90\xf54`\x8ar\x88\x00\x00\u07d4\xf9\xbf\xb5\x9dS\x8a\xfcHt\xd4\xf5\x94\x1b\b\xc9s\x0e8\xe2K\x89\x02+\x1c\x8c\x12'\xa0\x00\x00\u07d4\xf9\xdd#\x90\b\x18/\xb5\x19\xfb0\xee\xdd \x93\xfe\xd1c\x9b\xe8\x89\x1b\x1a\xe4\xd6\xe2\xefP\x00\x00\u07d4\xf9\u07ba\xec\xb5\xf39\xbe\xeaH\x94\xe5 K\xfa4\r\x06\u007f%\x89ZB\x84Fs\xb1d\x00\x00\xe0\x94\xf9\xe3tG@lA!\x97\xb2\u2bbc\x00\x1dn0\u024c`\x8a\x01\xc4y\xbbCI\xc0\xee\x00\x00\u07d4\xf9\xe7\"/\xaa\xf0\xf4\xda@\xc1\u0124\x0607:\t\xbe\u05f6\x89\x9bO\u0730\x94V$\x00\x00\u07d4\xf9\xec\xe0\"\xbc\xcd,\x924i\x11\xe7\x9d\xd5\x03\x03\xc0\x1e\x01\x88\x8965\u026d\xc5\u07a0\x00\x00\u07d4\xfa\x00\xc3v\xe8\x9c\x05\u81c1z\x9d\xd0t\x8d\x96\xf3A\xaa\x89\x89\x10M\r\x00\u04b7\xf6\x00\x00\u07d4\xfa\f\x1a\x98\x8c\x8a\x17\xad5(\xeb(\xb3@\x9d\xaaX\"_&\x89\n\u05ce\xbcZ\xc6 \x00\x00\xe0\x94\xfa\x10_\x1a\x11\xb6\xe4\xb1\xf5`\x12\xa2y\"\xe2\xac-\xa4\x81/\x8a\x02\x05\xb4\u07e1\xeetx\x00\x00\u07d4\xfa\x14/\xe4~\u0697\xe6P;8k\x18\xa2\xbe\xdds\u0335\xb1\x89.\x15:\xd8\x15H\x10\x00\x00\u07d4\xfa\x14\xb5f#J\xbe\xe70B\xc3\x1d!qq\x82\u02e1J\xa1\x89\x11\xc7\xea\x16.x \x00\x00\u07d4\xfa\x19\xd6\xf7\xa5\x0fO\a\x98\x93\xd1g\xbf\x14\xe2\x1d\x00s\u0456\x89\x1c\xbb:?\xf0\x8d\b\x00\x00\u07d4\xfa\x1f\x19q\xa7u\xc3PO\xefPy\xf6@\xc2\u013c\xe7\xac\x05\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\xfa'\x9b\xfd\x87g\xf9V\xbf\u007f\xa0\xbdV`\x16\x8d\xa7V\x86\xbd\x89\x90\xf54`\x8ar\x88\x00\x00\xe0\x94\xfa'\xccI\xd0\vl\x98s6\xa8u\xae9\xdaX\xfb\x04\x1b.\x8a\x02\x1e\x19\xe0\u027a\xb2@\x00\x00\xe0\x94\xfa(2\x99`=\x87X\xe8\u02b0\x82\x12],\x8f}DT)\x8a\x01[\xca\xcb\x1e\x05\x01\xae\x80\x00\u07d4\xfa+\xbc\xa1]?\u37ca2\x8e\x91\xf9\r\xa1Oz\xc6%=\x89\n\u05ce\xbcZ\xc6 \x00\x00\xe0\x94\xfa/\u049d\x03\xfe\xe9\xa0x\x93\xdf:&\x9fV\xb7/.\x1ed\x8a\x02\x1e\x19\xe0\u027a\xb2@\x00\x00\u07d4\xfa3U2\x85\xa9sq\x9a\r_\x95o\xf8a\xb2\u061e\xd3\x04\x89\x01\x15\x8eF\t\x13\xd0\x00\x00\u07d4\xfa:\fK\x90?n\xa5.\xa7\xab{\x88c\xb6\xa6\x16\xadfP\x89\x01\x15\x8eF\t\x13\xd0\x00\x00\u07d4\xfa:\x1a\xa4H\x8b5\x1a\xa7V\f\xf5\xeec\n/\xd4\\2\"\x89/\xa4~j\xa74\r\x00\x00\u07d4\xfaA\tq\xad\"\x9c06\xf4\x1a\u03c5/*\u0259(\x19P\x89\u0633\x11\xa8\xdd\xfa|\x00\x00\u07d4\xfaD\xa8U\xe4\x04\xc8m\f\xa8\xef3$%\x1d\xfb4\x9cS\x9e\x89T\"S\xa1&\xce@\x00\x00\xe0\x94\xfaR\x01\xfe\x13B\xaf\x110{\x91B\xa0A$<\xa9./\t\x8a 8\x11j:\xc0C\x98\x00\x00\xe0\x94\xfa`\x86\x8a\xaf\xd4\xffL\\W\x91K\x8e\u054bBWs\u07e9\x8a\x01\xcf\xe5\xc8\b\xf3\x9f\xbc\x00\x00\u07d4\xfag\xb6{O7\xa0\x15\t\x15\x11\x0e\xde\a;\x05\xb8S\xbd\xa2\x89#\x19\xba\x94sq\xad\x00\x00\u07d4\xfah\xe0\xcb>\xdfQ\xf0\xa6\xf2\x11\u0272\xcb^\a<\x9b\xff\xe6\x89\x0f\xc969(\x01\xc0\x00\x00\xe0\x94\xfaj7\xf0\x18\xe9yg\x93\u007f\xc5\xe8a{\xa1\u05c6\xdd_w\x8a\x04<0\xfb\b\x84\xa9l\x00\x00\u07d4\xfav\x06C[5l\xee%{\xd2\xfc\xd3\xd9\xea\xcb<\xd1\xc4\xe1\x89\x05k\xc7^-c\x10\x00\x00\xe0\x94\xfaz\xdff\v\x8d\x99\xce\x15\x93=|_\a/<\xbe\xb9\x9d3\x8a\x01@a\xb9\xd7z^\x98\x00\x00\u07d4\xfa\x86\xca'\xbf(T\u0648p\x83\u007f\xb6\xf6\xdf\xe4\xbfdS\xfc\x89\x11u~\x85%\xcf\x14\x80\x00\u07d4\xfa\x8c\xf4\xe6'i\x8c]W\x88\xab\xb7\x88\x04\x17\xe7P#\x13\x99\x89\xe6\x1a6\x96\xee\xf6\x10\x00\x00\u07d4\xfa\x8e;\x1f\x13C9\x00s}\xaa\xf1\xf6)\x9cH\x87\xf8[_\x89&\u009eG\u0104L\x00\x00\u07d4\xfa\x9e\xc8\xef\xe0\x86\x86\xfaX\xc1\x813Xr\xbai\x85`\ucac9lj\xccg\u05f1\xd4\x00\x00\u07d4\xfa\xad\x90]\x84|{#A\x8a\xee\xcb\xe3\xad\u06cd\xd3\xf8\x92J\x89j\xcb=\xf2~\x1f\x88\x00\x00\u07d4\xfa\xae\xba\x8f\xc0\xbb\xdaU<\xa7.0\xef=s.&\xe8 A\x89H\x8d(*\xaf\xc9\xf6\x80\x00\u07d4\xfa\xb4\x87P\r\xf2\x0f\xb8>\xbe\xd9\x16y\x1dV\x17r\xad\xbe\xbf\x89lkLM\xa6\u077e\x00\x00\u07d4\xfa\xc5\u0294u\x80x\xfb\xfc\xcd\x19\xdb5X\xda~\u8827h\x897(\xa6+\r\xcf\xf6\x00\x00\u07d4\xfa\xd9j\xb6\xacv\x8a\xd5\t\x94R\xacGw\xbd\x1aG\xed\u010f\x89\x05k\xc7^-c\x10\x00\x00\xe0\x94\xfa\xe7g\x19\xd9~\xacA\x87\x04(\xe9@'\x9d\x97\xddW\xb2\xf6\x8a\x14\u06f2\x19\\\xa2(\x90\x00\x00\u07d4\xfa\u8053pG\x89Zf\f\xf2)v\x0f'\xe6h(\xd6C\x89\t\xdd\xc1\xe3\xb9\x01\x18\x00\x00\u07d4\xfa\xe9,\x13p\xe9\u115a]\xf8;V\xd0\xf5\x86\xaa;@L\x89\x05\u0174\xf3\xd8C\x98\x00\x00\xe0\x94\xfa\xf5\xf0\xb7\xb6\xd5X\xf5\t\r\x9e\xa1\xfb-B%\x9cX`x\x8a\x01Z\xff\xb8B\fkd\x00\x00\xe0\x94\xfb\x12o\x0e\xc7i\xf4\x9d\xce\xfc\xa2\xf2\x00(dQX0\x84\xb8\x8a\x01\x0f\xcb\xc25\x03\x96\xbf\x00\x00\xe0\x94\xfb\x13^\xb1Z\x8b\xacr\xb6\x99\x154*`\xbb\xc0k~\a|\x8a\x04<3\xc1\x93ud\x80\x00\x00\u07d4\xfb\"<\x1e\"\xea\xc1&\x9b2\xee\x15jS\x85\x92.\xd3o\xb8\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\xfb7\xcfkO\x81\xa9\xe2\"\xfb\xa2.\x9b\xd2KP\x98\xb73\u03c9\x02\x1auJm\xc5(\x00\x00\u07d4\xfb8`\xf4\x12\x1cC.\xbd\xc8\xecj\x031\xb1\xb7\ty.\x90\x89 \x8c9J\xf1\u0208\x00\x00\u07d4\xfb9\x18\x9a\xf8v\xe7b\xc7\x1dl>t\x18\x93\xdf\"l\xed\u0589\xd8\xd7&\xb7\x17z\x80\x00\x00\u07d4\xfb:\v\rkjq\x8fo\xc0)*\x82]\xc9$z\x90\xa5\u0409\n\xd6\xdd\x19\x9e\x97[\x00\x00\xe0\x94\xfb?\xa1\xac\b\xab\xa9\xcc;\xf0\xfe\x9dH8 h\x8fe\xb4\x10\x8a\x06ZM\xa2]0\x16\xc0\x00\x00\u07d4\xfb?\xe0\x9b\xb86\x86\x15)\xd7Q\x8d\xa2v5\xf58PV\x15\x89K\xe3\x92\x16\xfd\xa0p\x00\x00\xe0\x94\xfbQ%\xbf\x0f^\xb0\xb6\xf0 \xe5k\xfc/\xdf=@,\t~\x8a\x01@a\xb9\xd7z^\x98\x00\x00\u07d4\xfbU\x18qL\xef\xc3m\x04\x86]\xe5\x91^\xf0\xffG\xdf\xe7C\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\xfb_\xfa\xa0\xf7aW&5x\x91GX\x18\x93\x9d 7\u03d6\x89\x01\x15\x8eF\t\x13\xd0\x00\x00\u07d4\xfbh\\\x15\xe49\x96^\xf6&\xbf\r\x83L\u0468\x9f+V\x95\x89\u0556{\xe4\xfc?\x10\x00\x00\u07d4\xfbtK\x95\x1d\tK1\x02b\xc8\xf9\x86\xc8`\u07da\xb1\xdee\x89\x02\xd1\xc5\x15\xf1\xcbJ\x80\x00\u07d4\xfby\xab\u06d2\\U\xb9\xf9\x8e\xfe\xefd\xcf\xc9\xeba\xf5\x1b\xb1\x89a@\xc0V\xfb\n\xc8\x00\x00\u07d4\xfb\x81\x13\xf9M\x91s\xee\xfdZ0s\xf5\x16\x80:\x10\xb2\x86\xae\x89\x04V9\x18$O@\x00\x00\u07d4\xfb\x84,\xa2\xc5\xef\x139\x17\xa26\xa0\u052c@i\x01\x10\xb08\x89\x10\x96\x9ab\xbe\x15\x88\x00\x00\u07d4\xfb\x91\xfb\x1aiUS\xf0\u018e!'m\xec\xf0\xb89\t\xb8m\x89\x05l\x006\x17\xafx\x00\x00\u07d4\xfb\x94s\xcfw\x125\n\x1f\xa09Rs\xfc\x80V\aR\xe4\xfb\x89\x06\xaf!\x98\xba\x85\xaa\x00\x00\xe0\x94\xfb\x94\x9cd\u007f\xdc\xfd%\x14\xc7\u054e1\xf2\x8aS-\x8cX3\x8a\x04<3\xc1\x93ud\x80\x00\x00\u07d4\xfb\xa5HmS\xc6\xe2@IBA\xab\xf8~C\xc7`\rA:\x89k\xbfaIIH4\x00\x00\u07d4\xfb\xb1a\xfe\x87_\t)\nK&+\xc6\x01\x10\x84\x8f\r\"&\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\xfb\xbb\xeb\u03fe#^W\xdd#\x06\xad\x1a\x9e\u0141\xc7\xf9\xf4\x8f\x89\x02+\x1c\x8c\x12'\xa0\x00\x00\xe0\x94\xfb\xc0\x1d\xb5NG\xcd\xc3\xc48iJ\xb7\x17\xa8V\xc2?\xe6\xe9\x8a\x01\xcaqP\xab\x17OG\x00\x00\xe0\x94\xfb\xcf\xccJ{\x0f&\xcf&\xe9\xf33!2\xe2\xfcj#\af\x8a\x01\xb1\xaeMn.\xf5\x00\x00\x00\u07d4\xfb\xe7\x16\"\xbc\xbd1\xc1\xa3iv\xe7\xe5\xf6p\xc0\u007f\xfe\x16\u0789\x15\xaf\x1dx\xb5\x8c@\x00\x00\u07d4\xfb\xed\xe3,4\x9f3\x00\xefL\xd3;M\xe7\xdc\x18\xe4C\xd3&\x89\xabM\xcf9\x9a:`\x00\x00\u07d4\xfb\xf2\x04\xc8\x13\xf86\xd89b\u01c7\fx\b\xca4\u007f\xd3>\x89\x01\x15\x8eF\t\x13\xd0\x00\x00\xe0\x94\xfb\xf7Y3\xe0\x1bu\xb1T\xef\x06i\ak\xe8\u007fb\xdf\xfa\xe1\x8a\x10\x84cr\xf2I\xd4\xc0\x00\x00\u07d4\xfc\x00\x96\xb2\x1e\x95\xac\xb8\xd6\x19\xd1v\xa4\xa1\xd8\xd5)\xba\xdb\xef\x89\x14\xd9i;\xcb\xec\x02\x80\x00\xe0\x94\xfc\x00\xa4 \xa3a\a\xdf\xd5\xf4\x95\x12\x8a_\u5af2\xdb\x0f4\x8a\x01C\x17\x9d\x86\x91\x10 \x00\x00\xe0\x94\xfc\x01\x8ai\n\xd6tm\xbe:\u03d7\x12\xdd\xcaR\xb6%\x009\x8a\x02\x1e\x19\xe0\u027a\xb2@\x00\x00\u07d4\xfc\x02s@3\xe5\u007fpQ~\n\xfc~\xe6$a\xf0o\xad\x8e\x89\x15[\xd90\u007f\x9f\xe8\x00\x00\u07d4\xfc\x0e\xe6\xf7\u00b3qJ\xe9\x91lEVf\x05\xb6V\xf3$A\x89_h\xe8\x13\x1e\u03c0\x00\x00\u07d4\xfc\x10\xb7\xa6{2h\xd53\x1b\xfbj\x14\xde\xf5\xeaJ\x16,\xa3\x89\n\u05ce\xbcZ\xc6 \x00\x00\u07d4\xfc\x15\u02d9\xa8\xd1\x03\v\x12w\n\xdd\x03:y\xee\r\f\x90\x8c\x89\x12\xfa\x00\xbdR\xe6$\x00\x00\u07d4\xfc)R\xb4\u011f\xed\u043c\x05(\xa3\bI^mj\x1cq\u0589lk\x93[\x8b\xbd@\x00\x00\xe0\x94\xfc,\x1f\x88\x96\x1d\x01\x9c>\x9e\xa30\t\x15.\x06\x93\xfb\xf8\x8a\x8a\x01\xb1\xaeMn.\xf5\x00\x00\x00\xe0\x94\xfc6\x11\x05\u0750\xf9\xed\xe5fI\x9di\xe9\x13\x03\x95\xf1*\u020aS\xa4\xfe/ N\x80\xe0\x00\x00\u07d4\xfc7/\xf6\x92|\xb3\x96\xd9\xcf)\x805\x00\x11\r\xa62\xbcR\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\xfc9\xbeA\tK\x19\x97\xd2\x16\x9e\x82d\xc2\u00fa\xa6\u025b\u0109lk\x93[\x8b\xbd@\x00\x00\u07d4\xfc=\"k\xb3jX\xf5&V\x88W\xb0\xbb\x12\xd1\t\xec\x93\x01\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\xfcC\x82\x9a\u01c7\xff\x88\xaa\xf1\x83\xba5*\xad\xbfZ\x15\xb1\x93\x89\u05ac\n+\x05R\xe0\x00\x00\u07d4\xfcI\xc1C\x9aA\u05b3\xcf&\xbbg\xe06R$\xe5\xe3\x8f_\x8966\u05ef^\u024e\x00\x00\u07d4\xfcU\x00\x82Q\x05\xcfq*1\x8a^\x9c;\xfci\u021d\f\x12\x89\xd8\xd7&\xb7\x17z\x80\x00\x00\xe0\x94\xfcf\xfa\xba'\u007fK]\xe6J\xd4^\xb1\x9c1\xe0\f\xed>\u054a\x011\xbe\xb9%\xff\xd3 \x00\x00\xe0\x94\xfc~\"\xa5\x03\xecZ\xbe\x9b\b\xc5\v\xd1I\x99\xf5 \xfaH\x84\x8a\x01ZG}\xfb\xe1\xea\x14\x80\x00\u07d4\xfc\x82\x15\xa0\xa6\x99\x13\xf6*C\xbf\x1c\x85\x90\xb9\xdd\xcd\r\x8d\u06c9lk\x93[\x8b\xbd@\x00\x00\u07d4\xfc\x98\x9c\xb4\x87\xbf\x1a}\x17\xe4\xc1\xb7\u0137\xaa\xfd\xdak\n\x8d\x89\x01\x15\x8eF\t\x13\xd0\x00\x00\xe0\x94\xfc\x9b4td\xb2\xf9\x92\x9d\x80~\x03\x9d\xaeH\xd3\u064d\xe3y\x8a\x02\xf6\xf1\a\x80\xd2,\xc0\x00\x00\u07d4\xfc\xa4;\xbc#\xa0\xd3!\xba\x9eF\xb9)s\\\xe7\xd8\xef\f\x18\x89\x01\x15\x8eF\t\x13\xd0\x00\x00\u07d4\xfc\xa7>\xff\x87q\xc0\x10;\xa3\xcc\x1a\x9c%\x94H\xc7*\xbf\v\x8965\u026d\xc5\u07a0\x00\x00\u07d4\xfc\xad\xa3\x00(?k\xcc\x13J\x91Eg`\xb0\xd7}\xe4\x10\xe0\x89lk\x93[\x8b\xbd@\x00\x00\xe0\x94\xfc\xbc\\q\xac\xe7\x97AE\v\x01,\xf6\xb8\xd3\xf1}\xb6\x8ap\x8a\x02\x05\xb4\u07e1\xeetx\x00\x00\u07d4\xfc\xbd\x85\xfe\xeajuO\xcf4ID\x9e7\xff\x97\x84\xf7w<\x89\xa7J\xdai\xab\xd7x\x00\x00\xe0\x94\xfc\xc9\u0524&.z\x02z\xb7Q\x91\x10\xd8\x02\u0115\xce\xea9\x8a\x01YQ\x82\"K&H\x00\x00\xe0\x94\xfc\xcd\r\x1e\xce\xe2z\xdd\xea\x95\xf6\x85z\xee\xc8\u01e0K(\xee\x8a\x02\x1e\x19\xe0\u027a\xb2@\x00\x00\xe0\x94\xfc\u0434\x82|\xd2\b\xff\xbf^u\x9d\xba\x8c<\xc6\x1d\x8c,<\x8a\x01\xb1\xaeMn.\xf5\x00\x00\x00\u07d4\xfc\xe0\x89c\\\xe9z\xba\xc0kD\x81\x9b\xe5\xbb\n>.\v7\x89\x05\x03\x92\nv0\xa7\x80\x00\u07d4\xfc\xf1\x99\xf8\xb8T\"/\x18.N\x1d\t\x9dN2>*\xae\x01\x8965\u026d\xc5\u07a0\x00\x00\u07d4\xfc\xfc:P\x04\xd6xa?\v6\xa6B&\x9a\u007f7\x1c?j\x8965\u026d\xc5\u07a0\x00\x00\u07d4\xfd\x19\x1a5\x15}x\x13s\xfbA\x1b\xf9\xf2R\x90\x04|^\xef\x8965\u026d\xc5\u07a0\x00\x00\u07d4\xfd\x1f\xaa4{\x0f\u0300L-\xa8l6\xd5\xf1\u044bp\x87\xbb\x89\x02\xd6\xeb$z\x96\xf6\x00\x00\u07d4\xfd\x1f\xb5\xa8\x9a\x89\xa7!\xb8yph\xfb\xc4\u007f>\x9dR\xe1I\x89\f\u0435\x83\u007f\xc6X\x00\x00\u07d4\xfd OOJ\xba%%\xbar\x8a\xfd\xf7\x87\x92\xcb\u07b75\xae\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\xfd'W\xcc5Q\xa0\x95\x87\x8d\x97\x87V\x15\xfe\fj2\xaa\x8a\x89 m\xb1R\x99\xbe\xac\x00\x00\u07d4\xfd(r\u045eW\x85<\xfa\x16\xef\xfe\x93\u0431\xd4{O\x93\xfb\x89\xd8\xd7&\xb7\x17z\x80\x00\x00\u07d4\xfd))'\x1e\x9d \x95\xa2dv~{\r\xf5.\xa0\xd1\xd4\x00\x89\xa2\xa1\xeb%\x1bZ\xe4\x00\x00\u07d4\xfd7z8Rr\x90\f\xb46\xa3\xbbyb\xcd\xff\xe9?]\xad\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\xfd@$+\xb3Jp\x85^\xf0\xfd\x90\xf3\x80-\xec!6\xb3'\x89h\xa8u\a>)$\x00\x00\xe0\x94\xfdE,9i\xec\xe3\x80\x1cT \xf1\xcd\u02a1\xc7\x1e\xd2=\x8a\x15-\x02\xc7\xe1J\xf6\x80\x00\x00\u07d4\xfdKU\x1fo\xdb\u0366\xc5\x11\xb5\xbb7\"P\xa6\xb7\x83\xe54\x89\x01\x1d\xe1\xe6\xdbE\f\x00\x00\u07d4\xfdK\x98\x95X\xae\x11\xbe\f;6\xe2\xd6\xf2\xa5J\x93C\xca.\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\xfdM\xe8\xe3t\x8a(\x9c\xf7\xd0`Q}\x9d88\x8d\xb0\x1f\xb8\x89\r\x8drkqw\xa8\x00\x00\u07d4\xfdZc\x15\u007f\x91O\u04d8\uac5c\x13}\xd9U\v\xb7q\\\x89\x05k\xc7^-c\x10\x00\x00\u07d4\xfd`\u04b5\xaf=5\xf7\xaa\xf0\u00d3\x05.y\xc4\xd8#\u0645\x89\x03\x0e\xb5\r.\x14\b\x00\x00\u07d4\xfdhm\xe5?\xa9\u007f\x99c\x9e%hT\x97 \xbcX\x8c\x9e\xfc\x89j\xc5\xc6-\x94\x86\a\x00\x00\u07d4\xfd~\u078fR@\xa0eA\xebi\x9dx,/\x9a\xfb!p\xf6\x89Hz\x9a0E9D\x00\x00\u07d4\xfd\x81+\u019f\xb1p\xefW\xe22~\x80\xaf\xfd\x14\xf8\xe4\xb6\u0489lk\x93[\x8b\xbd@\x00\x00\u07d4\xfd\x88\xd1\x14\"\x0f\b\x1c\xb3\xd5\xe1[\xe8\x15*\xb0sfWj\x89\x10CV\x1a\x88)0\x00\x00\u07d4\xfd\x91\x856\xa8\xef\xa6\xf6\xce\xfe\x1f\xa1\x159\x95\xfe\xf5\xe3=;\x89\x1b\x1a\xe4\xd6\xe2\xefP\x00\x00\u07d4\xfd\x92\x0fr&\x82\xaf\xb5\xafE\x1b\x05D\xd4\xf4\x1b;\x9dWB\x89~R\x05j\x12?<\x00\x00\u07d4\xfd\x95y\xf1\x19\xbb\xc8\x19\xa0+a\u3348\x03\xc9B\xf2M2\x89\x05\xb9~\x90\x81\xd9@\x00\x00\u07d4\xfd\xa0\xce\x153\a\a\xf1\v\xce2\x01\x17- \x18\xb9\xdd\xeat\x89\x02\xd0A\xd7\x05\xa2\xc6\x00\x00\xe0\x94\xfd\xa3\x04(\x19\xaf>f)\x00\xe1\xb9+CX\xed\xa6\xe9%\x90\x8a\x19\a\xa2\x84\u054fc\xe0\x00\x00\u07d4\xfd\xa6\x81\x0e\xa5\xac\x98]o\xfb\xf1\xc5\x11\xf1\xc1B\xed\xcf\xdd\xf7\x89\xd8\xd7&\xb7\x17z\x80\x00\x00\u07d4\xfd\xb39D\xf26\x06\x15\xe5\xbe#\x95w\u0221\x9b\xa5-\x98\x87\x89 \x9d\x92/RY\xc5\x00\x00\u07d4\xfd\xbaSY\xf7\xec;\xc7p\xacI\x97]\x84N\xc9qbV\xf1\x8965\u026d\xc5\u07a0\x00\x00\xe0\x94\xfd\xc4\xd4vZ\x94/[\xf9i1\xa9\xe8\xccz\xb8\xb7W\xffL\x8a\x12lG\x8a\x0e>\xa8`\x00\x00\xe0\x94\xfd\xcd]\x80\xb1\x05\x89zW\xab\xc4xev\x8b)\x00RB\x95\x8a\x01Z\xf1\u05cbX\xc4\x00\x00\x00\u0794\xfd\xd1\x19_y}O5q}\x15\xe6\xf9\x81\n\x9a?\xf5T`\x88\xfc\x93c\x92\x80\x1c\x00\x00\u07d4\xfd\xd5\x02\xa7N\x81;\u03e3U\xce\xda<\x17ojhq\xaf\u007f\x89\x15\xaf\x1dx\xb5\x8c@\x00\x00\u07d4\xfd\u357c\vm\\\xbbL\x1d\x8f\xea>\vK\xffc^\x9d\xb7\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\xfd\xea\xac*\xcf\x1d\x13\x8e\x19\xf2\xfc?\x9f\xb7E\x92\xe3\ud04a\x89$=M\x18\"\x9c\xa2\x00\x00\u07d4\xfd\xec\xc8-\xdf\xc5a\x92\xe2oV<=h\xcbTJ\x96\xbf\xed\x89\x17\xda:\x04\u01f3\xe0\x00\x00\u07d4\xfd\xf4#C\x01\x9b\v\fk\xf2`\xb1s\xaf\xab~E\xb9\xd6!\x89lj\xccg\u05f1\xd4\x00\x00\u07d4\xfd\xf4I\xf1\b\xc6\xfbOZ+\b\x1e\xed~E\u645eM%\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\xfd\xfda4\xc0J\x8a\xb7\xeb\x16\xf0\x06C\xf8\xfe\xd7\u06aa\ucc89\x15\xaf\x1dx\xb5\x8c@\x00\x00\u07d4\xfe\x00\xbfC\x99\x11\xa5S\x98-\xb68\x03\x92E\xbc\xf02\xdb\u0709\x15[\xd90\u007f\x9f\xe8\x00\x00\u07d4\xfe\x01n\xc1~\xc5\xf1\x0e;\xb9\x8f\xf4\xa1\xed\xa0E\x15v\x82\xab\x89\x14_T\x02\xe7\xb2\xe6\x00\x00\u07d4\xfe\x0e0\xe2\x14)\rt=\xd3\x0e\xb0\x82\xf1\xf0\xa5\"Z\xdea\x89\n\u05ce\xbcZ\xc6 \x00\x00\u07d4\xfe!\v\x8f\x04\xdcmOv!j\xcf\xcb\u055b\xa8;\xe9\xb60\x89\x01\x15\x8eF\t\x13\xd0\x00\x00\u07d4\xfe\"\xa0\xb3\x88f\x8d\x1a\xe2d>w\x1d\xac\xf3\x8aCB#\u0309\xd8\xdb^\xbd{&8\x00\x00\u07d4\xfe6&\x88\x84_\xa2D\u0300~K\x110\xeb7A\xa8\x05\x1e\x8965\u026d\xc5\u07a0\x00\x00\u07d4\xfe8'\xd5v0\u03c7a\xd5\x12y{\v\x85\x8eG\x8b\xbd\x12\x89\x01\x15\x8eF\t\x13\xd0\x00\x00\u07d4\xfeA\x8bB\x1a\x9cm76\x02y\x04u\xd20>\x11\xa7Y0\x897\b\xba\xed=h\x90\x00\x00\u07d4\xfeBI\x12yP\xe2\xf8\x96\xec\x0e~.=\x05Z\xab\x10U\x0f\x89$=M\x18\"\x9c\xa2\x00\x00\xe0\x94\xfeM\x84\x03!o\xd5qW+\xf1\xbd\xb0\x1d\x00W\x89x\u0588\x8a\x02\x15\xf85\xbcv\x9d\xa8\x00\x00\u07d4\xfeS\xb9I\x89\u0619d\xda aS\x95&\xbb\xe9y\xdd.\xa9\x89h\xa8u\a>)$\x00\x00\u07d4\xfeT\x9b\xbf\xe6G@\x18\x98\x92\x93%8\u06afF\u04b6\x1dO\x89\x02+\x1c\x8c\x12'\xa0\x00\x00\xe0\x94\xfea]\x97\\\b\x87\xe0\xc9\x11>\xc7)\x84 \xa7\x93\xaf\x8b\x96\x8a\x01\xb1\xaeMn.\xf5\x00\x00\x00\u07d4\xfee\xc4\x18\x8dy\"Wi\td D\xfd\xc5#\x95V\x01e\x89\xd8\xd7&\xb7\x17z\x80\x00\x00\u07d4\xfei\u007f\xf2,\xa5G\xbf\xc9^3\xd9`\xda`\\gc\xf3[\x89G\xd4\x11\x9f\xd9`\x94\x00\x00\u07d4\xfej\x89[y\\\xb4\xbf\x85\x90=<\xe0\x9cZ\xa49S\u04ff\x89\xb8Pz\x82\a( \x00\x00\u07d4\xfeo_B\xb6\x19;\x1a\xd1b\x06\u4bf5#\x9dM}\xb4^\x89]\u0212\xaa\x111\xc8\x00\x00\u07d4\xfep\x11\xb6\x98\xbf3q\x13-tE\xb1\x9e\xb5\xb0\x945j\xee\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\xfe\x80\xe9#-\xea\xff\x19\xba\xf9\x98i\x88:K\xdf\x00\x04\xe5<\x89.b\xf2\ni\xbe@\x00\x00\u07d4\xfe\x8en6eW\r\xffz\x1b\xdaiz\xa5\x89\xc0\xb4\xe9\x02J\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\xfe\x8f\x1f\u072b\u007f\xbe\u0266\xa3\xfc\xc5\aa\x96\x00P\\6\xa3\x89\x01\x11du\x9f\xfb2\x00\x00\u07d4\xfe\x91\xec\xcf+\xd5f\xaf\xa1\x16\x96\xc5\x04\x9f\xa8Lic\nR\x89i*\xe8\x89p\x81\xd0\x00\x00\u07d4\xfe\x96\xc4\xcd8\x15b@\x1a\xa3*\x86\xe6[\x9dR\xfa\x8a\xee'\x89\x8f\x1d\\\x1c\xae7@\x00\x00\u07d4\xfe\x98\xc6d\xc3\xe4G\xa9^i\xbdX!q\xb7\x17n\xa2\xa6\x85\x89\xd8\xd7&\xb7\x17z\x80\x00\x00\u07d4\xfe\x9a\xd1.\xf0]m\x90&\x1f\x96\xc84\n\x03\x81\x97M\xf4w\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\xfe\x9c\x0f\xff\xef\xb8\x03\b\x12V\xc0\xcfMfY\xe6\xd3>\xb4\xfb\x89R\xd5B\x80O\x1c\xe0\x00\x00\u07d4\xfe\x9c\xfc;\xb2\x93\u0772\x85\xe6%\xf3X/t\xa6\xb0\xa5\xa6\u0349j\xcb=\xf2~\x1f\x88\x00\x00\xe0\x94\xfe\x9e\x11\x97\u05d7JvH\xdc\u01e01\x12\xa8\x8e\xdb\xc9\x04]\x8a\x01\n\xfc\x1a\xde;N\xd4\x00\x00\xe0\x94\xfe\xac\xa2\xactbK\xf3H\xda\u0258QC\xcf\xd6R\xa4\xbeU\x8a\x05\x89\u007f\u02f0)\x14\b\x80\x00\u07d4\xfe\xad\x18\x03\xe5\xe77\xa6\x8e\x18G-\x9a\xc7\x15\xf0\x99L\u00be\x89\x1b\x1a\xe4\xd6\xe2\xefP\x00\x00\u07d4\xfe\xb8\xb8\xe2\xafqj\xe4\x1f\xc7\xc0K\xcf)T\x01VF\x1ek\x89TQt\xa5(\xa7z\x00\x00\u07d4\xfe\xb9-0\xbf\x01\xff\x9a\x19\x01flUsS+\xfa\a\xee\xec\x8965\u026d\xc5\u07a0\x00\x00\u07d4\xfe\xbc1s\xbc\x90r\x13cT\x00+{O\xb3\xbf\xc5?\"\xf1\x89\x14\x0e\xc8\x0f\xa7\xee\x88\x00\x00\u07d4\xfe\xbdH\xd0\xff\xdb\xd5el\xd5\xe6\x866:a\x14R(\xf2y\x89\x97\xc9\xceL\xf6\xd5\xc0\x00\x00\u07d4\xfe\xbd\x9f\x81\xcfx\xbd_\xb6\u0139\xa2K\xd4\x14\xbb\x9b\xfaLN\x89k\xe1\x0f\xb8\xedn\x13\x80\x00\u07d4\xfe\xc0o\xe2{D\u01c4\xb29n\xc9/{\x92:\xd1~\x90w\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\xfe\xc1NT\x85\xde+>\xef^t\xc4aF\u06ceEN\x035\x89\t\xb4\x1f\xbf\x9e\n\xec\x00\x00\u07d4\xfe\xd8Gm\x10\u0544\xb3\x8b\xfag7`\x0e\xf1\x9d5\xc4\x1e\u0609b\xa9\x92\xe5:\n\xf0\x00\x00\u07d4\xfe\xef;n\xab\xc9J\xff\xd31\f\x1cM\x0ee7^\x13\x11\x19\x89\x01\x15\x8eF\t\x13\xd0\x00\x00\u07d4\xfe\xf0\x9dp$?9\xed\x8c\xd8\x00\xbf\x96QG\x9e\x8fJ\xca<\x89\n\u05ce\xbcZ\xc6 \x00\x00\u07d4\xfe\xf3\xb3\u07ad\x1ai&\u051a\xa3+\x12\xc2*\xf5M\x9f\xf9\x85\x8965\u026d\xc5\u07a0\x00\x00\u07d4\xff\v|\xb7\x1d\xa9\xd4\xc1\xean\xcc(\xeb\xdaPLc\xf8/\u04498\x8a\x88]\xf2\xfcl\x00\x00\u07d4\xff\f<w\x98\xe8s=\xd2f\x81R\x89\x1b\xab\x80\xa8\xbe\x95\\\x89\x04YF\xb0\xf9\xe9\xd6\x00\x00\u07d4\xff\f\xb0lB\xe3\u0609H\xe4[\u05f0\xd4\u246e\xfe\xeaQ\x89g\x8a\x93 b\xe4\x18\x00\x00\u07d4\xff\f\xc8\xda\xc8$\xfa$\xfc<\xaa!i\xe6\xe0W\xcfc\x8a\u0589\xd8\xd7&\xb7\x17z\x80\x00\x00\u07d4\xff\x0e/\xec0B\aF~\x1e3\a\xf6L\xbf0\xaf\x8f\xd9\u0349lk\x93[\x8b\xbd@\x00\x00\u07d4\xff\x12\x8fK5[\xe1\xdcJo\x94\xfaQ\r\u007f\x15\xd5<*\xff\x89\x93s\x954\u0486\x80\x00\x00\u07d4\xff\x12\u474e\x06\xaa \xf8\x86)<\v\x98\xed~\xffx\x88\x05\x89\xd8\xd7&\xb7\x17z\x80\x00\x00\u07d4\xff s\b\xce\xd28\xa6\xc0\x1a\xd0!<\xa9\xebDe\xd4%\x90\x89lj\xccg\u05f1\xd4\x00\x00\u07d4\xff&\x13\x830'M\xf4\xe0\xa3\b\x1em\xf7\u0758>\xc6\u73c9lk\x93[\x8b\xbd@\x00\x00\u07d4\xff'&)AH\xb8lx\xa97$\x97\xe4Y\x89\x8e\xd3\xfe\xe3\x89j\xcb=\xf2~\x1f\x88\x00\x00\u07d4\xff=\xedz@\u04ef\xf0\u05e8\xc4_\xa6\x13j\xa0C=\xb4W\x89lh\xcc\u041b\x02,\x00\x00\u07d4\xff>\xeeW\xc3Mm\xae\x97\r\x8b1\x11\x17\xc55\x86\xcd5\x02\x89\\(=A\x03\x94\x10\x00\x00\u07d4\xff>\xf6\xba\x15\x1c!\xb5\x99\x86\xaed\xf6\xe8\"\x8b\u0262\xc73\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\xffA\xd9\xe1\xb4\xef\xfe\x18\u0630\xd1\xf6?\xc4%_\xb4\xe0l=\x89Hz\x9a0E9D\x00\x00\u07d4\xffE\xcb4\xc9(6M\x9c\xc9\u063b\x0074ta\x8f\x06\xf3\x89\x05k\xc7^-c\x10\x00\x00\xe0\x94\xffI\xa7u\x81N\xc0\x00Q\xa7\x95\xa8u\xde$Y.\xa4\x00\u050a*Z\x05\x8f\u0095\xed\x00\x00\x00\u07d4\xffJ@\x8fP\xe9\xe7!F\xa2\x8c\xe4\xfc\x8d\x90'\x1f\x11n\x84\x89j\xcb=\xf2~\x1f\x88\x00\x00\u07d4\xffM\x9c\x84\x84\xc4<B\xff,Z\xb7Y\x99d\x98\xd3#\x99M\x89\xd8\xd7&\xb7\x17z\x80\x00\x00\u07d4\xffO\xc6`i\x04lRVX\xc37\xa9\x17\xf2\u05382\xb4\t\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\xffQb\xf25M\u0112\xc7_\xd6\xe3\xa1\a&\x86`\xee\xcbG\x89\\(=A\x03\x94\x10\x00\x00\u07d4\xffT[\xbbf\xfb\xd0\x0e\xb5\xe67?\xf4\xe3&\xf5\xfe\xb5\xfe\x12\x89\x01\x15\x8eF\t\x13\xd0\x00\x00\u07d4\xff^~\xe7\xd5\x11H!\xe1Y\u0725\xe8\x1f\x18\xf1\xbf\xff\xbf\xf9\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\xffa\xc9\xc1\xb7\xa3\u0635;\xba \xb3DfTK{!fD\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\xffeQ\x1c\xad\xa2Y&\f\x1d\xdcA\x97N\xca\xec\xd3-cW\x89_h\xe8\x13\x1e\u03c0\x00\x00\xe0\x94\xffxC\xc7\x01\n\xa7\xe6\x15\x19\xb7b\xdf\xe4\x91$\xa7k\x0eN\x8a\u0171y$A+\x9b\xb0\x00\x00\xe0\x94\xffxT\x17V\xab+pn\rp\xb1\x8a\xdbp\x0f\xc4\xf1d=\x8a\t(\x96R\x9b\xad\u0708\x00\x00\u07d4\xff\x83\x85PQ\xee\x8f\xfbp\xb4\x81}\xba2\x11\xed#U\x86\x9d\x89\x15\xaf\x1dx\xb5\x8c@\x00\x00\u07d4\xff\x85\x0e;\xe1\xebjMrl\b\xfas\xaa\xd3X\xf3\x97\x06\u0689i*\xe8\x89p\x81\xd0\x00\x00\u07d4\xff\x86\xe5\xe8\xe1[S\x90\x96\x00\xe4\x13\b\u06b7_\x0e$\xe4k\x890\xebP\xd2\xe1@\x80\x00\x00\u07d4\xff\x88\xeb\xac\xc4\x1b6\x87\xf3\x9eKY\xe1YY\x9b\x80\u02e3?\x89\x15\xaf\x1dx\xb5\x8c@\x00\x00\u07d4\xff\x8a,\xa5\xa8\x133\xf1\x99\x98%_ 2V\xe1\xa8\x19\xc0\xaa\x89\f$\x9f\xdd2w\x80\x00\x00\u07d4\xff\x8e\xb0}\xe3\u051d\x9dR\xbb\xe8\xe5\xb2m\xbe\x1d\x16\x0f\xa84\x89\xd8\x14\u0739DS\b\x00\x00\xe0\x94\xff\xa4\xaf\xf1\xa3\u007f\x98K\ng'!I':\xe9\xbdA\u3f0a\x02\x1e\x19\xe0\u027a\xb2@\x00\x00\u07d4\xff\xa6\x96\xec\xbdx~f\xab\xaeO\xe8{c_\a\xcaW\xd8H\x89Hz\x9a0E9D\x00\x00\u07d4\xff\xac=\xb8y\xa6\xc7\x15\x8e\x8d\xec`;@tc\xba\r1\u03c9j\xcb=\xf2~\x1f\x88\x00\x00\xe0\x94\xff\xad=\xd7N,\x1fyj\xc6@\xdeV\u0719\xb4\u01d2\xa4\x02\x8a\x01\x0f\f\xf0d\xddY \x00\x00\u07d4\xff\xb0G&\u07e4\x1a\xfd\xc8\x19\x16\x84\x18a\x04r\x97\r{\xfc\x89\xd8\xd7&\xb7\x17z\x80\x00\x00\u07d4\xff\xb3\xbc\xc3\x19j\x8c<\xb84\xce\xc9L4\xfe\xd3[>\x10T\x89H\xa4<T`/p\x00\x00\u07d4\xff\xb9tg3g\xf5\xc0{\xe5\xfd'\r\u0137\x13\x8b\aMW\x89\x85\xeb\u023d\xb9\x06m\x80\x00\u07d4\xff\xb9\xc7!~ft01\xeb7z\xf6\\w\xdbsY\xdc\u0689\x02+\x1c\x8c\x12'\xa0\x00\x00\u07d4\xff\xbc=\xa08\x1e\xc39\xc1\xc0I\xeb\x1e\xd9\xee4\xfd\u03a6\u0289\xd8\xd7&\xb7\x17z\x80\x00\x00\u07d4\xff\xc5\xfcK~\x8a\x02\x93\xff9\xa3\xa0\xf7\xd6\r&F\xd3zt\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\xff\xc9\xcc0\x94\xb0A\xad\x0e\ao\x96\x8a\r\xe3\xb1g%Xf\x89\x17p\xc1e\v\xee\xe8\x00\x00\u07d4\xff\xd5\x17\x0f\u0468\x11\x8dU\x8eu\x11\xe3d\xb2I\x06\xc4\xf6\xb3\x89\x03A\xd8\xcd'\xf1X\x80\x00\xe0\x94\xff\xd6\u0695\x8e\xec\xbc\x01k\xab\x91\x05\x84@\u04dbA\u01fe\x83\x8a\x04<3\xc1\x93ud\x80\x00\x00\u07d4\xff\xe0\xe9\x97\xf1\x97za_Z1Z\xf4\x13\xfdHi4;\xa0\x89\x05l\xd5_\xc6M\xfe\x00\x00\u07d4\xff\u2375<\x90D\xb4\xec\xd4\x05?\u0474\xb1\rpV\u0188\x89\x05k\xc7^-c\x10\x00\x00\u07d4\xff\xe2\xe2\x8c?\xb7GI\xd7\xe7\x80\u070a]B%8\xe6\xe4Q\x89\r\xbb\x81\xe0[\xc1-\x80\x00\u07d4\xff\xe8\xcb\xc1h\x1e^\x9d\xb7J\x0f\x93\xf8\xed%\x89u\x19\x12\x0f\x89Q\xb1\u04c3\x92a\xac\x00\x00\u07d4\xff\xea\xc00^\xde:\x91R\x95\xec\x8ea\xc7\xf8\x81\x00oDt\x89\x05V\xf6L\x1f\xe7\xfa\x00\x00\u07d4\xff\xec\t\x13\xc65\xba\xca/^W\xa3z\xa9\xfb{l\x9bn&\x89+\xa3\x9e\x82\xed]t\x00\x00\xe0\x94\xff\xf3:;\xd3j\xbd\xbdA'\a\xb8\xe3\x10\xd6\x01\x14T\xa7\xae\x8a\x01\xb1\xaeMn.\xf5\x00\x00\x00\u07d4\xff\xf4\xba\u0556c4y\xa2\xa2\x9f\x9a\x8b?x\xee\xfd\a\xe6\xee\x89\x05k\xc7^-c\x10\x00\x00\u07d4\xff\xf7\xac\x99\xc8\xe4\xfe\xb6\f\x97P\x05K\xdc\x14\xce\x18W\xf1\x81\x8965\u026d\xc5\u07a0\x00\x00" const goerliAllocData = "\xf9\x04\x06\u0080\x01\xc2\x01\x01\xc2\x02\x01\xc2\x03\x01\xc2\x04\x01\xc2\x05\x01\xc2\x06\x01\xc2\a\x01\xc2\b\x01\xc2\t\x01\xc2\n\x01\xc2\v\x01\xc2\f\x01\xc2\r\x01\xc2\x0e\x01\xc2\x0f\x01\xc2\x10\x01\xc2\x11\x01\xc2\x12\x01\xc2\x13\x01\xc2\x14\x01\xc2\x15\x01\xc2\x16\x01\xc2\x17\x01\xc2\x18\x01\xc2\x19\x01\xc2\x1a\x01\xc2\x1b\x01\xc2\x1c\x01\xc2\x1d\x01\xc2\x1e\x01\xc2\x1f\x01\xc2 \x01\xc2!\x01\xc2\"\x01\xc2#\x01\xc2$\x01\xc2%\x01\xc2&\x01\xc2'\x01\xc2(\x01\xc2)\x01\xc2*\x01\xc2+\x01\xc2,\x01\xc2-\x01\xc2.\x01\xc2/\x01\xc20\x01\xc21\x01\xc22\x01\xc23\x01\xc24\x01\xc25\x01\xc26\x01\xc27\x01\xc28\x01\xc29\x01\xc2:\x01\xc2;\x01\xc2<\x01\xc2=\x01\xc2>\x01\xc2?\x01\xc2@\x01\xc2A\x01\xc2B\x01\xc2C\x01\xc2D\x01\xc2E\x01\xc2F\x01\xc2G\x01\xc2H\x01\xc2I\x01\xc2J\x01\xc2K\x01\xc2L\x01\xc2M\x01\xc2N\x01\xc2O\x01\xc2P\x01\xc2Q\x01\xc2R\x01\xc2S\x01\xc2T\x01\xc2U\x01\xc2V\x01\xc2W\x01\xc2X\x01\xc2Y\x01\xc2Z\x01\xc2[\x01\xc2\\\x01\xc2]\x01\xc2^\x01\xc2_\x01\xc2`\x01\xc2a\x01\xc2b\x01\xc2c\x01\xc2d\x01\xc2e\x01\xc2f\x01\xc2g\x01\xc2h\x01\xc2i\x01\xc2j\x01\xc2k\x01\xc2l\x01\xc2m\x01\xc2n\x01\xc2o\x01\xc2p\x01\xc2q\x01\xc2r\x01\xc2s\x01\xc2t\x01\xc2u\x01\xc2v\x01\xc2w\x01\xc2x\x01\xc2y\x01\xc2z\x01\xc2{\x01\xc2|\x01\xc2}\x01\xc2~\x01\xc2\u007f\x01\u00c1\x80\x01\u00c1\x81\x01\u00c1\x82\x01\u00c1\x83\x01\u00c1\x84\x01\u00c1\x85\x01\u00c1\x86\x01\u00c1\x87\x01\u00c1\x88\x01\u00c1\x89\x01\u00c1\x8a\x01\u00c1\x8b\x01\u00c1\x8c\x01\u00c1\x8d\x01\u00c1\x8e\x01\u00c1\x8f\x01\u00c1\x90\x01\u00c1\x91\x01\u00c1\x92\x01\u00c1\x93\x01\u00c1\x94\x01\u00c1\x95\x01\u00c1\x96\x01\u00c1\x97\x01\u00c1\x98\x01\u00c1\x99\x01\u00c1\x9a\x01\u00c1\x9b\x01\u00c1\x9c\x01\u00c1\x9d\x01\u00c1\x9e\x01\u00c1\x9f\x01\u00c1\xa0\x01\u00c1\xa1\x01\u00c1\xa2\x01\u00c1\xa3\x01\u00c1\xa4\x01\u00c1\xa5\x01\u00c1\xa6\x01\u00c1\xa7\x01\u00c1\xa8\x01\u00c1\xa9\x01\u00c1\xaa\x01\u00c1\xab\x01\u00c1\xac\x01\u00c1\xad\x01\u00c1\xae\x01\u00c1\xaf\x01\u00c1\xb0\x01\u00c1\xb1\x01\u00c1\xb2\x01\u00c1\xb3\x01\u00c1\xb4\x01\u00c1\xb5\x01\u00c1\xb6\x01\u00c1\xb7\x01\u00c1\xb8\x01\u00c1\xb9\x01\u00c1\xba\x01\u00c1\xbb\x01\u00c1\xbc\x01\u00c1\xbd\x01\u00c1\xbe\x01\u00c1\xbf\x01\u00c1\xc0\x01\u00c1\xc1\x01\u00c1\xc2\x01\u00c1\xc3\x01\u00c1\xc4\x01\u00c1\xc5\x01\u00c1\xc6\x01\u00c1\xc7\x01\u00c1\xc8\x01\u00c1\xc9\x01\u00c1\xca\x01\u00c1\xcb\x01\u00c1\xcc\x01\u00c1\xcd\x01\u00c1\xce\x01\u00c1\xcf\x01\u00c1\xd0\x01\u00c1\xd1\x01\u00c1\xd2\x01\u00c1\xd3\x01\u00c1\xd4\x01\u00c1\xd5\x01\u00c1\xd6\x01\u00c1\xd7\x01\u00c1\xd8\x01\u00c1\xd9\x01\u00c1\xda\x01\u00c1\xdb\x01\u00c1\xdc\x01\u00c1\xdd\x01\u00c1\xde\x01\u00c1\xdf\x01\u00c1\xe0\x01\u00c1\xe1\x01\u00c1\xe2\x01\u00c1\xe3\x01\u00c1\xe4\x01\u00c1\xe5\x01\u00c1\xe6\x01\u00c1\xe7\x01\u00c1\xe8\x01\u00c1\xe9\x01\u00c1\xea\x01\u00c1\xeb\x01\u00c1\xec\x01\u00c1\xed\x01\u00c1\xee\x01\u00c1\xef\x01\u00c1\xf0\x01\u00c1\xf1\x01\u00c1\xf2\x01\u00c1\xf3\x01\u00c1\xf4\x01\u00c1\xf5\x01\u00c1\xf6\x01\u00c1\xf7\x01\u00c1\xf8\x01\u00c1\xf9\x01\u00c1\xfa\x01\u00c1\xfb\x01\u00c1\xfc\x01\u00c1\xfd\x01\u00c1\xfe\x01\u00c1\xff\x01\xe0\x94L*\xe4\x82Y5\x05\xf0\x16<\xde\xfc\a>\x81\xc6<\xdaA\a\x8a\x15-\x02\xc7\xe1J\xf6\x80\x00\x00\xe0\x94\xa8\xe8\xf1G2e\x8eKQ\xe8q\x191\x05:\x8ai\xba\xf2\xb1\x8a\x15-\x02\xc7\xe1J\xf6\x80\x00\x00\xe1\x94\u0665\x17\x9f\t\x1d\x85\x05\x1d<\x98'\x85\xef\xd1E\\\uc199\x8b\bE\x95\x16\x14\x01HJ\x00\x00\x00\xe1\x94\u08bdBX\xd2v\x887\xba\xa2j(\xfeq\xdc\a\x9f\x84\u01cbJG\xe3\xc1$H\xf4\xad\x00\x00\x00" const sepoliaAllocData = "\xf9\x01\xee\u0791i\x16\xa8{\x823?BE\x04f#\xb27\x94\xc6\\\x8b\bE\x95\x16\x14\x01HJ\x00\x00\x00\xe1\x94\x10\xf5\xd4XT\xe08\a\x14\x85\xac\x9e@#\b\u03c0\xd2\xd2\xfe\x8bR\xb7\xd2\xdc\xc8\f\xd2\xe4\x00\x00\x00\u0794y\x9d2\x9e_X4\x19\x16|\xd7\"\x96$\x85\x92n3\x8fJ\x88\r\u0db3\xa7d\x00\x00\xe0\x94|\xf5\xb7\x9b\xfe)\x1ag\xab\x02\xb3\x93\xe4V\xcc\xc4\xc2f\xf7S\x8a\xd3\xc2\x1b\xce\xcc\xed\xa1\x00\x00\x00\xe0\x94\x8b\u007f\tw\xbbO\x0f\xbepv\xfa\"\xbc$\xac\xa0CX?^\x8a\xd3\xc2\x1b\xce\xcc\xed\xa1\x00\x00\x00\xe0\x94\xa2\xa6\xd949\x14O\xfeM'\xc9\xe0\x88\xdc\u0637\x83\x94bc\x8a\xd3\xc2\x1b\xce\xcc\xed\xa1\x00\x00\x00\xe0\x94\xaa\xec\x869DA\xf9\x15\xbc\xe3\xe6\xab9\x99w\xe9\x90o;i\x8a\xd3\xc2\x1b\xce\xcc\xed\xa1\x00\x00\x00\u1532\x1c3\xde\x1f\xab?\xa1T\x99\xc6+Y\xfe\f\xc3%\x00 \u044bR\xb7\xd2\xdc\xc8\f\xd2\xe4\x00\x00\x00\xe0\x94\xbc\x11)Y6\xaay\u0554\x13\x9d\xe1\xb2\xe1&)AO;\u06ca\xd3\xc2\x1b\xce\xcc\xed\xa1\x00\x00\x00\xe0\x94\xbe\xef2\xca[\x9a\x19\x8d'\xb4\xe0/LpC\x9f\xe6\x03V\u03ca\xd3\xc2\x1b\xce\xcc\xed\xa1\x00\x00\x00\xe1\x94\xd7\xd7lX\xb3\xa5\x19\xe9\xfal\xc4\xd2-\xc0\x17%\x9b\u011f\x1e\x8bR\xb7\xd2\xdc\xc8\f\xd2\xe4\x00\x00\x00\xe0\x94\xd7\xed\xdbx\xed)[<\x96)$\x0e\x89$\xfb\x8d\x88t\xdd\u060a\xd3\xc2\x1b\xce\xcc\xed\xa1\x00\x00\x00\xe0\x94\u0665\x17\x9f\t\x1d\x85\x05\x1d<\x98'\x85\xef\xd1E\\\uc199\x8a\xd3\xc2\x1b\xce\xcc\xed\xa1\x00\x00\x00\xe0\x94\xe2\xe2e\x90(\x147\x84\xd5W\xbc\xeco\xf3\xa0r\x10H\x88\n\x8a\xd3\xc2\x1b\xce\xcc\xed\xa1\x00\x00\x00\xe0\x94\xf4|\xae\x1c\xf7\x9c\xa6u\x8b\xfcx}\xbd!\u6f7eq\x12\xb8\x8a\xd3\xc2\x1b\xce\xcc\xed\xa1\x00\x00\x00" +const holeskyAllocData = "\xf9,\x85\u0080\x01\xc2\x01\x01\xc2\x02\x01\xc2\x03\x01\xc2\x04\x01\xc2\x05\x01\xc2\x06\x01\xc2\a\x01\xc2\b\x01\xc2\t\x01\xc2\n\x01\xc2\v\x01\xc2\f\x01\xc2\r\x01\xc2\x0e\x01\xc2\x0f\x01\xc2\x10\x01\xc2\x11\x01\xc2\x12\x01\xc2\x13\x01\xc2\x14\x01\xc2\x15\x01\xc2\x16\x01\xc2\x17\x01\xc2\x18\x01\xc2\x19\x01\xc2\x1a\x01\xc2\x1b\x01\xc2\x1c\x01\xc2\x1d\x01\xc2\x1e\x01\xc2\x1f\x01\xc2 \x01\xc2!\x01\xc2\"\x01\xc2#\x01\xc2$\x01\xc2%\x01\xc2&\x01\xc2'\x01\xc2(\x01\xc2)\x01\xc2*\x01\xc2+\x01\xc2,\x01\xc2-\x01\xc2.\x01\xc2/\x01\xc20\x01\xc21\x01\xc22\x01\xc23\x01\xc24\x01\xc25\x01\xc26\x01\xc27\x01\xc28\x01\xc29\x01\xc2:\x01\xc2;\x01\xc2<\x01\xc2=\x01\xc2>\x01\xc2?\x01\xc2@\x01\xc2A\x01\xc2B\x01\xc2C\x01\xc2D\x01\xc2E\x01\xc2F\x01\xc2G\x01\xc2H\x01\xc2I\x01\xc2J\x01\xc2K\x01\xc2L\x01\xc2M\x01\xc2N\x01\xc2O\x01\xc2P\x01\xc2Q\x01\xc2R\x01\xc2S\x01\xc2T\x01\xc2U\x01\xc2V\x01\xc2W\x01\xc2X\x01\xc2Y\x01\xc2Z\x01\xc2[\x01\xc2\\\x01\xc2]\x01\xc2^\x01\xc2_\x01\xc2`\x01\xc2a\x01\xc2b\x01\xc2c\x01\xc2d\x01\xc2e\x01\xc2f\x01\xc2g\x01\xc2h\x01\xc2i\x01\xc2j\x01\xc2k\x01\xc2l\x01\xc2m\x01\xc2n\x01\xc2o\x01\xc2p\x01\xc2q\x01\xc2r\x01\xc2s\x01\xc2t\x01\xc2u\x01\xc2v\x01\xc2w\x01\xc2x\x01\xc2y\x01\xc2z\x01\xc2{\x01\xc2|\x01\xc2}\x01\xc2~\x01\xc2\x7f\x01\u00c1\x80\x01\u00c1\x81\x01\u00c1\x82\x01\u00c1\x83\x01\u00c1\x84\x01\u00c1\x85\x01\u00c1\x86\x01\u00c1\x87\x01\u00c1\x88\x01\u00c1\x89\x01\u00c1\x8a\x01\u00c1\x8b\x01\u00c1\x8c\x01\u00c1\x8d\x01\u00c1\x8e\x01\u00c1\x8f\x01\u00c1\x90\x01\u00c1\x91\x01\u00c1\x92\x01\u00c1\x93\x01\u00c1\x94\x01\u00c1\x95\x01\u00c1\x96\x01\u00c1\x97\x01\u00c1\x98\x01\u00c1\x99\x01\u00c1\x9a\x01\u00c1\x9b\x01\u00c1\x9c\x01\u00c1\x9d\x01\u00c1\x9e\x01\u00c1\x9f\x01\u00c1\xa0\x01\u00c1\xa1\x01\u00c1\xa2\x01\u00c1\xa3\x01\u00c1\xa4\x01\u00c1\xa5\x01\u00c1\xa6\x01\u00c1\xa7\x01\u00c1\xa8\x01\u00c1\xa9\x01\u00c1\xaa\x01\u00c1\xab\x01\u00c1\xac\x01\u00c1\xad\x01\u00c1\xae\x01\u00c1\xaf\x01\u00c1\xb0\x01\u00c1\xb1\x01\u00c1\xb2\x01\u00c1\xb3\x01\u00c1\xb4\x01\u00c1\xb5\x01\u00c1\xb6\x01\u00c1\xb7\x01\u00c1\xb8\x01\u00c1\xb9\x01\u00c1\xba\x01\u00c1\xbb\x01\u00c1\xbc\x01\u00c1\xbd\x01\u00c1\xbe\x01\u00c1\xbf\x01\u00c1\xc0\x01\u00c1\xc1\x01\u00c1\xc2\x01\u00c1\xc3\x01\u00c1\xc4\x01\u00c1\xc5\x01\u00c1\xc6\x01\u00c1\xc7\x01\u00c1\xc8\x01\u00c1\xc9\x01\u00c1\xca\x01\u00c1\xcb\x01\u00c1\xcc\x01\u00c1\xcd\x01\u00c1\xce\x01\u00c1\xcf\x01\u00c1\xd0\x01\u00c1\xd1\x01\u00c1\xd2\x01\u00c1\xd3\x01\u00c1\xd4\x01\u00c1\xd5\x01\u00c1\xd6\x01\u00c1\xd7\x01\u00c1\xd8\x01\u00c1\xd9\x01\u00c1\xda\x01\u00c1\xdb\x01\u00c1\xdc\x01\u00c1\xdd\x01\u00c1\xde\x01\u00c1\xdf\x01\u00c1\xe0\x01\u00c1\xe1\x01\u00c1\xe2\x01\u00c1\xe3\x01\u00c1\xe4\x01\u00c1\xe5\x01\u00c1\xe6\x01\u00c1\xe7\x01\u00c1\xe8\x01\u00c1\xe9\x01\u00c1\xea\x01\u00c1\xeb\x01\u00c1\xec\x01\u00c1\xed\x01\u00c1\xee\x01\u00c1\xef\x01\u00c1\xf0\x01\u00c1\xf1\x01\u00c1\xf2\x01\u00c1\xf3\x01\u00c1\xf4\x01\u00c1\xf5\x01\u00c1\xf6\x01\u00c1\xf7\x01\u00c1\xf8\x01\u00c1\xf9\x01\u00c1\xfa\x01\u00c1\xfb\x01\u00c1\xfc\x01\u00c1\xfd\x01\u00c1\xfe\x01\u00c1\xff\x01\u0791i\x16\xa8{\x823?BE\x04f#\xb27\x94\xc6\\\x8bR\xb7\xd2\xdc\xc8\f\xd2\xe4\x00\x00\x00\xe1\x94\v\xe9I\x92\x8f\xf1\x99\xc9\xeb\xa9\xe1\x10\xdb!\n\xa5\xc9N\xfa\u040b|\x13\xbcK,\x13<V\x00\x00\x00\xe1\x94\f\x10\x00\x00\x00m{^#\xa1\xea\xeec\x7f(\xca2\xcd[1\x8bR\xb7\xd2\xdc\xc8\f\xd2\xe4\x00\x00\x00\xe0\x94\f51{z\x96\xc4T\xe2\xcb=\x1a%]wZ\xb1\x12\xcc\u020a\xd3\xc2\x1b\xce\xcc\xed\xa1\x00\x00\x00\xe0\x94\rs\x1c\xfa\xbcUt2\x98#\xf2mH\x84\x16E\x1d.\xa3v\x8a\xd3\xc2\x1b\xce\xcc\xed\xa1\x00\x00\x00\xe0\x94\x0ey\x06[_\x11\xb5\xbd\x1eb\xb95\xa6\x00\x97o\xff7T\xb9\x8a\xd3\xc2\x1b\xce\xcc\xed\xa1\x00\x00\x00\xe0\x94\x10P\x83\x92\x9b\xf9\xbb\"\xc2l\xb1w~\xc9&a\x17\rB\x85\x8a\xd3\xc2\x1b\xce\xcc\xed\xa1\x00\x00\x00\xe1\x94\x10\xf5\xd4XT\xe08\a\x14\x85\xac\x9e@#\b\u03c0\xd2\xd2\xfe\x8bR\xb7\xd2\xdc\xc8\f\xd2\xe4\x00\x00\x00\xe0\x94\x12h\xad\x18\x95&\xac\v8o\xaf\x06\xef\xfcFw\x9c4\x0e\xe6\x8a\xd3\xc2\x1b\xce\xcc\xed\xa1\x00\x00\x00\xe0\x94\x12\u02e5\x9fZt\u06c1\xa1/\xf6<4\x9b\xd8,\xbf`\a\u008a\xd3\xc2\x1b\xce\xcc\xed\xa1\x00\x00\x00\xe0\x94\x14F\xd7\xf6\xdf\x008\x0f$m\x82\x11\xde\x7f\x0f\xab\xc4\xfd$\x8c\x8a\xd3\xc2\x1b\xce\xcc\xed\xa1\x00\x00\x00\xe0\x94\x15\xe7\x19\xb6\xac\xaf\x1eD\x11\xbf\x0f\x95v\xcb\x1d\r\xb1a\xdd\xfc\x8a\xd3\xc2\x1b\xce\xcc\xed\xa1\x00\x00\x00\xe0\x94\x16N8\xa3u$zxJ\x81\xd4 \x1a\xa8\xfeNQ9!\x8a\xd3\xc2\x1b\xce\xcc\xed\xa1\x00\x00\x00\xe1\x94\x1bz\xa4@\x88\xa0\ua57d\xc6_\xefnPq\xe9F\xbf}\x8f\x8bR\xb7\xd2\xdc\xc8\f\xd2\xe4\x00\x00\x00\xe0\x94\"\"\"\"\"\"\xcfd\xa7j\xe3\xd3hY\x95\x8c\x86O\xda,\x8a\xd3\xc2\x1b\xce\xcc\xed\xa1\x00\x00\x00\xe1\x94/\x14X)G\u24a2\xec\xd2\fC\vF\xf2\xd2|\xfe!<\x8bR\xb7\xd2\xdc\xc8\f\xd2\xe4\x00\x00\x00\xe1\x94/,u\xb5\xdd]$a\x94\x81+\x00\uecf0\x9c,f\xe2\xee\x8bR\xb7\xd2\xdc\xc8\f\xd2\xe4\x00\x00\x00\xe0\x944\x1c@\xb9K\U000affe4%s\xcbx\xf1n\xe1Z\x05b8\x8a\xd3\xc2\x1b\xce\xcc\xed\xa1\x00\x00\x00\xe0\x944m\x82zu\xf9\x8f\nz2O\xf8\v|?\x90%.\x8b\xac\x8a\xd3\xc2\x1b\xce\xcc\xed\xa1\x00\x00\x00\xe0\x944\xf8Ew=Cd\x99\x9f/\xbcz\xa2j\xbd\xee\x90,\xbbF\x8a\xd3\xc2\x1b\xce\xcc\xed\xa1\x00\x00\x00\xe0\x94<uYA\x81\xe0>\x8e\u0344h\xa0\x03\x7f\x05\x8a\x9d\xaf\xady\x8a\xd3\xc2\x1b\xce\xcc\xed\xa1\x00\x00\x00\xf9!2\x94BBBBBBBBBBBBBBBBBBBB\x80\xf9!\x19\x80\xb9\x18\xd6`\x80`@R`\x046\x10a\x00?W`\x005`\xe0\x1c\x80c\x01\xff\u0267\x14a\x00DW\x80c\"\x89Q\x18\x14a\x00\xa4W\x80cb\x1f\xd10\x14a\x01\xbaW\x80c\xc5\xf2\x89/\x14a\x02DW[`\x00\x80\xfd[4\x80\x15a\x00PW`\x00\x80\xfd[Pa\x00\x90`\x04\x806\x03` \x81\x10\x15a\x00gW`\x00\x80\xfd[P5\x7f\xff\xff\xff\xff\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x16a\x02kV[`@\x80Q\x91\x15\x15\x82RQ\x90\x81\x90\x03` \x01\x90\xf3[a\x01\xb8`\x04\x806\x03`\x80\x81\x10\x15a\x00\xbaW`\x00\x80\xfd[\x81\x01\x90` \x81\x01\x815d\x01\x00\x00\x00\x00\x81\x11\x15a\x00\xd5W`\x00\x80\xfd[\x82\x01\x83` \x82\x01\x11\x15a\x00\xe7W`\x00\x80\xfd[\x805\x90` \x01\x91\x84`\x01\x83\x02\x84\x01\x11d\x01\x00\x00\x00\x00\x83\x11\x17\x15a\x01\tW`\x00\x80\xfd[\x91\x93\x90\x92\x90\x91` \x81\x01\x905d\x01\x00\x00\x00\x00\x81\x11\x15a\x01'W`\x00\x80\xfd[\x82\x01\x83` \x82\x01\x11\x15a\x019W`\x00\x80\xfd[\x805\x90` \x01\x91\x84`\x01\x83\x02\x84\x01\x11d\x01\x00\x00\x00\x00\x83\x11\x17\x15a\x01[W`\x00\x80\xfd[\x91\x93\x90\x92\x90\x91` \x81\x01\x905d\x01\x00\x00\x00\x00\x81\x11\x15a\x01yW`\x00\x80\xfd[\x82\x01\x83` \x82\x01\x11\x15a\x01\x8bW`\x00\x80\xfd[\x805\x90` \x01\x91\x84`\x01\x83\x02\x84\x01\x11d\x01\x00\x00\x00\x00\x83\x11\x17\x15a\x01\xadW`\x00\x80\xfd[\x91\x93P\x91P5a\x03\x04V[\x00[4\x80\x15a\x01\xc6W`\x00\x80\xfd[Pa\x01\xcfa\x10\xb5V[`@\x80Q` \x80\x82R\x83Q\x81\x83\x01R\x83Q\x91\x92\x83\x92\x90\x83\x01\x91\x85\x01\x90\x80\x83\x83`\x00[\x83\x81\x10\x15a\x02\tW\x81\x81\x01Q\x83\x82\x01R` \x01a\x01\xf1V[PPPP\x90P\x90\x81\x01\x90`\x1f\x16\x80\x15a\x026W\x80\x82\x03\x80Q`\x01\x83` \x03a\x01\x00\n\x03\x19\x16\x81R` \x01\x91P[P\x92PPP`@Q\x80\x91\x03\x90\xf3[4\x80\x15a\x02PW`\x00\x80\xfd[Pa\x02Ya\x10\xc7V[`@\x80Q\x91\x82RQ\x90\x81\x90\x03` \x01\x90\xf3[`\x00\x7f\xff\xff\xff\xff\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x82\x16\x7f\x01\xff\u0267\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x14\x80a\x02\xfeWP\x7f\xff\xff\xff\xff\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x82\x16\x7f\x85d\t\a\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x14[\x92\x91PPV[`0\x86\x14a\x03]W`@Q\x7f\b\xc3y\xa0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x81R`\x04\x01\x80\x80` \x01\x82\x81\x03\x82R`&\x81R` \x01\x80a\x18\x05`&\x919`@\x01\x91PP`@Q\x80\x91\x03\x90\xfd[` \x84\x14a\x03\xb6W`@Q\x7f\b\xc3y\xa0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x81R`\x04\x01\x80\x80` \x01\x82\x81\x03\x82R`6\x81R` \x01\x80a\x17\x9c`6\x919`@\x01\x91PP`@Q\x80\x91\x03\x90\xfd[``\x82\x14a\x04\x0fW`@Q\x7f\b\xc3y\xa0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x81R`\x04\x01\x80\x80` \x01\x82\x81\x03\x82R`)\x81R` \x01\x80a\x18x`)\x919`@\x01\x91PP`@Q\x80\x91\x03\x90\xfd[g\r\u0db3\xa7d\x00\x004\x10\x15a\x04pW`@Q\x7f\b\xc3y\xa0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x81R`\x04\x01\x80\x80` \x01\x82\x81\x03\x82R`&\x81R` \x01\x80a\x18R`&\x919`@\x01\x91PP`@Q\x80\x91\x03\x90\xfd[c;\x9a\xca\x004\x06\x15a\x04\xcdW`@Q\x7f\b\xc3y\xa0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x81R`\x04\x01\x80\x80` \x01\x82\x81\x03\x82R`3\x81R` \x01\x80a\x17\xd2`3\x919`@\x01\x91PP`@Q\x80\x91\x03\x90\xfd[c;\x9a\xca\x004\x04g\xff\xff\xff\xff\xff\xff\xff\xff\x81\x11\x15a\x055W`@Q\x7f\b\xc3y\xa0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x81R`\x04\x01\x80\x80` \x01\x82\x81\x03\x82R`'\x81R` \x01\x80a\x18+`'\x919`@\x01\x91PP`@Q\x80\x91\x03\x90\xfd[``a\x05@\x82a\x14\xbaV[\x90P\x7fd\x9b\xbcb\xd0\xe3\x13B\xaf\xeaN\\\xd8-@I\xe7\xe1\xee\x91/\xc0\x88\x9a\xa7\x90\x80;\xe3\x908\u0149\x89\x89\x89\x85\x8a\x8aa\x05u` Ta\x14\xbaV[`@\x80Q`\xa0\x80\x82R\x81\x01\x89\x90R\x90\x81\x90` \x82\x01\x90\x82\x01``\x83\x01`\x80\x84\x01`\xc0\x85\x01\x8e\x8e\x80\x82\x847`\x00\x83\x82\x01R`\x1f\x01\x7f\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xe0\x16\x90\x91\x01\x87\x81\x03\x86R\x8c\x81R` \x01\x90P\x8c\x8c\x80\x82\x847`\x00\x83\x82\x01\x81\x90R`\x1f\x90\x91\x01\x7f\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xe0\x16\x90\x92\x01\x88\x81\x03\x86R\x8cQ\x81R\x8cQ` \x91\x82\x01\x93\x91\x8e\x01\x92P\x90\x81\x90\x84\x90\x84\x90[\x83\x81\x10\x15a\x06HW\x81\x81\x01Q\x83\x82\x01R` \x01a\x060V[PPPP\x90P\x90\x81\x01\x90`\x1f\x16\x80\x15a\x06uW\x80\x82\x03\x80Q`\x01\x83` \x03a\x01\x00\n\x03\x19\x16\x81R` \x01\x91P[P\x86\x81\x03\x83R\x88\x81R` \x01\x89\x89\x80\x82\x847`\x00\x83\x82\x01\x81\x90R`\x1f\x90\x91\x01\x7f\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xe0\x16\x90\x92\x01\x88\x81\x03\x84R\x89Q\x81R\x89Q` \x91\x82\x01\x93\x91\x8b\x01\x92P\x90\x81\x90\x84\x90\x84\x90[\x83\x81\x10\x15a\x06\xefW\x81\x81\x01Q\x83\x82\x01R` \x01a\x06\xd7V[PPPP\x90P\x90\x81\x01\x90`\x1f\x16\x80\x15a\a\x1cW\x80\x82\x03\x80Q`\x01\x83` \x03a\x01\x00\n\x03\x19\x16\x81R` \x01\x91P[P\x9dPPPPPPPPPPPPPP`@Q\x80\x91\x03\x90\xa1`\x00`\x02\x8a\x8a`\x00`\x80\x1b`@Q` \x01\x80\x84\x84\x80\x82\x847\x7f\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x90\x94\x16\x91\x90\x93\x01\x90\x81R`@\x80Q\x7f\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xf0\x81\x84\x03\x01\x81R`\x10\x90\x92\x01\x90\x81\x90R\x81Q\x91\x95P\x93P\x83\x92P` \x85\x01\x91P\x80\x83\x83[` \x83\x10a\a\xfcW\x80Q\x82R\x7f\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xe0\x90\x92\x01\x91` \x91\x82\x01\x91\x01a\a\xbfV[Q\x81Q` \x93\x84\x03a\x01\x00\n\x7f\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x01\x80\x19\x90\x92\x16\x91\x16\x17\x90R`@Q\x91\x90\x93\x01\x94P\x91\x92PP\x80\x83\x03\x81\x85Z\xfa\x15\x80\x15a\bYW=`\x00\x80>=`\x00\xfd[PPP`@Q=` \x81\x10\x15a\bnW`\x00\x80\xfd[PQ\x90P`\x00`\x02\x80a\b\x84`@\x84\x8a\x8ca\x16\xfeV[`@Q` \x01\x80\x83\x83\x80\x82\x847\x80\x83\x01\x92PPP\x92PPP`@Q` \x81\x83\x03\x03\x81R\x90`@R`@Q\x80\x82\x80Q\x90` \x01\x90\x80\x83\x83[` \x83\x10a\b\xf8W\x80Q\x82R\x7f\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xe0\x90\x92\x01\x91` \x91\x82\x01\x91\x01a\b\xbbV[Q\x81Q` \x93\x84\x03a\x01\x00\n\x7f\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x01\x80\x19\x90\x92\x16\x91\x16\x17\x90R`@Q\x91\x90\x93\x01\x94P\x91\x92PP\x80\x83\x03\x81\x85Z\xfa\x15\x80\x15a\tUW=`\x00\x80>=`\x00\xfd[PPP`@Q=` \x81\x10\x15a\tjW`\x00\x80\xfd[PQ`\x02a\t{\x89`@\x81\x8da\x16\xfeV[`@Q`\x00\x90` \x01\x80\x84\x84\x80\x82\x847\x91\x90\x91\x01\x92\x83RPP`@\x80Q\x80\x83\x03\x81R` \x92\x83\x01\x91\x82\x90R\x80Q\x90\x94P\x90\x92P\x82\x91\x84\x01\x90\x80\x83\x83[` \x83\x10a\t\xf4W\x80Q\x82R\x7f\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xe0\x90\x92\x01\x91` \x91\x82\x01\x91\x01a\t\xb7V[Q\x81Q` \x93\x84\x03a\x01\x00\n\x7f\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x01\x80\x19\x90\x92\x16\x91\x16\x17\x90R`@Q\x91\x90\x93\x01\x94P\x91\x92PP\x80\x83\x03\x81\x85Z\xfa\x15\x80\x15a\nQW=`\x00\x80>=`\x00\xfd[PPP`@Q=` \x81\x10\x15a\nfW`\x00\x80\xfd[PQ`@\x80Q` \x81\x81\x01\x94\x90\x94R\x80\x82\x01\x92\x90\x92R\x80Q\x80\x83\x03\x82\x01\x81R``\x90\x92\x01\x90\x81\x90R\x81Q\x91\x92\x90\x91\x82\x91\x84\x01\x90\x80\x83\x83[` \x83\x10a\n\xdaW\x80Q\x82R\x7f\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xe0\x90\x92\x01\x91` \x91\x82\x01\x91\x01a\n\x9dV[Q\x81Q` \x93\x84\x03a\x01\x00\n\x7f\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x01\x80\x19\x90\x92\x16\x91\x16\x17\x90R`@Q\x91\x90\x93\x01\x94P\x91\x92PP\x80\x83\x03\x81\x85Z\xfa\x15\x80\x15a\v7W=`\x00\x80>=`\x00\xfd[PPP`@Q=` \x81\x10\x15a\vLW`\x00\x80\xfd[PQ`@\x80Q` \x81\x01\x85\x81R\x92\x93P`\x00\x92`\x02\x92\x83\x92\x87\x92\x8f\x92\x8f\x92\x01\x83\x83\x80\x82\x847\x80\x83\x01\x92PPP\x93PPPP`@Q` \x81\x83\x03\x03\x81R\x90`@R`@Q\x80\x82\x80Q\x90` \x01\x90\x80\x83\x83[` \x83\x10a\v\xd9W\x80Q\x82R\x7f\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xe0\x90\x92\x01\x91` \x91\x82\x01\x91\x01a\v\x9cV[Q\x81Q` \x93\x84\x03a\x01\x00\n\x7f\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x01\x80\x19\x90\x92\x16\x91\x16\x17\x90R`@Q\x91\x90\x93\x01\x94P\x91\x92PP\x80\x83\x03\x81\x85Z\xfa\x15\x80\x15a\f6W=`\x00\x80>=`\x00\xfd[PPP`@Q=` \x81\x10\x15a\fKW`\x00\x80\xfd[PQ`@Q\x86Q`\x02\x91\x88\x91`\x00\x91\x88\x91` \x91\x82\x01\x91\x82\x91\x90\x86\x01\x90\x80\x83\x83[` \x83\x10a\f\xa9W\x80Q\x82R\x7f\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xe0\x90\x92\x01\x91` \x91\x82\x01\x91\x01a\flV[`\x01\x83` \x03a\x01\x00\n\x03\x80\x19\x82Q\x16\x81\x84Q\x16\x80\x82\x17\x85RPPPPPP\x90P\x01\x83g\xff\xff\xff\xff\xff\xff\xff\xff\x19\x16g\xff\xff\xff\xff\xff\xff\xff\xff\x19\x16\x81R`\x18\x01\x82\x81R` \x01\x93PPPP`@Q` \x81\x83\x03\x03\x81R\x90`@R`@Q\x80\x82\x80Q\x90` \x01\x90\x80\x83\x83[` \x83\x10a\rNW\x80Q\x82R\x7f\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xe0\x90\x92\x01\x91` \x91\x82\x01\x91\x01a\r\x11V[Q\x81Q` \x93\x84\x03a\x01\x00\n\x7f\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x01\x80\x19\x90\x92\x16\x91\x16\x17\x90R`@Q\x91\x90\x93\x01\x94P\x91\x92PP\x80\x83\x03\x81\x85Z\xfa\x15\x80\x15a\r\xabW=`\x00\x80>=`\x00\xfd[PPP`@Q=` \x81\x10\x15a\r\xc0W`\x00\x80\xfd[PQ`@\x80Q` \x81\x81\x01\x94\x90\x94R\x80\x82\x01\x92\x90\x92R\x80Q\x80\x83\x03\x82\x01\x81R``\x90\x92\x01\x90\x81\x90R\x81Q\x91\x92\x90\x91\x82\x91\x84\x01\x90\x80\x83\x83[` \x83\x10a\x0e4W\x80Q\x82R\x7f\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xe0\x90\x92\x01\x91` \x91\x82\x01\x91\x01a\r\xf7V[Q\x81Q` \x93\x84\x03a\x01\x00\n\x7f\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x01\x80\x19\x90\x92\x16\x91\x16\x17\x90R`@Q\x91\x90\x93\x01\x94P\x91\x92PP\x80\x83\x03\x81\x85Z\xfa\x15\x80\x15a\x0e\x91W=`\x00\x80>=`\x00\xfd[PPP`@Q=` \x81\x10\x15a\x0e\xa6W`\x00\x80\xfd[PQ\x90P\x85\x81\x14a\x0f\x02W`@Q\x7f\b\xc3y\xa0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x81R`\x04\x01\x80\x80` \x01\x82\x81\x03\x82R`T\x81R` \x01\x80a\x17H`T\x919``\x01\x91PP`@Q\x80\x91\x03\x90\xfd[` Tc\xff\xff\xff\xff\x11a\x0f`W`@Q\x7f\b\xc3y\xa0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x81R`\x04\x01\x80\x80` \x01\x82\x81\x03\x82R`!\x81R` \x01\x80a\x17'`!\x919`@\x01\x91PP`@Q\x80\x91\x03\x90\xfd[` \x80T`\x01\x01\x90\x81\x90U`\x00[` \x81\x10\x15a\x10\xa9W\x81`\x01\x16`\x01\x14\x15a\x0f\xa0W\x82`\x00\x82` \x81\x10a\x0f\x91W\xfe[\x01UPa\x10\xac\x95PPPPPPV[`\x02`\x00\x82` \x81\x10a\x0f\xafW\xfe[\x01T\x84`@Q` \x01\x80\x83\x81R` \x01\x82\x81R` \x01\x92PPP`@Q` \x81\x83\x03\x03\x81R\x90`@R`@Q\x80\x82\x80Q\x90` \x01\x90\x80\x83\x83[` \x83\x10a\x10%W\x80Q\x82R\x7f\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xe0\x90\x92\x01\x91` \x91\x82\x01\x91\x01a\x0f\xe8V[Q\x81Q` \x93\x84\x03a\x01\x00\n\x7f\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x01\x80\x19\x90\x92\x16\x91\x16\x17\x90R`@Q\x91\x90\x93\x01\x94P\x91\x92PP\x80\x83\x03\x81\x85Z\xfa\x15\x80\x15a\x10\x82W=`\x00\x80>=`\x00\xfd[PPP`@Q=` \x81\x10\x15a\x10\x97W`\x00\x80\xfd[PQ\x92P`\x02\x82\x04\x91P`\x01\x01a\x0fnV[P\xfe[PPPPPPPV[``a\x10\xc2` Ta\x14\xbaV[\x90P\x90V[` T`\x00\x90\x81\x90\x81[` \x81\x10\x15a\x12\xf0W\x81`\x01\x16`\x01\x14\x15a\x11\xe6W`\x02`\x00\x82` \x81\x10a\x10\xf5W\xfe[\x01T\x84`@Q` \x01\x80\x83\x81R` \x01\x82\x81R` \x01\x92PPP`@Q` \x81\x83\x03\x03\x81R\x90`@R`@Q\x80\x82\x80Q\x90` \x01\x90\x80\x83\x83[` \x83\x10a\x11kW\x80Q\x82R\x7f\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xe0\x90\x92\x01\x91` \x91\x82\x01\x91\x01a\x11.V[Q\x81Q` \x93\x84\x03a\x01\x00\n\x7f\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x01\x80\x19\x90\x92\x16\x91\x16\x17\x90R`@Q\x91\x90\x93\x01\x94P\x91\x92PP\x80\x83\x03\x81\x85Z\xfa\x15\x80\x15a\x11\xc8W=`\x00\x80>=`\x00\xfd[PPP`@Q=` \x81\x10\x15a\x11\xddW`\x00\x80\xfd[PQ\x92Pa\x12\xe2V[`\x02\x83`!\x83` \x81\x10a\x11\xf6W\xfe[\x01T`@Q` \x01\x80\x83\x81R` \x01\x82\x81R` \x01\x92PPP`@Q` \x81\x83\x03\x03\x81R\x90`@R`@Q\x80\x82\x80Q\x90` \x01\x90\x80\x83\x83[` \x83\x10a\x12kW\x80Q\x82R\x7f\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xe0\x90\x92\x01\x91` \x91\x82\x01\x91\x01a\x12.V[Q\x81Q` \x93\x84\x03a\x01\x00\n\x7f\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x01\x80\x19\x90\x92\x16\x91\x16\x17\x90R`@Q\x91\x90\x93\x01\x94P\x91\x92PP\x80\x83\x03\x81\x85Z\xfa\x15\x80\x15a\x12\xc8W=`\x00\x80>=`\x00\xfd[PPP`@Q=` \x81\x10\x15a\x12\xddW`\x00\x80\xfd[PQ\x92P[`\x02\x82\x04\x91P`\x01\x01a\x10\xd1V[P`\x02\x82a\x12\xff` Ta\x14\xbaV[`\x00`@\x1b`@Q` \x01\x80\x84\x81R` \x01\x83\x80Q\x90` \x01\x90\x80\x83\x83[` \x83\x10a\x13ZW\x80Q\x82R\x7f\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xe0\x90\x92\x01\x91` \x91\x82\x01\x91\x01a\x13\x1dV[Q\x81Q` \x93\x84\x03a\x01\x00\n\x7f\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x01\x80\x19\x90\x92\x16\x91\x16\x17\x90R\x7f\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x00\x00\x00\x00\x00\x00\x00\x00\x95\x90\x95\x16\x92\x01\x91\x82RP`@\x80Q\x80\x83\x03\x7f\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xf8\x01\x81R`\x18\x90\x92\x01\x90\x81\x90R\x81Q\x91\x95P\x93P\x83\x92\x85\x01\x91P\x80\x83\x83[` \x83\x10a\x14?W\x80Q\x82R\x7f\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xe0\x90\x92\x01\x91` \x91\x82\x01\x91\x01a\x14\x02V[Q\x81Q` \x93\x84\x03a\x01\x00\n\x7f\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x01\x80\x19\x90\x92\x16\x91\x16\x17\x90R`@Q\x91\x90\x93\x01\x94P\x91\x92PP\x80\x83\x03\x81\x85Z\xfa\x15\x80\x15a\x14\x9cW=`\x00\x80>=`\x00\xfd[PPP`@Q=` \x81\x10\x15a\x14\xb1W`\x00\x80\xfd[PQ\x92PPP\x90V[`@\x80Q`\b\x80\x82R\x81\x83\x01\x90\x92R``\x91` \x82\x01\x81\x806\x837\x01\x90PP\x90P`\xc0\x82\x90\x1b\x80`\a\x1a`\xf8\x1b\x82`\x00\x81Q\x81\x10a\x14\xf4W\xfe[` \x01\x01\x90~\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x19\x16\x90\x81`\x00\x1a\x90SP\x80`\x06\x1a`\xf8\x1b\x82`\x01\x81Q\x81\x10a\x157W\xfe[` \x01\x01\x90~\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x19\x16\x90\x81`\x00\x1a\x90SP\x80`\x05\x1a`\xf8\x1b\x82`\x02\x81Q\x81\x10a\x15zW\xfe[` \x01\x01\x90~\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x19\x16\x90\x81`\x00\x1a\x90SP\x80`\x04\x1a`\xf8\x1b\x82`\x03\x81Q\x81\x10a\x15\xbdW\xfe[` \x01\x01\x90~\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x19\x16\x90\x81`\x00\x1a\x90SP\x80`\x03\x1a`\xf8\x1b\x82`\x04\x81Q\x81\x10a\x16\x00W\xfe[` \x01\x01\x90~\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x19\x16\x90\x81`\x00\x1a\x90SP\x80`\x02\x1a`\xf8\x1b\x82`\x05\x81Q\x81\x10a\x16CW\xfe[` \x01\x01\x90~\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x19\x16\x90\x81`\x00\x1a\x90SP\x80`\x01\x1a`\xf8\x1b\x82`\x06\x81Q\x81\x10a\x16\x86W\xfe[` \x01\x01\x90~\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x19\x16\x90\x81`\x00\x1a\x90SP\x80`\x00\x1a`\xf8\x1b\x82`\a\x81Q\x81\x10a\x16\xc9W\xfe[` \x01\x01\x90~\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x19\x16\x90\x81`\x00\x1a\x90SPP\x91\x90PV[`\x00\x80\x85\x85\x11\x15a\x17\rW\x81\x82\xfd[\x83\x86\x11\x15a\x17\x19W\x81\x82\xfd[PP\x82\x01\x93\x91\x90\x92\x03\x91PV\xfeDepositContract: merkle tree fullDepositContract: reconstructed DepositData does not match supplied deposit_data_rootDepositContract: invalid withdrawal_credentials lengthDepositContract: deposit value not multiple of gweiDepositContract: invalid pubkey lengthDepositContract: deposit value too highDepositContract: deposit value too lowDepositContract: invalid signature length\xa2dipfsX\"\x12 \x1d\xd2o7\xa6!p0\t\xab\xf1nw\u6713\xdcP\u01dd\xb7\xf6\xcc7T>>\x0e=\xec\u0717dsolcC\x00\x06\v\x003\xf9\b<\xf8B\xa0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\"\xa0\xf5\xa5\xfdB\xd1j 0'\x98\xefn\xd3\t\x97\x9bC\x00=# \xd9\xf0\xe8\xea\x981\xa9'Y\xfbK\xf8B\xa0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00#\xa0\xdbV\x11N\x00\xfd\xd4\xc1\xf8\\\x89+\xf3Z\u0268\x92\x89\xaa\xec\xb1\xeb\u0429l\xde`jt\x8b]q\xf8B\xa0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00$\xa0\u01c0\t\xfd\xf0\x7f\xc5j\x11\xf1\"7\x06X\xa3S\xaa\xa5B\xedc\xe4LK\xc1_\xf4\xcd\x10Z\xb3<\xf8B\xa0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00%\xa0Sm\x98\x83\x7f-\xd1e\xa5]^\xea\xe9\x14\x85\x95Dr\xd5o$m\xf2V\xbf<\xae\x195*\x12<\xf8B\xa0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00&\xa0\x9e\xfd\xe0R\xaa\x15B\x9f\xae\x05\xba\xd4\u0431\xd7\xc6M\xa6M\x03\u05e1\x85JX\x8c,\xb8C\f\r0\xf8B\xa0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'\xa0\u060d\xdf\xee\xd4\x00\xa8uU\x96\xb2\x19B\xc1I~\x11L0.a\x18)\x0f\x91\xe6w)v\x04\x1f\xa1\xf8B\xa0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00(\xa0\x87\xeb\r\u06e5~5\xf6\u0486g8\x02\xa4\xafYu\xe2%\x06\xc7\xcfLd\xbbk\xe5\xee\x11R\x7f,\xf8B\xa0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00)\xa0&\x84dv\xfd_\xc5J]C8Qg\xc9QD\xf2d?S<\xc8[\xb9\xd1kx/\x8d}\xb1\x93\xf8B\xa0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00*\xa0Pm\x86X-%$\x05\xb8@\x01\x87\x92\xca\u04bf\x12Y\xf1\xefZ\xa5\xf8\x87\xe1<\xb2\xf0\tOQ\xe1\xf8B\xa0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00+\xa0\xff\xff\n\xd7\xe6Yw/\x954\xc1\x95\xc8\x15\xef\xc4\x01N\xf1\xe1\xda\xedD\x04\xc0c\x85\xd1\x11\x92\xe9+\xf8B\xa0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00,\xa0l\xf0A'\xdb\x05D\x1c\xd83\x10zR\xbe\x85(h\x89\x0eC\x17\xe6\xa0*\xb4v\x83\xaau\x96B \xf8B\xa0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00-\xa0\xb7\xd0_\x87_\x14\x00'\xefQ\x18\xa2${\xbb\x84\u038f/\x0f\x11#b0\x85\xda\xf7\x96\f2\x9f_\xf8B\xa0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00.\xa0\xdfj\xf5\xf5\xbb\xdbk\xe9\uf2a6\x18\u4fc0s\x96\bg\x17\x1e)go\x8b(M\xeaj\b\xa8^\xf8B\xa0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00/\xa0\xb5\x8d\x90\x0f^\x18.<P\xeft\x96\x9e\xa1lw&\xc5Iu|\xc25#\xc3iX}\xa7)7\x84\xf8B\xa0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x000\xa0\u051au\x02\xff\u03f04\v\x1dx\x85h\x85\x00\xca0\x81a\xa7\xf9kb\u07dd\b;q\xfc\xc8\xf2\xbb\xf8B\xa0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x001\xa0\x8f\xe6\xb1h\x92V\xc0\u04c5\xf4/[\xbe '\xa2,\x19\x96\xe1\x10\xba\x97\xc1q\xd3\u550d\xe9+\xeb\xf8B\xa0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x002\xa0\x8d\rc\u00de\xba\u0785\t\xe0\xae<\x9c8v\xfb_\xa1\x12\xbe\x18\xf9\x05\xec\xac\xfe\u02d2\x05v\x03\xab\xf8B\xa0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x003\xa0\x95\xee\u0232\xe5A\xca\xd4\xe9\x1d\u30c5\xf2\xe0Fa\x9fTIl#\x82\xcbl\xac\u0579\x8c&\xf5\xa4\xf8B\xa0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004\xa0\xf8\x93\xe9\b\x91wu\xb6+\xff#)M\xbb\xe3\xa1\u034el\xc1\xc3[H\x01\x88{djo\x81\xf1\x7f\xf8B\xa0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x005\xa0\xcd\u06e7\xb5\x92\xe3\x133\x93\xc1a\x94\xfa\xc7C\x1a\xbf/T\x85\xedq\x1d\xb2\x82\x18<\x81\x9e\b\xeb\xaa\xf8B\xa0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x006\xa0\x8a\x8d\x7f\u3bcc\xaa\bZv9\xa82\x00\x14W\u07f9\x12\x8a\x80a\x14*\xd03V)\xff#\xff\x9c\xf8B\xa0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x007\xa0\xfe\xb3\xc37\u05e5\x1ao\xbf\x00\xb9\xe3LR\xe1\xc9\x19\\\x96\x9b\xd4\u783f\xd5\x1d\\[\xed\x9c\x11g\xf8B\xa0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x008\xa0\xe7\x1f\n\xa8<\xc3.\u07fe\xfa\x9fM>\x01t\u0285\x18.\xec\x9f:\t\xf6\xa6\xc0\xdfcw\xa5\x10\xd7\xf8B\xa0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x009\xa01 o\xa8\nP\xbbj\xbe)\bPX\xf1b\x12!*`\xee\xc8\xf0I\xfe\u02d2\xd8\xc8\xe0\xa8K\xc0\xf8B\xa0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00:\xa0!5+\xfe\xcb\xed\xdd\u94c3\x9faL=\xac\n>\xe3uC\xf9\xb4\x12\xb1a\x99\xdc\x15\x8e#\xb5D\xf8B\xa0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00;\xa0a\x9e1'$\xbbm|1S\xed\x9d\xe7\x91\xd7d\xa3f\xb3\x89\xaf\x13\u014b\xf8\xa8\xd9\x04\x81\xa4ge\xf8B\xa0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00<\xa0|\xdd)\x86&\x82Pb\x8d\f\x10\xe3\x85\u014ca\x91\xe6\xfb\xe0Q\x91\xbc\xc0O\x13?,\xear\xc1\xc4\xf8B\xa0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00=\xa0\x84\x890\xbd{\xa8\xca\xc5Fa\a!\x13\xfb'\x88i\xe0{\xb8X\x7f\x919)37M\x01{\xcb\xe1\xf8B\xa0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00>\xa0\x88i\xff,\"\xb2\x8c\xc1\x05\x10\u06452\x92\x803(\xbeO\xb0\xe8\x04\x95\u8ecd'\x1f[\x88\x966\xf8B\xa0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00?\xa0\xb5\xfe(\xe7\x9f\x1b\x85\x0f\x86X$l\u9da1\u7d1f\xc0m\xb7\x14>\x8f\xe0\xb4\xf2\xb0\xc5R:\\\xf8B\xa0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00@\xa0\x98^\x92\x9fp\xaf(\u043d\u0469\n\x80\x8f\x97\x7fY||w\x8cH\x9e\x98\u04fd\x89\x10\xd3\x1a\xc0\xf7\xe1\x94F#\x96\u677f\xa4U\xf4\x05\xf4\u0742\xf3\x01J\xf8\x00;r\x8b\xa5o\xa5\xb9\x90\x19\xa5\xc8\x00\x00\x00\xe0\x94I\xdf<\xca&p\xeb\rY\x11F\xb1cY\xfe3nGo)\x8a\xd3\xc2\x1b\xce\xcc\xed\xa1\x00\x00\x00\xe1\x94K\xc6V\xb3M\xe28\x96\xfa`i\u0246/5[t\x04\x01\xaf\x8b\bE\x95\x16\x14\x01HJ\x00\x00\x00\xe0\x94M\v\x04\xb4\x05\u01b6,|\xfc:\xe5GYt~,\vFb\x8a\xd3\xc2\x1b\xce\xcc\xed\xa1\x00\x00\x00\xe1\x94MIl\xcc(\x05\x8b\x1dt\xb7\xa1\x95Af>!\x15O\x9c\x84\x8bR\xb7\xd2\xdc\xc8\f\xd2\xe4\x00\x00\x00\xe1\x94P\x9avg\xac\x8d\x03 \xe3ar\xc1\x92Pja\x88\xaa\x84\xf6\x8b|\x13\xbcK,\x13<V\x00\x00\x00\xe0\x94Q\x80\xdb\x027)\x1adI\u0769\xed3\xad\x90\xa3\x87\x87b\x1c\x8a\xd3\xc2\x1b\xce\xcc\xed\xa1\x00\x00\x00\xe0\x94Rs\x0f4}\xefk\xa0\x9a\xdf\xf6.\xac`\xd5\xfe\xe8 [\u010a\xd3\xc2\x1b\xce\xcc\xed\xa1\x00\x00\x00\xe0\x94^\xac\x0f\xbd=\xfe\xf8\xae>\xfa<]\xc1\xaa\x19;\xc6\x03=\xfd\x8a\xd3\xc2\x1b\xce\xcc\xed\xa1\x00\x00\x00\xe1\x94jz\xa9\xb8\x82\xd5\v\xb7\xbc]\xa1\xa2Dq\x9c\x99\xf1/\x06\xa3\x8bR\xb7\xd2\xdc\xc8\f\xd2\xe4\x00\x00\x00\xe1\x94l\xc99|;8s\x9d\xac\xbf\xaah\xea\xd5\xf5\xd7{\xa5\xf4U\x8bR\xb7\xd2\xdc\xc8\f\xd2\xe4\x00\x00\x00\xe1\x94s\xb2\xe0\xe5E\x10#\x9e\"\u0313o\vJm\xe1\xac\xf0\xab\u078bR\xb7\xd2\xdc\xc8\f\xd2\xe4\x00\x00\x00\xe0\x94v,\xa6,\xa2T\x9a\xd8\x06v;:\xa1\xea1|B\x9b\xdb\u068a\xd3\xc2\x1b\xce\xcc\xed\xa1\x00\x00\x00\xe1\x94w\x8f_\x13\u013ex\xa3\xa4\xd7\x14\x1b\xcb&\x99\x97\x02\xf4\a\u03cbR\xb7\xd2\xdc\xc8\f\xd2\xe4\x00\x00\x00\xe0\x94\x83M\xbfZ\x03\xe2\x9c%\xbcUE\x9c\u039c\x02\x1e\xeb\xe6v\xad\x8a\xd3\xc2\x1b\xce\xcc\xed\xa1\x00\x00\x00\xe0\x94\x87]%\xeeK\xc6\x04\xc7\x1b\xafb6\xa8H\x8f\"9\x9b\xedK\x8a\xd3\xc2\x1b\xce\xcc\xed\xa1\x00\x00\x00\u150d\xf7\x87\x8d5q\xbe\xf5\xe5\xa7D\xf9b\x87\xc8\xd2\x03\x86\xd7Z\x8bR\xb7\xd2\xdc\xc8\f\xd2\xe4\x00\x00\x00\xe0\x94\x9eAZ\to\xf7vP\u0712]\xeaTe\x85\xb4\xad\xb3\"\xb6\x8a\xd3\xc2\x1b\xce\xcc\xed\xa1\x00\x00\x00\xe0\x94\xa0vke\xa4\xf7\xb1\xday\xa1\xafy\xaciTV\uf886D\x8a\xd3\xc2\x1b\xce\xcc\xed\xa1\x00\x00\x00\xe0\x94\xa2\x9b\x14JD\x9eAJG,`\u01ea\xf1\xaa\xff\xe3)\x02\x1d\x8a\xd3\xc2\x1b\xce\xcc\xed\xa1\x00\x00\x00\xe0\x94\xa5S\x95Vk\vT9[2F\xf9j\v\xdcK\x8aH=\xf9\x8a\xd3\xc2\x1b\xce\xcc\xed\xa1\x00\x00\x00\xe0\x94\xac\x9b\xa7/\xb6\x1a\xa7\xc3\x1a\x95\xdf\n\x8bn\xbaoA\xef\x87^\x8a\xd3\xc2\x1b\xce\xcc\xed\xa1\x00\x00\x00\xe0\x94\xb0I\x8c\x15\x87\x9d\xb2\xeeTq\u0512l_\xaa%\u0260\x96\x83\x8a\xd3\xc2\x1b\xce\xcc\xed\xa1\x00\x00\x00\xe0\x94\xb0J\xef*=-\x86\xb0\x10\x06\xcc\xd43\x9a.\x94=\x9cd\x80\x8a\xd3\xc2\x1b\xce\xcc\xed\xa1\x00\x00\x00\u1531\x9f\xb4\xc1\xf2\x802~`\xed7\xb1\xdcn\xe7u3S\x93\x14\x8bR\xb7\xd2\xdc\xc8\f\xd2\xe4\x00\x00\x00\xe0\x94\xbb\x97{.\xe8\xa1\x11\u05c8\xb3G}$ x\u04387\xe7+\x8a\xd3\xc2\x1b\xce\xcc\xed\xa1\x00\x00\x00\xe0\x94\xc2\x1c\xb9\u025c1m\x18c\x14/}\xd8m\xd5Im\x81\xa8\u058a\xd3\xc2\x1b\xce\xcc\xed\xa1\x00\x00\x00\xe0\x94\xc4s\xd4\x12\xdcR\xe3I\x86\"\t\x92L\x89\x81\xb2\xeeB\ah\x8a\xd3\xc2\x1b\xce\xcc\xed\xa1\x00\x00\x00\xe1\x94\u010e#\xc5\xf6\xe1\xea\v\xae\xf6S\a4\xed\u00d6\x8fy\xaf.\x8bR\xb7\xd2\xdc\xc8\f\xd2\xe4\x00\x00\x00\xe1\x94\xc6\xe2E\x99\x91\xbf\xe2|\xcam\x86r/5\xda#\xa1\xe4\u02d7\x8bR\xb7\xd2\xdc\xc8\f\xd2\xe4\x00\x00\x00\xe0\x94\xc9\xca+\xa9\xa2}\xe1\xdbX\x9d\x8c3\xab\x8e\u07e2\x11\x1b1\xfb\x8a\xd3\xc2\x1b\xce\xcc\xed\xa1\x00\x00\x00\xe0\x94\xd1\xf7~L\x1cE\x18n\x86S\u0109\xf9\x0e\x00\x8asYr\x96\x8a\xd3\xc2\x1b\xce\xcc\xed\xa1\x00\x00\x00\xe2\x94\u04d9NM2\x02\xdd#\xc8I}\x7fu\xbf\x16G\xd1\xda\x1b\xb1\x8c\x01\x9d\x97\x1eO\xe8@\x1et\x00\x00\x00\xe0\x94\u0726\u9d0e\xa8j\xeb\xfd\xf9\x92\x99I\x12@B)kn4\x8a\xd3\xc2\x1b\xce\xcc\xed\xa1\x00\x00\x00\xe0\x94\xe0\x99\x1e\x84@A\xbeo\x11\xb9\x9d\xa5\xb1\x14\xb6\xbc\xf8N\xbdW\x8a\xd3\xc2\x1b\xce\xcc\xed\xa1\x00\x00\x00\xe1\x94\u08bdBX\xd2v\x887\xba\xa2j(\xfeq\xdc\a\x9f\x84\u01cbR\xb7\xd2\xdc\xc8\f\xd2\xe4\x00\x00\x00\xe0\x94\xea(\xd0\x02\x04/\u0649\x8d\r\xb0\x16\xbe\x97X\xee\xaf\xe3\\\x1e\x8a\xd3\xc2\x1b\xce\xcc\xed\xa1\x00\x00\x00\xe0\x94\xef\xa7EO\x11\x16\x80yu\xa4u\vFi^\x96xP\xde]\x8a\xd3\xc2\x1b\xce\xcc\xed\xa1\x00\x00\x00\xe1\x94\xfb\xfdo\xa9\xf7:\u01a0X\xe0\x12Y\x03L(\x00\x1b\xef\x82G\x8bR\xb7\xd2\xdc\xc8\f\xd2\xe4\x00\x00\x00"
diff --git ethereum/go-ethereum/core/state_processor.go taikoxyz/taiko-geth/core/state_processor.go index fcaf5a8ff3c9bd36cd741f5a3d413521ff8ab2d2..c69fc88af5929a7c1a0d9961a4c3d9ac4edf082b 100644 --- ethereum/go-ethereum/core/state_processor.go +++ taikoxyz/taiko-geth/core/state_processor.go @@ -76,8 +76,16 @@ context = NewEVMBlockContext(header, p.bc, nil) vmenv = vm.NewEVM(context, vm.TxContext{}, statedb, p.config, cfg) signer = types.MakeSigner(p.config, header.Number, header.Time) ) + if beaconRoot := block.BeaconRoot(); beaconRoot != nil { + ProcessBeaconBlockRoot(*beaconRoot, vmenv, statedb) + } // Iterate over and process the individual transactions for i, tx := range block.Transactions() { + if i == 0 && p.config.Taiko { + if err := tx.MarkAsAnchor(); err != nil { + return nil, nil, 0, err + } + } msg, err := TransactionToMessage(tx, signer, header.BaseFee) if err != nil { return nil, nil, 0, fmt.Errorf("could not apply tx %d [%v]: %w", i, tx.Hash().Hex(), err) @@ -132,6 +140,11 @@ } receipt.TxHash = tx.Hash() receipt.GasUsed = result.UsedGas   + if tx.Type() == types.BlobTxType { + receipt.BlobGasUsed = uint64(len(tx.BlobHashes()) * params.BlobTxBlobGasPerBlob) + receipt.BlobGasPrice = evm.Context.BlobBaseFee + } + // If the transaction created a contract, store the creation address in the receipt. if msg.To == nil { receipt.ContractAddress = crypto.CreateAddress(evm.TxContext.Origin, tx.Nonce()) @@ -160,3 +173,23 @@ blockContext := NewEVMBlockContext(header, bc, author) vmenv := vm.NewEVM(blockContext, vm.TxContext{BlobHashes: tx.BlobHashes()}, statedb, config, cfg) return applyTransaction(msg, config, gp, statedb, header.Number, header.Hash(), tx, usedGas, vmenv) } + +// ProcessBeaconBlockRoot applies the EIP-4788 system call to the beacon block root +// contract. This method is exported to be used in tests. +func ProcessBeaconBlockRoot(beaconRoot common.Hash, vmenv *vm.EVM, statedb *state.StateDB) { + // If EIP-4788 is enabled, we need to invoke the beaconroot storage contract with + // the new root + msg := &Message{ + From: params.SystemAddress, + GasLimit: 30_000_000, + GasPrice: common.Big0, + GasFeeCap: common.Big0, + GasTipCap: common.Big0, + To: &params.BeaconRootsStorageAddress, + Data: beaconRoot[:], + } + vmenv.Reset(NewEVMTxContext(msg), statedb) + statedb.AddAddressToAccessList(params.BeaconRootsStorageAddress) + _, _, _ = vmenv.Call(vm.AccountRef(msg.From), *msg.To, msg.Data, 30_000_000, common.Big0) + statedb.Finalise(true) +}
diff --git ethereum/go-ethereum/core/blockchain_repair_test.go taikoxyz/taiko-geth/core/blockchain_repair_test.go index 6a4a9c9d22bd14847283a63a1457e03dc333aac4..b2df39d17bb8aa27da367c0329b9efe4a78183c0 100644 --- ethereum/go-ethereum/core/blockchain_repair_test.go +++ taikoxyz/taiko-geth/core/blockchain_repair_test.go @@ -22,6 +22,7 @@ package core   import ( "math/big" + "path" "testing" "time"   @@ -1749,16 +1750,24 @@ }, snapshots) }   func testRepair(t *testing.T, tt *rewindTest, snapshots bool) { + for _, scheme := range []string{rawdb.HashScheme, rawdb.PathScheme} { + testRepairWithScheme(t, tt, snapshots, scheme) + } +} + +func testRepairWithScheme(t *testing.T, tt *rewindTest, snapshots bool, scheme string) { // It's hard to follow the test case, visualize the input //log.Root().SetHandler(log.LvlFilterHandler(log.LvlTrace, log.StreamHandler(os.Stderr, log.TerminalFormat(true)))) // fmt.Println(tt.dump(true))   // Create a temporary persistent database datadir := t.TempDir() + ancient := path.Join(datadir, "ancient")   db, err := rawdb.Open(rawdb.OpenOptions{ Directory: datadir, - AncientsDirectory: datadir, + AncientsDirectory: ancient, + Ephemeral: true, }) if err != nil { t.Fatalf("Failed to create persistent database: %v", err) @@ -1777,6 +1786,7 @@ TrieCleanLimit: 256, TrieDirtyLimit: 256, TrieTimeLimit: 5 * time.Minute, SnapshotLimit: 0, // Disable snapshot by default + StateScheme: scheme, } ) defer engine.Close() @@ -1806,7 +1816,9 @@ if _, err := chain.InsertChain(canonblocks[:tt.commitBlock]); err != nil { t.Fatalf("Failed to import canonical chain start: %v", err) } if tt.commitBlock > 0 { - chain.stateCache.TrieDB().Commit(canonblocks[tt.commitBlock-1].Root(), false) + if err := chain.triedb.Commit(canonblocks[tt.commitBlock-1].Root(), false); err != nil { + t.Fatalf("Failed to flush trie state: %v", err) + } if snapshots { if err := chain.snaps.Cap(canonblocks[tt.commitBlock-1].Root(), 0); err != nil { t.Fatalf("Failed to flatten snapshots: %v", err) @@ -1828,21 +1840,22 @@ if tt.pivotBlock != nil { rawdb.WriteLastPivotNumber(db, *tt.pivotBlock) } // Pull the plug on the database, simulating a hard crash + chain.triedb.Close() db.Close() chain.stopWithoutSaving()   // Start a new blockchain back up and see where the repair leads us db, err = rawdb.Open(rawdb.OpenOptions{ Directory: datadir, - AncientsDirectory: datadir, + AncientsDirectory: ancient, + Ephemeral: true, }) - if err != nil { t.Fatalf("Failed to reopen persistent database: %v", err) } defer db.Close()   - newChain, err := NewBlockChain(db, nil, gspec, nil, engine, vm.Config{}, nil, nil) + newChain, err := NewBlockChain(db, config, gspec, nil, engine, vm.Config{}, nil, nil) if err != nil { t.Fatalf("Failed to recreate chain: %v", err) } @@ -1885,17 +1898,22 @@ // chain rewinds itself to the B1 (skip B3 in order to recover snapshot) // In this case the snapshot layer of B3 is not created because of existent // state. func TestIssue23496(t *testing.T) { + testIssue23496(t, rawdb.HashScheme) + testIssue23496(t, rawdb.PathScheme) +} + +func testIssue23496(t *testing.T, scheme string) { // It's hard to follow the test case, visualize the input //log.Root().SetHandler(log.LvlFilterHandler(log.LvlTrace, log.StreamHandler(os.Stderr, log.TerminalFormat(true))))   // Create a temporary persistent database datadir := t.TempDir() + ancient := path.Join(datadir, "ancient")   db, err := rawdb.Open(rawdb.OpenOptions{ Directory: datadir, - AncientsDirectory: datadir, + AncientsDirectory: ancient, }) - if err != nil { t.Fatalf("Failed to create persistent database: %v", err) } @@ -1908,15 +1926,8 @@ Config: params.TestChainConfig, BaseFee: big.NewInt(params.InitialBaseFee), } engine = ethash.NewFullFaker() - config = &CacheConfig{ - TrieCleanLimit: 256, - TrieDirtyLimit: 256, - TrieTimeLimit: 5 * time.Minute, - SnapshotLimit: 256, - SnapshotWait: true, - } ) - chain, err := NewBlockChain(db, config, gspec, nil, engine, vm.Config{}, nil, nil) + chain, err := NewBlockChain(db, DefaultCacheConfigWithScheme(scheme), gspec, nil, engine, vm.Config{}, nil, nil) if err != nil { t.Fatalf("Failed to create chain: %v", err) } @@ -1929,7 +1940,7 @@ // Insert block B1 and commit the state into disk if _, err := chain.InsertChain(blocks[:1]); err != nil { t.Fatalf("Failed to import canonical chain start: %v", err) } - chain.stateCache.TrieDB().Commit(blocks[0].Root(), false) + chain.triedb.Commit(blocks[0].Root(), false)   // Insert block B2 and commit the snapshot into disk if _, err := chain.InsertChain(blocks[1:2]); err != nil { @@ -1943,7 +1954,7 @@ // Insert block B3 and commit the state into disk if _, err := chain.InsertChain(blocks[2:3]); err != nil { t.Fatalf("Failed to import canonical chain start: %v", err) } - chain.stateCache.TrieDB().Commit(blocks[2].Root(), false) + chain.triedb.Commit(blocks[2].Root(), false)   // Insert the remaining blocks if _, err := chain.InsertChain(blocks[3:]); err != nil { @@ -1951,20 +1962,22 @@ t.Fatalf("Failed to import canonical chain tail: %v", err) }   // Pull the plug on the database, simulating a hard crash + chain.triedb.Close() db.Close() chain.stopWithoutSaving()   // Start a new blockchain back up and see where the repair leads us db, err = rawdb.Open(rawdb.OpenOptions{ Directory: datadir, - AncientsDirectory: datadir, + AncientsDirectory: ancient, + Ephemeral: true, }) if err != nil { t.Fatalf("Failed to reopen persistent database: %v", err) } defer db.Close()   - chain, err = NewBlockChain(db, nil, gspec, nil, engine, vm.Config{}, nil, nil) + chain, err = NewBlockChain(db, DefaultCacheConfigWithScheme(scheme), gspec, nil, engine, vm.Config{}, nil, nil) if err != nil { t.Fatalf("Failed to recreate chain: %v", err) } @@ -1976,8 +1989,12 @@ } if head := chain.CurrentSnapBlock(); head.Number.Uint64() != uint64(4) { t.Errorf("Head fast block mismatch: have %d, want %d", head.Number, uint64(4)) } - if head := chain.CurrentBlock(); head.Number.Uint64() != uint64(1) { - t.Errorf("Head block mismatch: have %d, want %d", head.Number, uint64(1)) + expHead := uint64(1) + if scheme == rawdb.PathScheme { + expHead = uint64(2) + } + if head := chain.CurrentBlock(); head.Number.Uint64() != expHead { + t.Errorf("Head block mismatch: have %d, want %d", head.Number, expHead) }   // Reinsert B2-B4
diff --git ethereum/go-ethereum/core/chain_makers.go taikoxyz/taiko-geth/core/chain_makers.go index 4e8e80b92b56363afa76e9ca08837aabe528a56e..3608329a132f9bc8224a38b02c4f48e06a206abd 100644 --- ethereum/go-ethereum/core/chain_makers.go +++ taikoxyz/taiko-geth/core/chain_makers.go @@ -24,6 +24,7 @@ "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/consensus" "github.com/ethereum/go-ethereum/consensus/misc" "github.com/ethereum/go-ethereum/consensus/misc/eip1559" + "github.com/ethereum/go-ethereum/consensus/misc/eip4844" "github.com/ethereum/go-ethereum/core/rawdb" "github.com/ethereum/go-ethereum/core/state" "github.com/ethereum/go-ethereum/core/types" @@ -105,6 +106,9 @@ panic(err) } b.txs = append(b.txs, tx) b.receipts = append(b.receipts, receipt) + if b.header.BlobGasUsed != nil { + *b.header.BlobGasUsed += receipt.BlobGasUsed + } }   // AddTx adds a transaction to the generated block. If no coinbase has @@ -283,7 +287,7 @@ config = params.TestChainConfig } blocks, receipts := make(types.Blocks, n), make([]types.Receipts, n) chainreader := &fakeChainReader{config: config} - genblock := func(i int, parent *types.Block, statedb *state.StateDB) (*types.Block, types.Receipts) { + genblock := func(i int, parent *types.Block, triedb *trie.Database, statedb *state.StateDB) (*types.Block, types.Receipts) { b := &BlockGen{i: i, chain: blocks, parent: parent, statedb: statedb, config: config, engine: engine} b.header = makeHeader(chainreader, parent, statedb, b.engine)   @@ -326,19 +330,23 @@ root, err := statedb.Commit(b.header.Number.Uint64(), config.IsEIP158(b.header.Number)) if err != nil { panic(fmt.Sprintf("state write error: %v", err)) } - if err := statedb.Database().TrieDB().Commit(root, false); err != nil { + if err = triedb.Commit(root, false); err != nil { panic(fmt.Sprintf("trie write error: %v", err)) } return block, b.receipts } return nil, nil } + // Forcibly use hash-based state scheme for retaining all nodes in disk. + triedb := trie.NewDatabase(db, trie.HashDefaults) + defer triedb.Close() + for i := 0; i < n; i++ { - statedb, err := state.New(parent.Root(), state.NewDatabase(db), nil) + statedb, err := state.New(parent.Root(), state.NewDatabaseWithNodeDB(db, triedb), nil) if err != nil { panic(err) } - block, receipt := genblock(i, parent, statedb) + block, receipt := genblock(i, parent, triedb, statedb) blocks[i] = block receipts[i] = receipt parent = block @@ -351,7 +359,9 @@ // genesis block to database first according to the provided genesis specification // then generate chain on top. func GenerateChainWithGenesis(genesis *Genesis, engine consensus.Engine, n int, gen func(int, *BlockGen)) (ethdb.Database, []*types.Block, []types.Receipts) { db := rawdb.NewMemoryDatabase() - _, err := genesis.Commit(db, trie.NewDatabase(db)) + triedb := trie.NewDatabase(db, trie.HashDefaults) + defer triedb.Close() + _, err := genesis.Commit(db, triedb) if err != nil { panic(err) } @@ -386,6 +396,20 @@ if !chain.Config().IsLondon(parent.Number()) { parentGasLimit := parent.GasLimit() * chain.Config().ElasticityMultiplier() header.GasLimit = CalcGasLimit(parentGasLimit, parentGasLimit) } + } + if chain.Config().IsCancun(header.Number, header.Time) { + var ( + parentExcessBlobGas uint64 + parentBlobGasUsed uint64 + ) + if parent.ExcessBlobGas() != nil { + parentExcessBlobGas = *parent.ExcessBlobGas() + parentBlobGasUsed = *parent.BlobGasUsed() + } + excessBlobGas := eip4844.CalcExcessBlobGas(parentExcessBlobGas, parentBlobGasUsed) + header.ExcessBlobGas = &excessBlobGas + header.BlobGasUsed = new(uint64) + header.ParentBeaconRoot = new(common.Hash) } return header }
diff --git ethereum/go-ethereum/core/chain_makers_test.go taikoxyz/taiko-geth/core/chain_makers_test.go index 4f73555275534784327b61d24dd2aa7a1f11498a..db220cf24a7fa3e9b9eece3c6b9752027af5f884 100644 --- ethereum/go-ethereum/core/chain_makers_test.go +++ taikoxyz/taiko-geth/core/chain_makers_test.go @@ -29,6 +29,7 @@ "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/core/vm" "github.com/ethereum/go-ethereum/crypto" "github.com/ethereum/go-ethereum/params" + "github.com/ethereum/go-ethereum/trie" )   func TestGenerateWithdrawalChain(t *testing.T) { @@ -74,8 +75,7 @@ Nonce: 1, Storage: storage, Code: common.Hex2Bytes("600154600354"), } - - genesis := gspec.MustCommit(gendb) + genesis := gspec.MustCommit(gendb, trie.NewDatabase(gendb, trie.HashDefaults))   chain, _ := GenerateChain(gspec.Config, genesis, beacon.NewFaker(), gendb, 4, func(i int, gen *BlockGen) { tx, _ := types.SignTx(types.NewTransaction(gen.TxNonce(address), address, big.NewInt(1000), params.TxGas, new(big.Int).Add(gen.BaseFee(), common.Big1), nil), signer, key) @@ -146,6 +146,7 @@ addr1 = crypto.PubkeyToAddress(key1.PublicKey) addr2 = crypto.PubkeyToAddress(key2.PublicKey) addr3 = crypto.PubkeyToAddress(key3.PublicKey) db = rawdb.NewMemoryDatabase() + genDb = rawdb.NewMemoryDatabase() )   // Ensure that key1 has some funds in the genesis block. @@ -153,13 +154,13 @@ gspec := &Genesis{ Config: &params.ChainConfig{HomesteadBlock: new(big.Int)}, Alloc: GenesisAlloc{addr1: {Balance: big.NewInt(1000000)}}, } - genesis := gspec.MustCommit(db) + genesis := gspec.MustCommit(genDb, trie.NewDatabase(genDb, trie.HashDefaults))   // This call generates a chain of 5 blocks. The function runs for // each block and adds different features to gen based on the // block index. signer := types.HomesteadSigner{} - chain, _ := GenerateChain(gspec.Config, genesis, ethash.NewFaker(), db, 5, func(i int, gen *BlockGen) { + chain, _ := GenerateChain(gspec.Config, genesis, ethash.NewFaker(), genDb, 5, func(i int, gen *BlockGen) { switch i { case 0: // In block 1, addr1 sends addr2 some ether. @@ -188,7 +189,7 @@ } })   // Import the chain. This runs all block validation rules. - blockchain, _ := NewBlockChain(db, nil, gspec, nil, ethash.NewFaker(), vm.Config{}, nil, nil) + blockchain, _ := NewBlockChain(db, DefaultCacheConfigWithScheme(rawdb.HashScheme), gspec, nil, ethash.NewFaker(), vm.Config{}, nil, nil) defer blockchain.Stop()   if i, err := blockchain.InsertChain(chain); err != nil {
diff --git ethereum/go-ethereum/core/evm.go taikoxyz/taiko-geth/core/evm.go index 104f2c09dc1da27e863a99c3f542da455a9e3c93..46dcb314626052b8a97dfa7daba039512ad875a1 100644 --- ethereum/go-ethereum/core/evm.go +++ taikoxyz/taiko-geth/core/evm.go @@ -21,6 +21,7 @@ "math/big"   "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/consensus" + "github.com/ethereum/go-ethereum/consensus/misc/eip4844" "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/core/vm" ) @@ -40,6 +41,7 @@ func NewEVMBlockContext(header *types.Header, chain ChainContext, author *common.Address) vm.BlockContext { var ( beneficiary common.Address baseFee *big.Int + blobBaseFee *big.Int random *common.Hash )   @@ -52,21 +54,24 @@ } if header.BaseFee != nil { baseFee = new(big.Int).Set(header.BaseFee) } + if header.ExcessBlobGas != nil { + blobBaseFee = eip4844.CalcBlobFee(*header.ExcessBlobGas) + } if header.Difficulty.Cmp(common.Big0) == 0 { random = &header.MixDigest } return vm.BlockContext{ - CanTransfer: CanTransfer, - Transfer: Transfer, - GetHash: GetHashFn(header, chain), - Coinbase: beneficiary, - BlockNumber: new(big.Int).Set(header.Number), - Time: header.Time, - Difficulty: new(big.Int).Set(header.Difficulty), - BaseFee: baseFee, - GasLimit: header.GasLimit, - Random: random, - ExcessBlobGas: header.ExcessBlobGas, + CanTransfer: CanTransfer, + Transfer: Transfer, + GetHash: GetHashFn(header, chain), + Coinbase: beneficiary, + BlockNumber: new(big.Int).Set(header.Number), + Time: header.Time, + Difficulty: new(big.Int).Set(header.Difficulty), + BaseFee: baseFee, + BlobBaseFee: blobBaseFee, + GasLimit: header.GasLimit, + Random: random, } }
diff --git ethereum/go-ethereum/core/genesis.go taikoxyz/taiko-geth/core/genesis.go index 33716d0b61dff273433fc15b49b5c0c93cd75475..0f1e8baf43cdc0e798ccae16be67586697451948 100644 --- ethereum/go-ethereum/core/genesis.go +++ taikoxyz/taiko-geth/core/genesis.go @@ -120,8 +120,8 @@ } return nil }   -// deriveHash computes the state root according to the genesis specification. -func (ga *GenesisAlloc) deriveHash() (common.Hash, error) { +// hash computes the state root according to the genesis specification. +func (ga *GenesisAlloc) hash() (common.Hash, error) { // Create an ephemeral in-memory database for computing hash, // all the derived states will be discarded to not pollute disk. db := state.NewDatabase(rawdb.NewMemoryDatabase()) @@ -130,7 +130,9 @@ if err != nil { return common.Hash{}, err } for addr, account := range *ga { - statedb.AddBalance(addr, account.Balance) + if account.Balance != nil { + statedb.AddBalance(addr, account.Balance) + } statedb.SetCode(addr, account.Code) statedb.SetNonce(addr, account.Nonce) for key, value := range account.Storage { @@ -140,16 +142,18 @@ } return statedb.Commit(0, false) }   -// flush is very similar with deriveHash, but the main difference is -// all the generated states will be persisted into the given database. -// Also, the genesis state specification will be flushed as well. +// flush is very similar with hash, but the main difference is all the generated +// states will be persisted into the given database. Also, the genesis state +// specification will be flushed as well. func (ga *GenesisAlloc) flush(db ethdb.Database, triedb *trie.Database, blockhash common.Hash) error { statedb, err := state.New(types.EmptyRootHash, state.NewDatabaseWithNodeDB(db, triedb), nil) if err != nil { return err } for addr, account := range *ga { - statedb.AddBalance(addr, account.Balance) + if account.Balance != nil { + statedb.AddBalance(addr, account.Balance) + } statedb.SetCode(addr, account.Code) statedb.SetNonce(addr, account.Nonce) for key, value := range account.Storage { @@ -173,39 +177,6 @@ return err } rawdb.WriteGenesisStateSpec(db, blockhash, blob) return nil -} - -// CommitGenesisState loads the stored genesis state with the given block -// hash and commits it into the provided trie database. -func CommitGenesisState(db ethdb.Database, triedb *trie.Database, blockhash common.Hash) error { - var alloc GenesisAlloc - blob := rawdb.ReadGenesisStateSpec(db, blockhash) - if len(blob) != 0 { - if err := alloc.UnmarshalJSON(blob); err != nil { - return err - } - } else { - // Genesis allocation is missing and there are several possibilities: - // the node is legacy which doesn't persist the genesis allocation or - // the persisted allocation is just lost. - // - supported networks(mainnet, testnets), recover with defined allocations - // - private network, can't recover - var genesis *Genesis - switch blockhash { - case params.MainnetGenesisHash: - genesis = DefaultGenesisBlock() - case params.GoerliGenesisHash: - genesis = DefaultGoerliGenesisBlock() - case params.SepoliaGenesisHash: - genesis = DefaultSepoliaGenesisBlock() - } - if genesis != nil { - alloc = genesis.Alloc - } else { - return errors.New("not found") - } - } - return alloc.flush(db, triedb, blockhash) }   // GenesisAccount is an account in the state of the genesis block. @@ -323,10 +294,12 @@ } applyOverrides(genesis.Config) return genesis.Config, block.Hash(), nil } - // We have the genesis block in database(perhaps in ancient database) - // but the corresponding state is missing. + // The genesis block is present(perhaps in ancient database) while the + // state database is not initialized yet. It can happen that the node + // is initialized with an external ancient store. Commit genesis state + // in this case. header := rawdb.ReadHeader(db, stored, 0) - if header.Root != types.EmptyRootHash && !rawdb.HasLegacyTrieNode(db, header.Root) { + if header.Root != types.EmptyRootHash && !triedb.Initialized(header.Root) { if genesis == nil { genesis = DefaultGenesisBlock() } @@ -438,7 +411,7 @@ }   // ToBlock returns the genesis block according to genesis specification. func (g *Genesis) ToBlock() *types.Block { - root, err := g.Alloc.deriveHash() + root, err := g.Alloc.hash() if err != nil { panic(err) } @@ -477,6 +450,11 @@ head.WithdrawalsHash = &types.EmptyWithdrawalsHash withdrawals = make([]*types.Withdrawal, 0) } if conf.IsCancun(num, g.Timestamp) { + // EIP-4788: The parentBeaconBlockRoot of the genesis block is always + // the zero hash. This is because the genesis block does not have a parent + // by definition. + head.ParentBeaconRoot = new(common.Hash) + // EIP-4844 fields head.ExcessBlobGas = g.ExcessBlobGas head.BlobGasUsed = g.BlobGasUsed if head.ExcessBlobGas == nil { @@ -526,10 +504,8 @@ }   // MustCommit writes the genesis block and state to db, panicking on error. // The block is committed as the canonical head block. -// Note the state changes will be committed in hash-based scheme, use Commit -// if path-scheme is preferred. -func (g *Genesis) MustCommit(db ethdb.Database) *types.Block { - block, err := g.Commit(db, trie.NewDatabase(db)) +func (g *Genesis) MustCommit(db ethdb.Database, triedb *trie.Database) *types.Block { + block, err := g.Commit(db, triedb) if err != nil { panic(err) } @@ -573,6 +549,18 @@ Alloc: decodePrealloc(sepoliaAllocData), } }   +// DefaultHoleskyGenesisBlock returns the Holesky network genesis block. +func DefaultHoleskyGenesisBlock() *Genesis { + return &Genesis{ + Config: params.HoleskyChainConfig, + Nonce: 0x1234, + GasLimit: 0x17d7840, + Difficulty: big.NewInt(0x01), + Timestamp: 1695902100, + Alloc: decodePrealloc(holeskyAllocData), + } +} + // DeveloperGenesisBlock returns the 'geth --dev' genesis block. func DeveloperGenesisBlock(gasLimit uint64, faucet common.Address) *Genesis { // Override the default period to the user requested one @@ -600,13 +588,34 @@ } }   func decodePrealloc(data string) GenesisAlloc { - var p []struct{ Addr, Balance *big.Int } + var p []struct { + Addr *big.Int + Balance *big.Int + Misc *struct { + Nonce uint64 + Code []byte + Slots []struct { + Key common.Hash + Val common.Hash + } + } `rlp:"optional"` + } if err := rlp.NewStream(strings.NewReader(data), 0).Decode(&p); err != nil { panic(err) } ga := make(GenesisAlloc, len(p)) for _, account := range p { - ga[common.BigToAddress(account.Addr)] = GenesisAccount{Balance: account.Balance} + acc := GenesisAccount{Balance: account.Balance} + if account.Misc != nil { + acc.Nonce = account.Misc.Nonce + acc.Code = account.Misc.Code + + acc.Storage = make(map[common.Hash]common.Hash) + for _, slot := range account.Misc.Slots { + acc.Storage[slot.Key] = slot.Val + } + } + ga[common.BigToAddress(account.Addr)] = acc } return ga }
diff --git ethereum/go-ethereum/core/state_transition.go taikoxyz/taiko-geth/core/state_transition.go index f84757be781fba4beec4d64c5fa832c259a80a3e..b0cc3b487e58bbc4773f2ca01d8654a84a8ba438 100644 --- ethereum/go-ethereum/core/state_transition.go +++ taikoxyz/taiko-geth/core/state_transition.go @@ -24,10 +24,13 @@ "math/big"   "github.com/ethereum/go-ethereum/common" cmath "github.com/ethereum/go-ethereum/common/math" - "github.com/ethereum/go-ethereum/consensus/misc/eip4844" "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/core/vm" "github.com/ethereum/go-ethereum/params" +) + +var ( + treasury = common.HexToAddress("0xdf09A0afD09a63fb04ab3573922437e1e637dE8b") )   // ExecutionResult includes all output after executing given evm @@ -144,6 +147,9 @@ // When SkipAccountChecks is true, the message nonce is not checked against the // account nonce in state. It also disables checking that the sender is an EOA. // This field will be set to true for operations like RPC eth_call. SkipAccountChecks bool + + // CHANGE(taiko): whether the current transaction is the first TaikoL2.anchor transaction in a block. + IsAnchor bool }   // TransactionToMessage converts a transaction into a Message. @@ -161,6 +167,7 @@ AccessList: tx.AccessList(), SkipAccountChecks: false, BlobHashes: tx.BlobHashes(), BlobGasFeeCap: tx.BlobGasFeeCap(), + IsAnchor: tx.IsAnchor(), } // If baseFee provided, set gasPrice to effectiveGasPrice. if baseFee != nil { @@ -248,10 +255,15 @@ blobBalanceCheck.Mul(blobBalanceCheck, st.msg.BlobGasFeeCap) balanceCheck.Add(balanceCheck, blobBalanceCheck) // Pay for blobGasUsed * actual blob fee blobFee := new(big.Int).SetUint64(blobGas) - blobFee.Mul(blobFee, eip4844.CalcBlobFee(*st.evm.Context.ExcessBlobGas)) + blobFee.Mul(blobFee, st.evm.Context.BlobBaseFee) mgval.Add(mgval, blobFee) } } + // CHANGE(taiko): skip balance check for TaikoL2.anchor transaction. + if st.msg.IsAnchor { + balanceCheck = common.Big0 + mgval = common.Big0 + } if have, want := st.state.GetBalance(st.msg.From), balanceCheck; have.Cmp(want) < 0 { return fmt.Errorf("%w: address %v have %v want %v", ErrInsufficientFunds, st.msg.From.Hex(), have, want) } @@ -292,7 +304,7 @@ // Make sure that transaction gasFeeCap is greater than the baseFee (post london) if st.evm.ChainConfig().IsLondon(st.evm.Context.BlockNumber) { // Skip the checks if gas fields are zero and baseFee was explicitly disabled (eth_call) - if !st.evm.Config.NoBaseFee || msg.GasFeeCap.BitLen() > 0 || msg.GasTipCap.BitLen() > 0 { + if (!st.evm.Config.NoBaseFee || msg.GasFeeCap.BitLen() > 0 || msg.GasTipCap.BitLen() > 0) && !st.msg.IsAnchor { if l := msg.GasFeeCap.BitLen(); l > 256 { return fmt.Errorf("%w: address %v, maxFeePerGas bit length: %d", ErrFeeCapVeryHigh, msg.From.Hex(), l) @@ -329,7 +341,7 @@ if st.evm.ChainConfig().IsCancun(st.evm.Context.BlockNumber, st.evm.Context.Time) { if st.blobGasUsed() > 0 { // Check that the user is paying at least the current blob fee - blobFee := eip4844.CalcBlobFee(*st.evm.Context.ExcessBlobGas) + blobFee := st.evm.Context.BlobBaseFee if st.msg.BlobGasFeeCap.Cmp(blobFee) < 0 { return fmt.Errorf("%w: address %v have %v want %v", ErrBlobFeeCapTooLow, st.msg.From.Hex(), st.msg.BlobGasFeeCap, blobFee) } @@ -436,6 +448,13 @@ } else { fee := new(big.Int).SetUint64(st.gasUsed()) fee.Mul(fee, effectiveTip) st.state.AddBalance(st.evm.Context.Coinbase, fee) + // CHANGE(taiko): basefee is not burnt, but sent to a treasury instead. + if st.evm.ChainConfig().Taiko && st.evm.Context.BaseFee != nil && !st.msg.IsAnchor { + st.state.AddBalance( + treasury, + new(big.Int).Mul(st.evm.Context.BaseFee, new(big.Int).SetUint64(st.gasUsed())), + ) + } }   return &ExecutionResult{
diff --git ethereum/go-ethereum/core/taiko_genesis.go taikoxyz/taiko-geth/core/taiko_genesis.go new file mode 100644 index 0000000000000000000000000000000000000000..6222a674f7f5988f9abd41a47f7ce591a74ff39b --- /dev/null +++ taikoxyz/taiko-geth/core/taiko_genesis.go @@ -0,0 +1,58 @@ +package core + +import ( + "math/big" + + "github.com/ethereum/go-ethereum/common" + taikoGenesis "github.com/ethereum/go-ethereum/core/taiko_genesis" + "github.com/ethereum/go-ethereum/log" + "github.com/ethereum/go-ethereum/params" +) + +// TaikoGenesisBlock returns the Taiko network genesis block configs. +func TaikoGenesisBlock(networkID uint64) *Genesis { + chainConfig := params.TaikoChainConfig + + var allocJSON []byte + switch networkID { + case params.TaikoInternalNetworkID.Uint64(): + chainConfig.ChainID = params.TaikoInternalNetworkID + allocJSON = taikoGenesis.InternalGenesisAllocJSON + case params.TaikoInternalL3NetworkID.Uint64(): + chainConfig.ChainID = params.TaikoInternalL3NetworkID + allocJSON = taikoGenesis.InternalL3GenesisAllocJSON + case params.SnaefellsjokullNetworkID.Uint64(): + chainConfig.ChainID = params.SnaefellsjokullNetworkID + allocJSON = taikoGenesis.SnaefellsjokullGenesisAllocJSON + case params.AskjaNetworkID.Uint64(): + chainConfig.ChainID = params.AskjaNetworkID + allocJSON = taikoGenesis.AskjaGenesisAllocJSON + case params.GrimsvotnNetworkID.Uint64(): + chainConfig.ChainID = params.GrimsvotnNetworkID + allocJSON = taikoGenesis.GrimsvotnGenesisAllocJSON + case params.EldfellNetworkID.Uint64(): + chainConfig.ChainID = params.EldfellNetworkID + allocJSON = taikoGenesis.EldfellGenesisAllocJSON + case params.JolnirNetworkID.Uint64(): + chainConfig.ChainID = params.JolnirNetworkID + allocJSON = taikoGenesis.JolnirGenesisAllocJSON + default: + chainConfig.ChainID = params.TaikoInternalNetworkID + allocJSON = taikoGenesis.InternalGenesisAllocJSON + } + + var alloc GenesisAlloc + if err := alloc.UnmarshalJSON(allocJSON); err != nil { + log.Crit("unmarshal alloc json error", "error", err) + } + + return &Genesis{ + Config: chainConfig, + ExtraData: []byte{}, + GasLimit: uint64(15_000_000), + Difficulty: common.Big0, + Alloc: alloc, + GasUsed: 0, + BaseFee: new(big.Int).SetUint64(10_000_000), + } +}
diff --git ethereum/go-ethereum/core/block_validator.go taikoxyz/taiko-geth/core/block_validator.go index 3c9ac3dc49d5188692154730816a65f7e4f7c392..f3d65cea25ff351bd750fa90c9b21d29ef86c8e6 100644 --- ethereum/go-ethereum/core/block_validator.go +++ taikoxyz/taiko-geth/core/block_validator.go @@ -68,6 +68,7 @@ } if hash := types.DeriveSha(block.Transactions(), trie.NewStackTrie(nil)); hash != header.TxHash { return fmt.Errorf("transaction root hash mismatch (header value %x, calculated %x)", header.TxHash, hash) } + // Withdrawals are present after the Shanghai fork. if header.WithdrawalsHash != nil { // Withdrawals list must be present in body after Shanghai. @@ -81,14 +82,23 @@ } else if block.Withdrawals() != nil { // Withdrawals are not allowed prior to Shanghai fork return errors.New("withdrawals present in block body") } + // Blob transactions may be present after the Cancun fork. var blobs int - for _, tx := range block.Transactions() { + for i, tx := range block.Transactions() { // Count the number of blobs to validate against the header's blobGasUsed blobs += len(tx.BlobHashes()) + + // If the tx is a blob tx, it must NOT have a sidecar attached to be valid in a block. + if tx.BlobTxSidecar() != nil { + return fmt.Errorf("unexpected blob sidecar in transaction at index %d", i) + } + // The individual checks for blob validity (version-check + not empty) - // happens in the state_transition check. + // happens in StateTransition. } + + // Check blob gas usage. if header.BlobGasUsed != nil { if want := *header.BlobGasUsed / params.BlobTxBlobGasPerBlob; uint64(blobs) != want { // div because the header is surely good vs the body might be bloated return fmt.Errorf("blob gas used mismatch (header %v, calculated %v)", *header.BlobGasUsed, blobs*params.BlobTxBlobGasPerBlob) @@ -98,6 +108,8 @@ if blobs > 0 { return errors.New("data blobs present in block body") } } + + // Ancestor block must be known. if !v.bc.HasBlockAndState(block.ParentHash(), block.NumberU64()-1) { if !v.bc.HasBlock(block.ParentHash(), block.NumberU64()-1) { return consensus.ErrUnknownAncestor
diff --git ethereum/go-ethereum/core/rawdb/chain_freezer.go taikoxyz/taiko-geth/core/rawdb/chain_freezer.go index 22dbda4a2107a7e3376aa450a2579bcdca7d54d3..cbfaf5b9e4e6ad5e775b138827f144ffa30ba870 100644 --- ethereum/go-ethereum/core/rawdb/chain_freezer.go +++ taikoxyz/taiko-geth/core/rawdb/chain_freezer.go @@ -200,7 +200,7 @@ log.Crit("Failed to delete frozen side blocks", "err", err) } batch.Reset()   - // Step into the future and delete and dangling side chains + // Step into the future and delete any dangling side chains if frozen > 0 { tip := frozen for len(dangling) > 0 {
diff --git ethereum/go-ethereum/core/state/statedb.go taikoxyz/taiko-geth/core/state/statedb.go index 5c33e2d7e130fa1f05637978539178b24858a504..d28cd29b309a8ba8c404ed1a9eff612cecc36ad5 100644 --- ethereum/go-ethereum/core/state/statedb.go +++ taikoxyz/taiko-geth/core/state/statedb.go @@ -18,7 +18,6 @@ // Package state provides a caching layer atop the Ethereum state trie. package state   import ( - "errors" "fmt" "math/big" "sort" @@ -32,26 +31,20 @@ "github.com/ethereum/go-ethereum/crypto" "github.com/ethereum/go-ethereum/log" "github.com/ethereum/go-ethereum/metrics" "github.com/ethereum/go-ethereum/params" - "github.com/ethereum/go-ethereum/rlp" "github.com/ethereum/go-ethereum/trie" "github.com/ethereum/go-ethereum/trie/trienode" "github.com/ethereum/go-ethereum/trie/triestate" )   +const ( + // storageDeleteLimit denotes the highest permissible memory allocation + // employed for contract storage deletion. + storageDeleteLimit = 512 * 1024 * 1024 +) + type revision struct { id int journalIndex int -} - -type proofList [][]byte - -func (n *proofList) Put(key []byte, value []byte) error { - *n = append(*n, value) - return nil -} - -func (n *proofList) Delete(key []byte) error { - panic("not supported") }   // StateDB structs within the ethereum protocol are used to store anything @@ -142,6 +135,9 @@ AccountUpdated int StorageUpdated int AccountDeleted int StorageDeleted int + + // Testing hooks + onCommit func(states *triestate.Set) // Hook invoked when commit is performed }   // New creates a new state from a given trie. @@ -292,6 +288,7 @@ } return common.Big0 }   +// GetNonce retrieves the nonce from the given address or 0 if object not found func (s *StateDB) GetNonce(addr common.Address) uint64 { stateObject := s.getStateObject(addr) if stateObject != nil { @@ -301,6 +298,16 @@ return 0 }   +// GetStorageRoot retrieves the storage root from the given address or empty +// if object not found. +func (s *StateDB) GetStorageRoot(addr common.Address) common.Hash { + stateObject := s.getStateObject(addr) + if stateObject != nil { + return stateObject.Root() + } + return common.Hash{} +} + // TxIndex returns the current transaction index set by Prepare. func (s *StateDB) TxIndex() int { return s.txIndex @@ -339,35 +346,6 @@ } return common.Hash{} }   -// GetProof returns the Merkle proof for a given account. -func (s *StateDB) GetProof(addr common.Address) ([][]byte, error) { - return s.GetProofByHash(crypto.Keccak256Hash(addr.Bytes())) -} - -// GetProofByHash returns the Merkle proof for a given account. -func (s *StateDB) GetProofByHash(addrHash common.Hash) ([][]byte, error) { - var proof proofList - err := s.trie.Prove(addrHash[:], &proof) - return proof, err -} - -// GetStorageProof returns the Merkle proof for given storage slot. -func (s *StateDB) GetStorageProof(a common.Address, key common.Hash) ([][]byte, error) { - trie, err := s.StorageTrie(a) - if err != nil { - return nil, err - } - if trie == nil { - return nil, errors.New("storage trie for requested address does not exist") - } - var proof proofList - err = trie.Prove(crypto.Keccak256(key.Bytes()), &proof) - if err != nil { - return nil, err - } - return proof, nil -} - // GetCommittedState retrieves a value from the given account's committed storage trie. func (s *StateDB) GetCommittedState(addr common.Address, hash common.Hash) common.Hash { stateObject := s.getStateObject(addr) @@ -382,21 +360,6 @@ func (s *StateDB) Database() Database { return s.db }   -// StorageTrie returns the storage trie of an account. The return value is a copy -// and is nil for non-existent accounts. An error will be returned if storage trie -// is existent but can't be loaded correctly. -func (s *StateDB) StorageTrie(addr common.Address) (Trie, error) { - stateObject := s.getStateObject(addr) - if stateObject == nil { - return nil, nil - } - cpy := stateObject.deepCopy(s) - if _, err := cpy.updateTrie(); err != nil { - return nil, err - } - return cpy.getTrie() -} - func (s *StateDB) HasSelfDestructed(addr common.Address) bool { stateObject := s.getStateObject(addr) if stateObject != nil { @@ -722,43 +685,6 @@ newObj.setBalance(prev.data.Balance) } }   -func (s *StateDB) ForEachStorage(addr common.Address, cb func(key, value common.Hash) bool) error { - so := s.getStateObject(addr) - if so == nil { - return nil - } - tr, err := so.getTrie() - if err != nil { - return err - } - trieIt, err := tr.NodeIterator(nil) - if err != nil { - return err - } - it := trie.NewIterator(trieIt) - - for it.Next() { - key := common.BytesToHash(s.trie.GetKey(it.Key)) - if value, dirty := so.dirtyStorage[key]; dirty { - if !cb(key, value) { - return nil - } - continue - } - - if len(it.Value) > 0 { - _, content, _, err := rlp.Split(it.Value) - if err != nil { - return err - } - if !cb(key, common.BytesToHash(content)) { - return nil - } - } - } - return nil -} - // Copy creates a deep, independent copy of the state. // Snapshots of the copied state cannot be applied to the copy. func (s *StateDB) Copy() *StateDB { @@ -1022,59 +948,128 @@ } s.validRevisions = s.validRevisions[:0] // Snapshots can be created without journal entries }   -// deleteStorage iterates the storage trie belongs to the account and mark all -// slots inside as deleted. -func (s *StateDB) deleteStorage(addr common.Address, addrHash common.Hash, root common.Hash) (bool, map[common.Hash][]byte, *trienode.NodeSet, error) { - start := time.Now() +// fastDeleteStorage is the function that efficiently deletes the storage trie +// of a specific account. It leverages the associated state snapshot for fast +// storage iteration and constructs trie node deletion markers by creating +// stack trie with iterated slots. +func (s *StateDB) fastDeleteStorage(addrHash common.Hash, root common.Hash) (bool, common.StorageSize, map[common.Hash][]byte, *trienode.NodeSet, error) { + iter, err := s.snaps.StorageIterator(s.originalRoot, addrHash, common.Hash{}) + if err != nil { + return false, 0, nil, nil, err + } + defer iter.Release() + + var ( + size common.StorageSize + nodes = trienode.NewNodeSet(addrHash) + slots = make(map[common.Hash][]byte) + ) + stack := trie.NewStackTrie(func(path []byte, hash common.Hash, blob []byte) { + nodes.AddNode(path, trienode.NewDeleted()) + size += common.StorageSize(len(path)) + }) + for iter.Next() { + if size > storageDeleteLimit { + return true, size, nil, nil, nil + } + slot := common.CopyBytes(iter.Slot()) + if err := iter.Error(); err != nil { // error might occur after Slot function + return false, 0, nil, nil, err + } + size += common.StorageSize(common.HashLength + len(slot)) + slots[iter.Hash()] = slot + + if err := stack.Update(iter.Hash().Bytes(), slot); err != nil { + return false, 0, nil, nil, err + } + } + if err := iter.Error(); err != nil { // error might occur during iteration + return false, 0, nil, nil, err + } + if stack.Hash() != root { + return false, 0, nil, nil, fmt.Errorf("snapshot is not matched, exp %x, got %x", root, stack.Hash()) + } + return false, size, slots, nodes, nil +} + +// slowDeleteStorage serves as a less-efficient alternative to "fastDeleteStorage," +// employed when the associated state snapshot is not available. It iterates the +// storage slots along with all internal trie nodes via trie directly. +func (s *StateDB) slowDeleteStorage(addr common.Address, addrHash common.Hash, root common.Hash) (bool, common.StorageSize, map[common.Hash][]byte, *trienode.NodeSet, error) { tr, err := s.db.OpenStorageTrie(s.originalRoot, addr, root) if err != nil { - return false, nil, nil, fmt.Errorf("failed to open storage trie, err: %w", err) + return false, 0, nil, nil, fmt.Errorf("failed to open storage trie, err: %w", err) } it, err := tr.NodeIterator(nil) if err != nil { - return false, nil, nil, fmt.Errorf("failed to open storage iterator, err: %w", err) + return false, 0, nil, nil, fmt.Errorf("failed to open storage iterator, err: %w", err) } var ( - set = trienode.NewNodeSet(addrHash) - slots = make(map[common.Hash][]byte) - stateSize common.StorageSize - nodeSize common.StorageSize + size common.StorageSize + nodes = trienode.NewNodeSet(addrHash) + slots = make(map[common.Hash][]byte) ) for it.Next(true) { - // arbitrary stateSize limit, make it configurable - if stateSize+nodeSize > 512*1024*1024 { - log.Info("Skip large storage deletion", "address", addr.Hex(), "states", stateSize, "nodes", nodeSize) - if metrics.EnabledExpensive { - slotDeletionSkip.Inc(1) - } - return true, nil, nil, nil + if size > storageDeleteLimit { + return true, size, nil, nil, nil } if it.Leaf() { slots[common.BytesToHash(it.LeafKey())] = common.CopyBytes(it.LeafBlob()) - stateSize += common.StorageSize(common.HashLength + len(it.LeafBlob())) + size += common.StorageSize(common.HashLength + len(it.LeafBlob())) continue } if it.Hash() == (common.Hash{}) { continue } - nodeSize += common.StorageSize(len(it.Path())) - set.AddNode(it.Path(), trienode.NewDeleted()) + size += common.StorageSize(len(it.Path())) + nodes.AddNode(it.Path(), trienode.NewDeleted()) } if err := it.Error(); err != nil { + return false, 0, nil, nil, err + } + return false, size, slots, nodes, nil +} + +// deleteStorage is designed to delete the storage trie of a designated account. +// It could potentially be terminated if the storage size is excessively large, +// potentially leading to an out-of-memory panic. The function will make an attempt +// to utilize an efficient strategy if the associated state snapshot is reachable; +// otherwise, it will resort to a less-efficient approach. +func (s *StateDB) deleteStorage(addr common.Address, addrHash common.Hash, root common.Hash) (bool, map[common.Hash][]byte, *trienode.NodeSet, error) { + var ( + start = time.Now() + err error + aborted bool + size common.StorageSize + slots map[common.Hash][]byte + nodes *trienode.NodeSet + ) + // The fast approach can be failed if the snapshot is not fully + // generated, or it's internally corrupted. Fallback to the slow + // one just in case. + if s.snap != nil { + aborted, size, slots, nodes, err = s.fastDeleteStorage(addrHash, root) + } + if s.snap == nil || err != nil { + aborted, size, slots, nodes, err = s.slowDeleteStorage(addr, addrHash, root) + } + if err != nil { return false, nil, nil, err } if metrics.EnabledExpensive { - if int64(len(slots)) > slotDeletionMaxCount.Value() { - slotDeletionMaxCount.Update(int64(len(slots))) + if aborted { + slotDeletionSkip.Inc(1) } - if int64(stateSize+nodeSize) > slotDeletionMaxSize.Value() { - slotDeletionMaxSize.Update(int64(stateSize + nodeSize)) - } + n := int64(len(slots)) + + slotDeletionMaxCount.UpdateIfGt(int64(len(slots))) + slotDeletionMaxSize.UpdateIfGt(int64(size)) + slotDeletionTimer.UpdateSince(start) - slotDeletionCount.Mark(int64(len(slots))) - slotDeletionSize.Mark(int64(stateSize + nodeSize)) + slotDeletionCount.Mark(n) + slotDeletionSize.Mark(int64(size)) } - return false, slots, set, nil + return aborted, slots, nodes, nil }   // handleDestruction processes all destruction markers and deletes the account @@ -1102,7 +1097,13 @@ // // In case (d), **original** account along with its storages should be deleted, // with their values be tracked as original value. func (s *StateDB) handleDestruction(nodes *trienode.MergedNodeSet) (map[common.Address]struct{}, error) { + // Short circuit if geth is running with hash mode. This procedure can consume + // considerable time and storage deletion isn't supported in hash mode, thus + // preemptively avoiding unnecessary expenses. incomplete := make(map[common.Address]struct{}) + if s.db.TrieDB().Scheme() == rawdb.HashScheme { + return incomplete, nil + } for addr, prev := range s.stateObjectsDestruct { // The original account was non-existing, and it's marked as destructed // in the scope of block. It can be case (a) or (b). @@ -1276,12 +1277,16 @@ origin = types.EmptyRootHash } if root != origin { start := time.Now() - if err := s.db.TrieDB().Update(root, origin, block, nodes, triestate.New(s.accountsOrigin, s.storagesOrigin, incomplete)); err != nil { + set := triestate.New(s.accountsOrigin, s.storagesOrigin, incomplete) + if err := s.db.TrieDB().Update(root, origin, block, nodes, set); err != nil { return common.Hash{}, err } s.originalRoot = root if metrics.EnabledExpensive { s.TrieDBCommits += time.Since(start) + } + if s.onCommit != nil { + s.onCommit(set) } } // Clear all internal flags at the end of commit operation.
diff --git ethereum/go-ethereum/core/rawdb/freezer.go taikoxyz/taiko-geth/core/rawdb/freezer.go index a9fe2343215a095cee658d85f11f1c591af88b5c..b7824ddc0d2c29aafe2a653442608ccfddfcc2f2 100644 --- ethereum/go-ethereum/core/rawdb/freezer.go +++ taikoxyz/taiko-geth/core/rawdb/freezer.go @@ -108,7 +108,11 @@ } // Leveldb uses LOCK as the filelock filename. To prevent the // name collision, we use FLOCK as the lock name. lock := flock.New(flockFile) - if locked, err := lock.TryLock(); err != nil { + tryLock := lock.TryLock + if readonly { + tryLock = lock.TryRLock + } + if locked, err := tryLock(); err != nil { return nil, err } else if !locked { return nil, errors.New("locking failed")
diff --git ethereum/go-ethereum/core/rawdb/databases_64bit.go taikoxyz/taiko-geth/core/rawdb/databases_64bit.go deleted file mode 100644 index 73bfeb20838f1a7af41117afac276712a73ee6b3..0000000000000000000000000000000000000000 --- ethereum/go-ethereum/core/rawdb/databases_64bit.go +++ /dev/null @@ -1,37 +0,0 @@ -// Copyright 2023 The go-ethereum Authors -// This file is part of the go-ethereum library. -// -// The go-ethereum library is free software: you can redistribute it and/or modify -// it under the terms of the GNU Lesser General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// The go-ethereum library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Lesser General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public License -// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/> - -//go:build (arm64 || amd64) && !openbsd - -package rawdb - -import ( - "github.com/ethereum/go-ethereum/ethdb" - "github.com/ethereum/go-ethereum/ethdb/pebble" -) - -// Pebble is unsuported on 32bit architecture -const PebbleEnabled = true - -// NewPebbleDBDatabase creates a persistent key-value database without a freezer -// moving immutable chain segments into cold storage. -func NewPebbleDBDatabase(file string, cache int, handles int, namespace string, readonly bool) (ethdb.Database, error) { - db, err := pebble.New(file, cache, handles, namespace, readonly) - if err != nil { - return nil, err - } - return NewDatabase(db), nil -}
diff --git ethereum/go-ethereum/core/state/state_object.go taikoxyz/taiko-geth/core/state/state_object.go index cd72f3fb9b91645aa49647c29e6bc85e6f6b4efb..d42d2c34d87703ef3b90951e6a3ca61e8de55ab4 100644 --- ethereum/go-ethereum/core/state/state_object.go +++ taikoxyz/taiko-geth/core/state/state_object.go @@ -264,12 +264,17 @@ s.dirtyStorage = make(Storage) } }   -// updateTrie writes cached storage modifications into the object's storage trie. -// It will return nil if the trie has not been loaded and no changes have been -// made. An error will be returned if the trie can't be loaded/updated correctly. +// updateTrie is responsible for persisting cached storage changes into the +// object's storage trie. In case the storage trie is not yet loaded, this +// function will load the trie automatically. If any issues arise during the +// loading or updating of the trie, an error will be returned. Furthermore, +// this function will return the mutated storage trie, or nil if there is no +// storage change at all. func (s *stateObject) updateTrie() (Trie, error) { // Make sure all dirty slots are finalized into the pending storage area - s.finalise(false) // Don't prefetch anymore, pull directly if need be + s.finalise(false) + + // Short circuit if nothing changed, don't bother with hashing anything if len(s.pendingStorage) == 0 { return s.trie, nil } @@ -281,14 +286,13 @@ // The snapshot storage map for the object var ( storage map[common.Hash][]byte origin map[common.Hash][]byte - hasher = s.db.hasher ) tr, err := s.getTrie() if err != nil { s.db.setError(err) return nil, err } - // Insert all the pending updates into the trie + // Insert all the pending storage updates into the trie usedStorage := make([][]byte, 0, len(s.pendingStorage)) for key, value := range s.pendingStorage { // Skip noop changes, persist actual changes @@ -298,8 +302,7 @@ } prev := s.originStorage[key] s.originStorage[key] = value   - // rlp-encoded value to be used by the snapshot - var snapshotVal []byte + var encoded []byte // rlp-encoded value to be used by the snapshot if (value == common.Hash{}) { if err := tr.DeleteStorage(s.address, key[:]); err != nil { s.db.setError(err) @@ -307,10 +310,10 @@ return nil, err } s.db.StorageDeleted += 1 } else { - trimmedVal := common.TrimLeftZeroes(value[:]) // Encoding []byte cannot fail, ok to ignore the error. - snapshotVal, _ = rlp.EncodeToBytes(trimmedVal) - if err := tr.UpdateStorage(s.address, key[:], trimmedVal); err != nil { + trimmed := common.TrimLeftZeroes(value[:]) + encoded, _ = rlp.EncodeToBytes(trimmed) + if err := tr.UpdateStorage(s.address, key[:], trimmed); err != nil { s.db.setError(err) return nil, err } @@ -323,8 +326,8 @@ storage = make(map[common.Hash][]byte) s.db.storages[s.addrHash] = storage } } - khash := crypto.HashData(hasher, key[:]) - storage[khash] = snapshotVal // snapshotVal will be nil if it's deleted + khash := crypto.HashData(s.db.hasher, key[:]) + storage[khash] = encoded // encoded will be nil if it's deleted   // Cache the original value of mutated storage slots if origin == nil { @@ -349,21 +352,17 @@ } if s.db.prefetcher != nil { s.db.prefetcher.used(s.addrHash, s.data.Root, usedStorage) } - if len(s.pendingStorage) > 0 { - s.pendingStorage = make(Storage) - } + s.pendingStorage = make(Storage) // reset pending map return tr, nil }   -// UpdateRoot sets the trie root to the current root hash of. An error -// will be returned if trie root hash is not computed correctly. +// updateRoot flushes all cached storage mutations to trie, recalculating the +// new storage trie root. func (s *stateObject) updateRoot() { + // Flush cached storage mutations into trie, short circuit if any error + // is occurred or there is not change in the trie. tr, err := s.updateTrie() - if err != nil { - return - } - // If nothing changed, don't bother with hashing anything - if tr == nil { + if err != nil || tr == nil { return } // Track the amount of time wasted on hashing the storage trie @@ -373,14 +372,12 @@ } s.data.Root = tr.Hash() }   -// commit returns the changes made in storage trie and updates the account data. +// commit obtains a set of dirty storage trie nodes and updates the account data. +// The returned set can be nil if nothing to commit. This function assumes all +// storage mutations have already been flushed into trie by updateRoot. func (s *stateObject) commit() (*trienode.NodeSet, error) { - tr, err := s.updateTrie() - if err != nil { - return nil, err - } - // If nothing changed, don't bother with committing anything - if tr == nil { + // Short circuit if trie is not even loaded, don't bother with committing anything + if s.trie == nil { s.origin = s.data.Copy() return nil, nil } @@ -388,7 +385,10 @@ // Track the amount of time wasted on committing the storage trie if metrics.EnabledExpensive { defer func(start time.Time) { s.db.StorageCommits += time.Since(start) }(time.Now()) } - root, nodes, err := tr.Commit(false) + // The trie is currently in an open state and could potentially contain + // cached mutations. Call commit to acquire a set of nodes that have been + // modified, the set can be nil if nothing to commit. + root, nodes, err := s.trie.Commit(false) if err != nil { return nil, err } @@ -536,3 +536,7 @@ func (s *stateObject) Nonce() uint64 { return s.data.Nonce } + +func (s *stateObject) Root() common.Hash { + return s.data.Root +}
diff --git ethereum/go-ethereum/core/rawdb/accessors_chain.go taikoxyz/taiko-geth/core/rawdb/accessors_chain.go index c7abd44f365cd052ef047c97ab2cd8fff34a1d43..97401d283caa0d19b19e1cd59b583d76539dfed6 100644 --- ethereum/go-ethereum/core/rawdb/accessors_chain.go +++ taikoxyz/taiko-geth/core/rawdb/accessors_chain.go @@ -381,7 +381,7 @@ if len(data) == 0 { return nil } header := new(types.Header) - if err := rlp.Decode(bytes.NewReader(data), header); err != nil { + if err := rlp.DecodeBytes(data, header); err != nil { log.Error("Invalid block header RLP", "hash", hash, "err", err) return nil } @@ -498,7 +498,7 @@ if len(data) == 0 { return nil } body := new(types.Body) - if err := rlp.Decode(bytes.NewReader(data), body); err != nil { + if err := rlp.DecodeBytes(data, body); err != nil { log.Error("Invalid block body RLP", "hash", hash, "err", err) return nil } @@ -544,7 +544,7 @@ if len(data) == 0 { return nil } td := new(big.Int) - if err := rlp.Decode(bytes.NewReader(data), td); err != nil { + if err := rlp.DecodeBytes(data, td); err != nil { log.Error("Invalid block total difficulty RLP", "hash", hash, "err", err) return nil } @@ -731,7 +731,7 @@ // ReadLogs retrieves the logs for all transactions in a block. In case // receipts is not found, a nil is returned. // Note: ReadLogs does not derive unstored log fields. -func ReadLogs(db ethdb.Reader, hash common.Hash, number uint64, config *params.ChainConfig) [][]*types.Log { +func ReadLogs(db ethdb.Reader, hash common.Hash, number uint64) [][]*types.Log { // Retrieve the flattened receipt slice data := ReadReceiptsRLP(db, hash, number) if len(data) == 0 {
diff --git ethereum/go-ethereum/core/asm/tokentype_string.go taikoxyz/taiko-geth/core/asm/tokentype_string.go new file mode 100644 index 0000000000000000000000000000000000000000..ade76aa360c4840376b239ac9d1317b13dae72fe --- /dev/null +++ taikoxyz/taiko-geth/core/asm/tokentype_string.go @@ -0,0 +1,31 @@ +// Code generated by "stringer -type tokenType"; DO NOT EDIT. + +package asm + +import "strconv" + +func _() { + // An "invalid array index" compiler error signifies that the constant values have changed. + // Re-run the stringer command to generate them again. + var x [1]struct{} + _ = x[eof-0] + _ = x[lineStart-1] + _ = x[lineEnd-2] + _ = x[invalidStatement-3] + _ = x[element-4] + _ = x[label-5] + _ = x[labelDef-6] + _ = x[number-7] + _ = x[stringValue-8] +} + +const _tokenType_name = "eoflineStartlineEndinvalidStatementelementlabellabelDefnumberstringValue" + +var _tokenType_index = [...]uint8{0, 3, 12, 19, 35, 42, 47, 55, 61, 72} + +func (i tokenType) String() string { + if i < 0 || i >= tokenType(len(_tokenType_index)-1) { + return "tokenType(" + strconv.FormatInt(int64(i), 10) + ")" + } + return _tokenType_name[_tokenType_index[i]:_tokenType_index[i+1]] +}
diff --git ethereum/go-ethereum/core/types/hashing_test.go taikoxyz/taiko-geth/core/types/hashing_test.go index c5b9f690d801092097e31ad786f7eaf7474e4465..d2a98ed7bf553be0a217c72c81640702875abbfa 100644 --- ethereum/go-ethereum/core/types/hashing_test.go +++ taikoxyz/taiko-geth/core/types/hashing_test.go @@ -39,7 +39,7 @@ if err != nil { t.Fatal(err) } for len(txs) < 1000 { - exp := types.DeriveSha(txs, trie.NewEmpty(trie.NewDatabase(rawdb.NewMemoryDatabase()))) + exp := types.DeriveSha(txs, trie.NewEmpty(trie.NewDatabase(rawdb.NewMemoryDatabase(), nil))) got := types.DeriveSha(txs, trie.NewStackTrie(nil)) if !bytes.Equal(got[:], exp[:]) { t.Fatalf("%d txs: got %x exp %x", len(txs), got, exp) @@ -86,7 +86,7 @@ b.Run("std_trie", func(b *testing.B) { b.ResetTimer() b.ReportAllocs() for i := 0; i < b.N; i++ { - exp = types.DeriveSha(txs, trie.NewEmpty(trie.NewDatabase(rawdb.NewMemoryDatabase()))) + exp = types.DeriveSha(txs, trie.NewEmpty(trie.NewDatabase(rawdb.NewMemoryDatabase(), nil))) } })   @@ -107,7 +107,7 @@ // increase this for longer runs -- it's set to quite low for travis rndSeed := mrand.Int() for i := 0; i < 10; i++ { seed := rndSeed + i - exp := types.DeriveSha(newDummy(i), trie.NewEmpty(trie.NewDatabase(rawdb.NewMemoryDatabase()))) + exp := types.DeriveSha(newDummy(i), trie.NewEmpty(trie.NewDatabase(rawdb.NewMemoryDatabase(), nil))) got := types.DeriveSha(newDummy(i), trie.NewStackTrie(nil)) if !bytes.Equal(got[:], exp[:]) { printList(newDummy(seed)) @@ -135,7 +135,7 @@ "0xca410605310cdc3bb8d4977ae4f0143df54a724ed873457e2272f39d66e0460e971d9d", }, } for i, tc := range tcs[1:] { - exp := types.DeriveSha(flatList(tc), trie.NewEmpty(trie.NewDatabase(rawdb.NewMemoryDatabase()))) + exp := types.DeriveSha(flatList(tc), trie.NewEmpty(trie.NewDatabase(rawdb.NewMemoryDatabase(), nil))) got := types.DeriveSha(flatList(tc), trie.NewStackTrie(nil)) if !bytes.Equal(got[:], exp[:]) { t.Fatalf("case %d: got %x exp %x", i, got, exp)
diff --git ethereum/go-ethereum/core/rawdb/databases_non64bit.go taikoxyz/taiko-geth/core/rawdb/databases_non64bit.go deleted file mode 100644 index 1f10c2f52bd209013f7d5e74539501b0ea13da0a..0000000000000000000000000000000000000000 --- ethereum/go-ethereum/core/rawdb/databases_non64bit.go +++ /dev/null @@ -1,34 +0,0 @@ -// Copyright 2023 The go-ethereum Authors -// This file is part of the go-ethereum library. -// -// The go-ethereum library is free software: you can redistribute it and/or modify -// it under the terms of the GNU Lesser General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// The go-ethereum library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Lesser General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public License -// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>. - -//go:build !((arm64 || amd64) && !openbsd) - -package rawdb - -import ( - "errors" - - "github.com/ethereum/go-ethereum/ethdb" -) - -// Pebble is unsuported on 32bit architecture -const PebbleEnabled = false - -// NewPebbleDBDatabase creates a persistent key-value database without a freezer -// moving immutable chain segments into cold storage. -func NewPebbleDBDatabase(file string, cache int, handles int, namespace string, readonly bool) (ethdb.Database, error) { - return nil, errors.New("pebble is not supported on this platform") -}
diff --git ethereum/go-ethereum/core/rawdb/accessors_metadata.go taikoxyz/taiko-geth/core/rawdb/accessors_metadata.go index 2ff29d1add93938a5f76f621ce6b47af179d9aca..859566f722f5960b0ce417514d6f20ff35a5cbe9 100644 --- ethereum/go-ethereum/core/rawdb/accessors_metadata.go +++ taikoxyz/taiko-geth/core/rawdb/accessors_metadata.go @@ -111,10 +111,10 @@ // - a count of how many old unclean-shutdowns have been discarded func PushUncleanShutdownMarker(db ethdb.KeyValueStore) ([]uint64, uint64, error) { var uncleanShutdowns crashList // Read old data - if data, err := db.Get(uncleanShutdownKey); err != nil { - log.Warn("Error reading unclean shutdown markers", "error", err) - } else if err := rlp.DecodeBytes(data, &uncleanShutdowns); err != nil { - return nil, 0, err + if data, err := db.Get(uncleanShutdownKey); err == nil { + if err := rlp.DecodeBytes(data, &uncleanShutdowns); err != nil { + return nil, 0, err + } } var discarded = uncleanShutdowns.Discarded var previous = make([]uint64, len(uncleanShutdowns.Recent))
diff --git ethereum/go-ethereum/core/vm/gas_table.go taikoxyz/taiko-geth/core/vm/gas_table.go index 5153c8b7a3de990d4b5bc4caae40645663236b38..4b141d8f9a5d81df32b09095c9d121c3ad7750a5 100644 --- ethereum/go-ethereum/core/vm/gas_table.go +++ taikoxyz/taiko-geth/core/vm/gas_table.go @@ -104,7 +104,7 @@ // The legacy gas metering only takes into consideration the current state // Legacy rules should be applied if we are in Petersburg (removal of EIP-1283) // OR Constantinople is not active if evm.chainRules.IsPetersburg || !evm.chainRules.IsConstantinople { - // This checks for 3 scenario's and calculates gas accordingly: + // This checks for 3 scenarios and calculates gas accordingly: // // 1. From a zero-value address to a non-zero value (NEW VALUE) // 2. From a non-zero value address to a zero-value address (DELETE)
diff --git ethereum/go-ethereum/core/rawdb/ancient_utils.go taikoxyz/taiko-geth/core/rawdb/ancient_utils.go index 363a911aeea72ea0c32530af5f2b804fdf2d5912..dfb2fdfb67dfdbc3ba513a49d0069d06a88a9861 100644 --- ethereum/go-ethereum/core/rawdb/ancient_utils.go +++ taikoxyz/taiko-geth/core/rawdb/ancient_utils.go @@ -50,36 +50,61 @@ } return total }   +func inspect(name string, order map[string]bool, reader ethdb.AncientReader) (freezerInfo, error) { + info := freezerInfo{name: name} + for t := range order { + size, err := reader.AncientSize(t) + if err != nil { + return freezerInfo{}, err + } + info.sizes = append(info.sizes, tableSize{name: t, size: common.StorageSize(size)}) + } + // Retrieve the number of last stored item + ancients, err := reader.Ancients() + if err != nil { + return freezerInfo{}, err + } + info.head = ancients - 1 + + // Retrieve the number of first stored item + tail, err := reader.Tail() + if err != nil { + return freezerInfo{}, err + } + info.tail = tail + return info, nil +} + // inspectFreezers inspects all freezers registered in the system. func inspectFreezers(db ethdb.Database) ([]freezerInfo, error) { var infos []freezerInfo for _, freezer := range freezers { switch freezer { case chainFreezerName: - // Chain ancient store is a bit special. It's always opened along - // with the key-value store, inspect the chain store directly. - info := freezerInfo{name: freezer} - // Retrieve storage size of every contained table. - for table := range chainFreezerNoSnappy { - size, err := db.AncientSize(table) - if err != nil { - return nil, err - } - info.sizes = append(info.sizes, tableSize{name: table, size: common.StorageSize(size)}) + info, err := inspect(chainFreezerName, chainFreezerNoSnappy, db) + if err != nil { + return nil, err + } + infos = append(infos, info) + + case stateFreezerName: + if ReadStateScheme(db) != PathScheme { + continue } - // Retrieve the number of last stored item - ancients, err := db.Ancients() + datadir, err := db.AncientDatadir() if err != nil { return nil, err } - info.head = ancients - 1 + f, err := NewStateFreezer(datadir, true) + if err != nil { + return nil, err + } + defer f.Close()   - // Retrieve the number of first stored item - tail, err := db.Tail() + info, err := inspect(stateFreezerName, stateFreezerNoSnappy, f) if err != nil { return nil, err } - info.tail = tail infos = append(infos, info)   default:
diff --git ethereum/go-ethereum/core/vm/eips.go taikoxyz/taiko-geth/core/vm/eips.go index 704c1ce1274516c8bdef8edcdae4f642c96e626e..35f0a3f7c2831e6f669ad3f718123ff9deeca54e 100644 --- ethereum/go-ethereum/core/vm/eips.go +++ taikoxyz/taiko-geth/core/vm/eips.go @@ -282,14 +282,30 @@ } return nil, nil }   -// enable4844 applies EIP-4844 (DATAHASH opcode) +// opBlobBaseFee implements BLOBBASEFEE opcode +func opBlobBaseFee(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) { + blobBaseFee, _ := uint256.FromBig(interpreter.evm.Context.BlobBaseFee) + scope.Stack.push(blobBaseFee) + return nil, nil +} + +// enable4844 applies EIP-4844 (BLOBHASH opcode) func enable4844(jt *JumpTable) { - // New opcode jt[BLOBHASH] = &operation{ execute: opBlobHash, constantGas: GasFastestStep, minStack: minStack(1, 1), maxStack: maxStack(1, 1), + } +} + +// enable7516 applies EIP-7516 (BLOBBASEFEE opcode) +func enable7516(jt *JumpTable) { + jt[BLOBBASEFEE] = &operation{ + execute: opBlobBaseFee, + constantGas: GasQuickStep, + minStack: minStack(0, 1), + maxStack: maxStack(0, 1), } }
diff --git ethereum/go-ethereum/core/state/statedb_fuzz_test.go taikoxyz/taiko-geth/core/state/statedb_fuzz_test.go index 17d60c9ba6295fff50057c93637719a7838841c5..c4704257c73f6f10a8bf31c90288c17ee15f9690 100644 --- ethereum/go-ethereum/core/state/statedb_fuzz_test.go +++ taikoxyz/taiko-geth/core/state/statedb_fuzz_test.go @@ -31,10 +31,12 @@ "testing/quick"   "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/core/rawdb" + "github.com/ethereum/go-ethereum/core/state/snapshot" "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/crypto" "github.com/ethereum/go-ethereum/rlp" "github.com/ethereum/go-ethereum/trie" + "github.com/ethereum/go-ethereum/trie/triedb/pathdb" "github.com/ethereum/go-ethereum/trie/triestate" )   @@ -179,19 +181,33 @@ accountList = append(accountList, copySet(states.Accounts)) storageList = append(storageList, copy2DSet(states.Storages)) } disk = rawdb.NewMemoryDatabase() - tdb = trie.NewDatabaseWithConfig(disk, &trie.Config{OnCommit: onCommit}) + tdb = trie.NewDatabase(disk, &trie.Config{PathDB: pathdb.Defaults}) sdb = NewDatabaseWithNodeDB(disk, tdb) byzantium = rand.Intn(2) == 0 ) + defer disk.Close() + defer tdb.Close() + + var snaps *snapshot.Tree + if rand.Intn(3) == 0 { + snaps, _ = snapshot.New(snapshot.Config{ + CacheSize: 1, + Recovery: false, + NoBuild: false, + AsyncBuild: false, + }, disk, tdb, types.EmptyRootHash) + } for i, actions := range test.actions { root := types.EmptyRootHash if i != 0 { root = roots[len(roots)-1] } - state, err := New(root, sdb, nil) + state, err := New(root, sdb, snaps) if err != nil { panic(err) } + state.onCommit = onCommit + for i, action := range actions { if i%test.chunk == 0 && i != 0 { if byzantium {
diff --git ethereum/go-ethereum/core/state/trie_prefetcher.go taikoxyz/taiko-geth/core/state/trie_prefetcher.go index 4e8fd1e10f576bdf3a8c3ea7847661f1cded7ffd..772c698dd0e1ef21370855f68ef16676c60c6786 100644 --- ethereum/go-ethereum/core/state/trie_prefetcher.go +++ taikoxyz/taiko-geth/core/state/trie_prefetcher.go @@ -37,7 +37,7 @@ // Note, the prefetcher's API is not thread safe. type triePrefetcher struct { db Database // Database to fetch trie nodes through root common.Hash // Root hash of the account trie for metrics - fetches map[string]Trie // Partially or fully fetcher tries + fetches map[string]Trie // Partially or fully fetched tries. Only populated for inactive copies. fetchers map[string]*subfetcher // Subfetchers for each trie   deliveryMissMeter metrics.Meter @@ -197,7 +197,10 @@ }   // trieID returns an unique trie identifier consists the trie owner and root hash. func (p *triePrefetcher) trieID(owner common.Hash, root common.Hash) string { - return string(append(owner.Bytes(), root.Bytes()...)) + trieID := make([]byte, common.HashLength*2) + copy(trieID, owner.Bytes()) + copy(trieID[common.HashLength:], root.Bytes()) + return string(trieID) }   // subfetcher is a trie fetcher goroutine responsible for pulling entries for a
diff --git ethereum/go-ethereum/core/types/hashing.go taikoxyz/taiko-geth/core/types/hashing.go index fbdeaf0d0793c61b2e8e8c08cfb265e2468c387e..224d7a87eafcb5bd8e45a0bfc4eda07aa997f815 100644 --- ethereum/go-ethereum/core/types/hashing.go +++ taikoxyz/taiko-geth/core/types/hashing.go @@ -18,6 +18,8 @@ package types   import ( "bytes" + "fmt" + "math" "sync"   "github.com/ethereum/go-ethereum/common" @@ -34,6 +36,22 @@ // encodeBufferPool holds temporary encoder buffers for DeriveSha and TX encoding. var encodeBufferPool = sync.Pool{ New: func() interface{} { return new(bytes.Buffer) }, +} + +// getPooledBuffer retrieves a buffer from the pool and creates a byte slice of the +// requested size from it. +// +// The caller should return the *bytes.Buffer object back into encodeBufferPool after use! +// The returned byte slice must not be used after returning the buffer. +func getPooledBuffer(size uint64) ([]byte, *bytes.Buffer, error) { + if size > math.MaxInt { + return nil, nil, fmt.Errorf("can't get buffer of size %d", size) + } + buf := encodeBufferPool.Get().(*bytes.Buffer) + buf.Reset() + buf.Grow(int(size)) + b := buf.Bytes()[:int(size)] + return b, buf, nil }   // rlpHash encodes x and hashes the encoded bytes. @@ -77,7 +95,7 @@ func encodeForDerive(list DerivableList, i int, buf *bytes.Buffer) []byte { buf.Reset() list.EncodeIndex(i, buf) - // It's really unfortunate that we need to do perform this copy. + // It's really unfortunate that we need to perform this copy. // StackTrie holds onto the values until Hash is called, so the values // written to it must not alias. return common.CopyBytes(buf.Bytes())
diff --git ethereum/go-ethereum/core/state/sync_test.go taikoxyz/taiko-geth/core/state/sync_test.go index b065ad8355c3432c3e181b1b78e48339df6d3c81..6196e77817e2beee52dc3a976548440e7ac271be 100644 --- ethereum/go-ethereum/core/state/sync_test.go +++ taikoxyz/taiko-geth/core/state/sync_test.go @@ -28,6 +28,8 @@ "github.com/ethereum/go-ethereum/crypto" "github.com/ethereum/go-ethereum/ethdb" "github.com/ethereum/go-ethereum/rlp" "github.com/ethereum/go-ethereum/trie" + "github.com/ethereum/go-ethereum/trie/triedb/hashdb" + "github.com/ethereum/go-ethereum/trie/triedb/pathdb" )   // testAccount is the data associated with an account used by the state tests. @@ -39,10 +41,17 @@ code []byte }   // makeTestState create a sample test state to test node-wise reconstruction. -func makeTestState() (ethdb.Database, Database, common.Hash, []*testAccount) { +func makeTestState(scheme string) (ethdb.Database, Database, *trie.Database, common.Hash, []*testAccount) { // Create an empty state + config := &trie.Config{Preimages: true} + if scheme == rawdb.PathScheme { + config.PathDB = pathdb.Defaults + } else { + config.HashDB = hashdb.Defaults + } db := rawdb.NewMemoryDatabase() - sdb := NewDatabaseWithConfig(db, &trie.Config{Preimages: true}) + nodeDb := trie.NewDatabase(db, config) + sdb := NewDatabaseWithNodeDB(db, nodeDb) state, _ := New(types.EmptyRootHash, sdb, nil)   // Fill it with some arbitrary data @@ -67,24 +76,27 @@ hash := crypto.Keccak256Hash([]byte{i, i, i, i, i, j, j}) obj.SetState(hash, hash) } } - state.updateStateObject(obj) accounts = append(accounts, acc) } root, _ := state.Commit(0, false)   // Return the generated state - return db, sdb, root, accounts + return db, sdb, nodeDb, root, accounts }   // checkStateAccounts cross references a reconstructed state with an expected // account array. -func checkStateAccounts(t *testing.T, db ethdb.Database, root common.Hash, accounts []*testAccount) { +func checkStateAccounts(t *testing.T, db ethdb.Database, scheme string, root common.Hash, accounts []*testAccount) { + var config trie.Config + if scheme == rawdb.PathScheme { + config.PathDB = pathdb.Defaults + } // Check root availability and state contents - state, err := New(root, NewDatabase(db), nil) + state, err := New(root, NewDatabaseWithConfig(db, &config), nil) if err != nil { t.Fatalf("failed to create state trie at %x: %v", root, err) } - if err := checkStateConsistency(db, root); err != nil { + if err := checkStateConsistency(db, scheme, root); err != nil { t.Fatalf("inconsistent state trie at %x: %v", root, err) } for i, acc := range accounts { @@ -101,8 +113,12 @@ } }   // checkStateConsistency checks that all data of a state root is present. -func checkStateConsistency(db ethdb.Database, root common.Hash) error { - state, err := New(root, NewDatabaseWithConfig(db, &trie.Config{Preimages: true}), nil) +func checkStateConsistency(db ethdb.Database, scheme string, root common.Hash) error { + config := &trie.Config{Preimages: true} + if scheme == rawdb.PathScheme { + config.PathDB = pathdb.Defaults + } + state, err := New(root, NewDatabaseWithConfig(db, config), nil) if err != nil { return err } @@ -114,8 +130,14 @@ }   // Tests that an empty state is not scheduled for syncing. func TestEmptyStateSync(t *testing.T) { - db := trie.NewDatabase(rawdb.NewMemoryDatabase()) - sync := NewStateSync(types.EmptyRootHash, rawdb.NewMemoryDatabase(), nil, db.Scheme()) + dbA := trie.NewDatabase(rawdb.NewMemoryDatabase(), nil) + dbB := trie.NewDatabase(rawdb.NewMemoryDatabase(), &trie.Config{PathDB: pathdb.Defaults}) + + sync := NewStateSync(types.EmptyRootHash, rawdb.NewMemoryDatabase(), nil, dbA.Scheme()) + if paths, nodes, codes := sync.Missing(1); len(paths) != 0 || len(nodes) != 0 || len(codes) != 0 { + t.Errorf("content requested for empty state: %v, %v, %v", nodes, paths, codes) + } + sync = NewStateSync(types.EmptyRootHash, rawdb.NewMemoryDatabase(), nil, dbB.Scheme()) if paths, nodes, codes := sync.Missing(1); len(paths) != 0 || len(nodes) != 0 || len(codes) != 0 { t.Errorf("content requested for empty state: %v, %v, %v", nodes, paths, codes) } @@ -124,22 +146,28 @@ // Tests that given a root hash, a state can sync iteratively on a single thread, // requesting retrieval tasks and returning all of them in one go. func TestIterativeStateSyncIndividual(t *testing.T) { - testIterativeStateSync(t, 1, false, false) + testIterativeStateSync(t, 1, false, false, rawdb.HashScheme) + testIterativeStateSync(t, 1, false, false, rawdb.PathScheme) } func TestIterativeStateSyncBatched(t *testing.T) { - testIterativeStateSync(t, 100, false, false) + testIterativeStateSync(t, 100, false, false, rawdb.HashScheme) + testIterativeStateSync(t, 100, false, false, rawdb.PathScheme) } func TestIterativeStateSyncIndividualFromDisk(t *testing.T) { - testIterativeStateSync(t, 1, true, false) + testIterativeStateSync(t, 1, true, false, rawdb.HashScheme) + testIterativeStateSync(t, 1, true, false, rawdb.PathScheme) } func TestIterativeStateSyncBatchedFromDisk(t *testing.T) { - testIterativeStateSync(t, 100, true, false) + testIterativeStateSync(t, 100, true, false, rawdb.HashScheme) + testIterativeStateSync(t, 100, true, false, rawdb.PathScheme) } func TestIterativeStateSyncIndividualByPath(t *testing.T) { - testIterativeStateSync(t, 1, false, true) + testIterativeStateSync(t, 1, false, true, rawdb.HashScheme) + testIterativeStateSync(t, 1, false, true, rawdb.PathScheme) } func TestIterativeStateSyncBatchedByPath(t *testing.T) { - testIterativeStateSync(t, 100, false, true) + testIterativeStateSync(t, 100, false, true, rawdb.HashScheme) + testIterativeStateSync(t, 100, false, true, rawdb.PathScheme) }   // stateElement represents the element in the state trie(bytecode or trie node). @@ -150,17 +178,17 @@ code common.Hash syncPath trie.SyncPath }   -func testIterativeStateSync(t *testing.T, count int, commit bool, bypath bool) { +func testIterativeStateSync(t *testing.T, count int, commit bool, bypath bool, scheme string) { // Create a random state to copy - srcDisk, srcDb, srcRoot, srcAccounts := makeTestState() + srcDisk, srcDb, ndb, srcRoot, srcAccounts := makeTestState(scheme) if commit { - srcDb.TrieDB().Commit(srcRoot, false) + ndb.Commit(srcRoot, false) } - srcTrie, _ := trie.New(trie.StateTrieID(srcRoot), srcDb.TrieDB()) + srcTrie, _ := trie.New(trie.StateTrieID(srcRoot), ndb)   // Create a destination state and sync with the scheduler dstDb := rawdb.NewMemoryDatabase() - sched := NewStateSync(srcRoot, dstDb, nil, srcDb.TrieDB().Scheme()) + sched := NewStateSync(srcRoot, dstDb, nil, ndb.Scheme())   var ( nodeElements []stateElement @@ -175,9 +203,11 @@ syncPath: trie.NewSyncPath([]byte(paths[i])), }) } for i := 0; i < len(codes); i++ { - codeElements = append(codeElements, stateElement{ - code: codes[i], - }) + codeElements = append(codeElements, stateElement{code: codes[i]}) + } + reader, err := ndb.Reader(srcRoot) + if err != nil { + t.Fatalf("state is not existent, %#x", srcRoot) } for len(nodeElements)+len(codeElements) > 0 { var ( @@ -205,7 +235,7 @@ if err := rlp.DecodeBytes(srcTrie.MustGet(node.syncPath[0]), &acc); err != nil { t.Fatalf("failed to decode account on path %x: %v", node.syncPath[0], err) } id := trie.StorageTrieID(srcRoot, common.BytesToHash(node.syncPath[0]), acc.Root) - stTrie, err := trie.New(id, srcDb.TrieDB()) + stTrie, err := trie.New(id, ndb) if err != nil { t.Fatalf("failed to retriev storage trie for path %x: %v", node.syncPath[1], err) } @@ -216,7 +246,8 @@ } nodeResults[i] = trie.NodeSyncResult{Path: node.path, Data: data} } } else { - data, err := srcDb.TrieDB().Node(node.hash) + owner, inner := trie.ResolvePath([]byte(node.path)) + data, err := reader.Node(owner, inner, node.hash) if err != nil { t.Fatalf("failed to retrieve node data for key %v", []byte(node.path)) } @@ -260,18 +291,23 @@ srcDb.TrieDB().WritePreimages() copyPreimages(srcDisk, dstDb)   // Cross check that the two states are in sync - checkStateAccounts(t, dstDb, srcRoot, srcAccounts) + checkStateAccounts(t, dstDb, ndb.Scheme(), srcRoot, srcAccounts) }   // Tests that the trie scheduler can correctly reconstruct the state even if only // partial results are returned, and the others sent only later. func TestIterativeDelayedStateSync(t *testing.T) { + testIterativeDelayedStateSync(t, rawdb.HashScheme) + testIterativeDelayedStateSync(t, rawdb.PathScheme) +} + +func testIterativeDelayedStateSync(t *testing.T, scheme string) { // Create a random state to copy - srcDisk, srcDb, srcRoot, srcAccounts := makeTestState() + srcDisk, srcDb, ndb, srcRoot, srcAccounts := makeTestState(scheme)   // Create a destination state and sync with the scheduler dstDb := rawdb.NewMemoryDatabase() - sched := NewStateSync(srcRoot, dstDb, nil, srcDb.TrieDB().Scheme()) + sched := NewStateSync(srcRoot, dstDb, nil, ndb.Scheme())   var ( nodeElements []stateElement @@ -286,9 +322,11 @@ syncPath: trie.NewSyncPath([]byte(paths[i])), }) } for i := 0; i < len(codes); i++ { - codeElements = append(codeElements, stateElement{ - code: codes[i], - }) + codeElements = append(codeElements, stateElement{code: codes[i]}) + } + reader, err := ndb.Reader(srcRoot) + if err != nil { + t.Fatalf("state is not existent, %#x", srcRoot) } for len(nodeElements)+len(codeElements) > 0 { // Sync only half of the scheduled nodes @@ -313,7 +351,8 @@ } if len(nodeElements) > 0 { nodeResults := make([]trie.NodeSyncResult, len(nodeElements)/2+1) for i, element := range nodeElements[:len(nodeResults)] { - data, err := srcDb.TrieDB().Node(element.hash) + owner, inner := trie.ResolvePath([]byte(element.path)) + data, err := reader.Node(owner, inner, element.hash) if err != nil { t.Fatalf("failed to retrieve contract bytecode for %x", element.code) } @@ -353,22 +392,28 @@ srcDb.TrieDB().WritePreimages() copyPreimages(srcDisk, dstDb)   // Cross check that the two states are in sync - checkStateAccounts(t, dstDb, srcRoot, srcAccounts) + checkStateAccounts(t, dstDb, ndb.Scheme(), srcRoot, srcAccounts) }   // Tests that given a root hash, a trie can sync iteratively on a single thread, // requesting retrieval tasks and returning all of them in one go, however in a // random order. -func TestIterativeRandomStateSyncIndividual(t *testing.T) { testIterativeRandomStateSync(t, 1) } -func TestIterativeRandomStateSyncBatched(t *testing.T) { testIterativeRandomStateSync(t, 100) } +func TestIterativeRandomStateSyncIndividual(t *testing.T) { + testIterativeRandomStateSync(t, 1, rawdb.HashScheme) + testIterativeRandomStateSync(t, 1, rawdb.PathScheme) +} +func TestIterativeRandomStateSyncBatched(t *testing.T) { + testIterativeRandomStateSync(t, 100, rawdb.HashScheme) + testIterativeRandomStateSync(t, 100, rawdb.PathScheme) +}   -func testIterativeRandomStateSync(t *testing.T, count int) { +func testIterativeRandomStateSync(t *testing.T, count int, scheme string) { // Create a random state to copy - srcDisk, srcDb, srcRoot, srcAccounts := makeTestState() + srcDisk, srcDb, ndb, srcRoot, srcAccounts := makeTestState(scheme)   // Create a destination state and sync with the scheduler dstDb := rawdb.NewMemoryDatabase() - sched := NewStateSync(srcRoot, dstDb, nil, srcDb.TrieDB().Scheme()) + sched := NewStateSync(srcRoot, dstDb, nil, ndb.Scheme())   nodeQueue := make(map[string]stateElement) codeQueue := make(map[common.Hash]struct{}) @@ -383,6 +428,10 @@ } for _, hash := range codes { codeQueue[hash] = struct{}{} } + reader, err := ndb.Reader(srcRoot) + if err != nil { + t.Fatalf("state is not existent, %#x", srcRoot) + } for len(nodeQueue)+len(codeQueue) > 0 { // Fetch all the queued nodes in a random order if len(codeQueue) > 0 { @@ -403,7 +452,8 @@ } if len(nodeQueue) > 0 { results := make([]trie.NodeSyncResult, 0, len(nodeQueue)) for path, element := range nodeQueue { - data, err := srcDb.TrieDB().Node(element.hash) + owner, inner := trie.ResolvePath([]byte(element.path)) + data, err := reader.Node(owner, inner, element.hash) if err != nil { t.Fatalf("failed to retrieve node data for %x %v %v", element.hash, []byte(element.path), element.path) } @@ -415,7 +465,6 @@ t.Fatalf("failed to process result %v", err) } } } - // Feed the retrieved results back and queue new tasks batch := dstDb.NewBatch() if err := sched.Commit(batch); err != nil { t.Fatalf("failed to commit data: %v", err) @@ -441,18 +490,23 @@ srcDb.TrieDB().WritePreimages() copyPreimages(srcDisk, dstDb)   // Cross check that the two states are in sync - checkStateAccounts(t, dstDb, srcRoot, srcAccounts) + checkStateAccounts(t, dstDb, ndb.Scheme(), srcRoot, srcAccounts) }   // Tests that the trie scheduler can correctly reconstruct the state even if only // partial results are returned (Even those randomly), others sent only later. func TestIterativeRandomDelayedStateSync(t *testing.T) { + testIterativeRandomDelayedStateSync(t, rawdb.HashScheme) + testIterativeRandomDelayedStateSync(t, rawdb.PathScheme) +} + +func testIterativeRandomDelayedStateSync(t *testing.T, scheme string) { // Create a random state to copy - srcDisk, srcDb, srcRoot, srcAccounts := makeTestState() + srcDisk, srcDb, ndb, srcRoot, srcAccounts := makeTestState(scheme)   // Create a destination state and sync with the scheduler dstDb := rawdb.NewMemoryDatabase() - sched := NewStateSync(srcRoot, dstDb, nil, srcDb.TrieDB().Scheme()) + sched := NewStateSync(srcRoot, dstDb, nil, ndb.Scheme())   nodeQueue := make(map[string]stateElement) codeQueue := make(map[common.Hash]struct{}) @@ -466,6 +520,10 @@ } } for _, hash := range codes { codeQueue[hash] = struct{}{} + } + reader, err := ndb.Reader(srcRoot) + if err != nil { + t.Fatalf("state is not existent, %#x", srcRoot) } for len(nodeQueue)+len(codeQueue) > 0 { // Sync only half of the scheduled nodes, even those in random order @@ -495,7 +553,8 @@ results := make([]trie.NodeSyncResult, 0, len(nodeQueue)/2+1) for path, element := range nodeQueue { delete(nodeQueue, path)   - data, err := srcDb.TrieDB().Node(element.hash) + owner, inner := trie.ResolvePath([]byte(element.path)) + data, err := reader.Node(owner, inner, element.hash) if err != nil { t.Fatalf("failed to retrieve node data for %x", element.hash) } @@ -535,14 +594,19 @@ srcDb.TrieDB().WritePreimages() copyPreimages(srcDisk, dstDb)   // Cross check that the two states are in sync - checkStateAccounts(t, dstDb, srcRoot, srcAccounts) + checkStateAccounts(t, dstDb, ndb.Scheme(), srcRoot, srcAccounts) }   // Tests that at any point in time during a sync, only complete sub-tries are in // the database. func TestIncompleteStateSync(t *testing.T) { + testIncompleteStateSync(t, rawdb.HashScheme) + testIncompleteStateSync(t, rawdb.PathScheme) +} + +func testIncompleteStateSync(t *testing.T, scheme string) { // Create a random state to copy - db, srcDb, srcRoot, srcAccounts := makeTestState() + db, srcDb, ndb, srcRoot, srcAccounts := makeTestState(scheme)   // isCodeLookup to save some hashing var isCode = make(map[common.Hash]struct{}) @@ -555,14 +619,14 @@ isCode[types.EmptyCodeHash] = struct{}{}   // Create a destination state and sync with the scheduler dstDb := rawdb.NewMemoryDatabase() - sched := NewStateSync(srcRoot, dstDb, nil, srcDb.TrieDB().Scheme()) + sched := NewStateSync(srcRoot, dstDb, nil, ndb.Scheme())   var ( addedCodes []common.Hash addedPaths []string addedHashes []common.Hash ) - reader, err := srcDb.TrieDB().Reader(srcRoot) + reader, err := ndb.Reader(srcRoot) if err != nil { t.Fatalf("state is not available %x", srcRoot) } @@ -649,12 +713,11 @@ // Sanity check that removing any node from the database is detected for _, node := range addedCodes { val := rawdb.ReadCode(dstDb, node) rawdb.DeleteCode(dstDb, node) - if err := checkStateConsistency(dstDb, srcRoot); err == nil { + if err := checkStateConsistency(dstDb, ndb.Scheme(), srcRoot); err == nil { t.Errorf("trie inconsistency not caught, missing: %x", node) } rawdb.WriteCode(dstDb, node, val) } - scheme := srcDb.TrieDB().Scheme() for i, path := range addedPaths { owner, inner := trie.ResolvePath([]byte(path)) hash := addedHashes[i] @@ -663,7 +726,7 @@ if val == nil { t.Error("missing trie node") } rawdb.DeleteTrieNode(dstDb, owner, inner, hash, scheme) - if err := checkStateConsistency(dstDb, srcRoot); err == nil { + if err := checkStateConsistency(dstDb, scheme, srcRoot); err == nil { t.Errorf("trie inconsistency not caught, missing: %v", path) } rawdb.WriteTrieNode(dstDb, owner, inner, hash, val, scheme)
diff --git ethereum/go-ethereum/core/types/tx_blob_test.go taikoxyz/taiko-geth/core/types/tx_blob_test.go new file mode 100644 index 0000000000000000000000000000000000000000..44ac48cc6faca58dabaf1f6e640f4bfaad38d8ca --- /dev/null +++ taikoxyz/taiko-geth/core/types/tx_blob_test.go @@ -0,0 +1,90 @@ +package types + +import ( + "crypto/ecdsa" + "testing" + + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/crypto" + "github.com/ethereum/go-ethereum/crypto/kzg4844" + "github.com/holiman/uint256" +) + +// This test verifies that tx.Hash() is not affected by presence of a BlobTxSidecar. +func TestBlobTxHashing(t *testing.T) { + key, _ := crypto.GenerateKey() + withBlobs := createEmptyBlobTx(key, true) + withBlobsStripped := withBlobs.WithoutBlobTxSidecar() + withoutBlobs := createEmptyBlobTx(key, false) + + hash := withBlobs.Hash() + t.Log("tx hash:", hash) + + if h := withBlobsStripped.Hash(); h != hash { + t.Fatal("wrong tx hash after WithoutBlobTxSidecar:", h) + } + if h := withoutBlobs.Hash(); h != hash { + t.Fatal("wrong tx hash on tx created without sidecar:", h) + } +} + +// This test verifies that tx.Size() takes BlobTxSidecar into account. +func TestBlobTxSize(t *testing.T) { + key, _ := crypto.GenerateKey() + withBlobs := createEmptyBlobTx(key, true) + withBlobsStripped := withBlobs.WithoutBlobTxSidecar() + withoutBlobs := createEmptyBlobTx(key, false) + + withBlobsEnc, _ := withBlobs.MarshalBinary() + withoutBlobsEnc, _ := withoutBlobs.MarshalBinary() + + size := withBlobs.Size() + t.Log("size with blobs:", size) + + sizeNoBlobs := withoutBlobs.Size() + t.Log("size without blobs:", sizeNoBlobs) + + if size != uint64(len(withBlobsEnc)) { + t.Error("wrong size with blobs:", size, "encoded length:", len(withBlobsEnc)) + } + if sizeNoBlobs != uint64(len(withoutBlobsEnc)) { + t.Error("wrong size without blobs:", sizeNoBlobs, "encoded length:", len(withoutBlobsEnc)) + } + if sizeNoBlobs >= size { + t.Error("size without blobs >= size with blobs") + } + if sz := withBlobsStripped.Size(); sz != sizeNoBlobs { + t.Fatal("wrong size on tx after WithoutBlobTxSidecar:", sz) + } +} + +var ( + emptyBlob = kzg4844.Blob{} + emptyBlobCommit, _ = kzg4844.BlobToCommitment(emptyBlob) + emptyBlobProof, _ = kzg4844.ComputeBlobProof(emptyBlob, emptyBlobCommit) +) + +func createEmptyBlobTx(key *ecdsa.PrivateKey, withSidecar bool) *Transaction { + sidecar := &BlobTxSidecar{ + Blobs: []kzg4844.Blob{emptyBlob}, + Commitments: []kzg4844.Commitment{emptyBlobCommit}, + Proofs: []kzg4844.Proof{emptyBlobProof}, + } + blobtx := &BlobTx{ + ChainID: uint256.NewInt(1), + Nonce: 5, + GasTipCap: uint256.NewInt(22), + GasFeeCap: uint256.NewInt(5), + Gas: 25000, + To: common.Address{0x03, 0x04, 0x05}, + Value: uint256.NewInt(99), + Data: make([]byte, 50), + BlobFeeCap: uint256.NewInt(15), + BlobHashes: sidecar.BlobHashes(), + } + if withSidecar { + blobtx.Sidecar = sidecar + } + signer := NewCancunSigner(blobtx.ChainID.ToBig()) + return MustSignNewTx(key, signer, blobtx) +}
diff --git ethereum/go-ethereum/core/asm/compiler.go taikoxyz/taiko-geth/core/asm/compiler.go index 4b1d379206f61d66ca8e75db33173483fa71905a..02c589b2c1a90a49fbe1bc1dbbabeecf7e15037a 100644 --- ethereum/go-ethereum/core/asm/compiler.go +++ taikoxyz/taiko-geth/core/asm/compiler.go @@ -17,6 +17,8 @@ package asm   import ( + "encoding/hex" + "errors" "fmt" "math/big" "os" @@ -30,7 +32,7 @@ // Compiler contains information about the parsed source // and holds the tokens for the program. type Compiler struct { tokens []token - binary []interface{} + out []byte   labels map[string]int   @@ -47,15 +49,13 @@ debug: debug, } }   -// Feed feeds tokens in to ch and are interpreted by +// Feed feeds tokens into ch and are interpreted by // the compiler. // -// feed is the first pass in the compile stage as it -// collects the used labels in the program and keeps a -// program counter which is used to determine the locations -// of the jump dests. The labels can than be used in the -// second stage to push labels and determine the right -// position. +// feed is the first pass in the compile stage as it collects the used labels in the +// program and keeps a program counter which is used to determine the locations of the +// jump dests. The labels can than be used in the second stage to push labels and +// determine the right position. func (c *Compiler) Feed(ch <-chan token) { var prev token for i := range ch { @@ -79,7 +79,6 @@ if prev.typ == element && isJump(prev.text) { c.pc++ } } - c.tokens = append(c.tokens, i) prev = i } @@ -88,12 +87,11 @@ fmt.Fprintln(os.Stderr, "found", len(c.labels), "labels") } }   -// Compile compiles the current tokens and returns a -// binary string that can be interpreted by the EVM -// and an error if it failed. +// Compile compiles the current tokens and returns a binary string that can be interpreted +// by the EVM and an error if it failed. // -// compile is the second stage in the compile phase -// which compiles the tokens to EVM instructions. +// compile is the second stage in the compile phase which compiles the tokens to EVM +// instructions. func (c *Compiler) Compile() (string, []error) { var errors []error // continue looping over the tokens until @@ -105,16 +103,8 @@ } }   // turn the binary to hex - var bin strings.Builder - for _, v := range c.binary { - switch v := v.(type) { - case vm.OpCode: - bin.WriteString(fmt.Sprintf("%x", []byte{byte(v)})) - case []byte: - bin.WriteString(fmt.Sprintf("%x", v)) - } - } - return bin.String(), errors + h := hex.EncodeToString(c.out) + return h, errors }   // next returns the next token and increments the @@ -156,87 +146,114 @@ return nil }   -// compileNumber compiles the number to bytes -func (c *Compiler) compileNumber(element token) { - num := math.MustParseBig256(element.text).Bytes() - if len(num) == 0 { - num = []byte{0} +// parseNumber compiles the number to bytes +func parseNumber(tok token) ([]byte, error) { + if tok.typ != number { + panic("parseNumber of non-number token") + } + num, ok := math.ParseBig256(tok.text) + if !ok { + return nil, errors.New("invalid number") + } + bytes := num.Bytes() + if len(bytes) == 0 { + bytes = []byte{0} } - c.pushBin(num) + return bytes, nil }   // compileElement compiles the element (push & label or both) // to a binary representation and may error if incorrect statements // where fed. func (c *Compiler) compileElement(element token) error { - // check for a jump. jumps must be read and compiled - // from right to left. - if isJump(element.text) { - rvalue := c.next() - switch rvalue.typ { - case number: - // TODO figure out how to return the error properly - c.compileNumber(rvalue) - case stringValue: - // strings are quoted, remove them. - c.pushBin(rvalue.text[1 : len(rvalue.text)-2]) - case label: - c.pushBin(vm.PUSH4) - pos := big.NewInt(int64(c.labels[rvalue.text])).Bytes() - pos = append(make([]byte, 4-len(pos)), pos...) - c.pushBin(pos) - case lineEnd: - c.pos-- - default: - return compileErr(rvalue, rvalue.text, "number, string or label") - } - // push the operation - c.pushBin(toBinary(element.text)) + switch { + case isJump(element.text): + return c.compileJump(element.text) + case isPush(element.text): + return c.compilePush() + default: + c.outputOpcode(toBinary(element.text)) return nil - } else if isPush(element.text) { - // handle pushes. pushes are read from left to right. - var value []byte + } +}   - rvalue := c.next() - switch rvalue.typ { - case number: - value = math.MustParseBig256(rvalue.text).Bytes() - if len(value) == 0 { - value = []byte{0} - } - case stringValue: - value = []byte(rvalue.text[1 : len(rvalue.text)-1]) - case label: - value = big.NewInt(int64(c.labels[rvalue.text])).Bytes() - value = append(make([]byte, 4-len(value)), value...) - default: - return compileErr(rvalue, rvalue.text, "number, string or label") +func (c *Compiler) compileJump(jumpType string) error { + rvalue := c.next() + switch rvalue.typ { + case number: + numBytes, err := parseNumber(rvalue) + if err != nil { + return err } + c.outputBytes(numBytes)   - if len(value) > 32 { - return fmt.Errorf("%d type error: unsupported string or number with size > 32", rvalue.lineno) - } + case stringValue: + // strings are quoted, remove them. + str := rvalue.text[1 : len(rvalue.text)-2] + c.outputBytes([]byte(str)) + + case label: + c.outputOpcode(vm.PUSH4) + pos := big.NewInt(int64(c.labels[rvalue.text])).Bytes() + pos = append(make([]byte, 4-len(pos)), pos...) + c.outputBytes(pos) + + case lineEnd: + // push without argument is supported, it just takes the destination from the stack. + c.pos--   - c.pushBin(vm.OpCode(int(vm.PUSH1) - 1 + len(value))) - c.pushBin(value) - } else { - c.pushBin(toBinary(element.text)) + default: + return compileErr(rvalue, rvalue.text, "number, string or label") } + // push the operation + c.outputOpcode(toBinary(jumpType)) + return nil +}   +func (c *Compiler) compilePush() error { + // handle pushes. pushes are read from left to right. + var value []byte + rvalue := c.next() + switch rvalue.typ { + case number: + value = math.MustParseBig256(rvalue.text).Bytes() + if len(value) == 0 { + value = []byte{0} + } + case stringValue: + value = []byte(rvalue.text[1 : len(rvalue.text)-1]) + case label: + value = big.NewInt(int64(c.labels[rvalue.text])).Bytes() + value = append(make([]byte, 4-len(value)), value...) + default: + return compileErr(rvalue, rvalue.text, "number, string or label") + } + if len(value) > 32 { + return fmt.Errorf("%d: string or number size > 32 bytes", rvalue.lineno+1) + } + c.outputOpcode(vm.OpCode(int(vm.PUSH1) - 1 + len(value))) + c.outputBytes(value) return nil }   // compileLabel pushes a jumpdest to the binary slice. func (c *Compiler) compileLabel() { - c.pushBin(vm.JUMPDEST) + c.outputOpcode(vm.JUMPDEST) }   -// pushBin pushes the value v to the binary stack. -func (c *Compiler) pushBin(v interface{}) { +func (c *Compiler) outputOpcode(op vm.OpCode) { + if c.debug { + fmt.Printf("%d: %v\n", len(c.out), op) + } + c.out = append(c.out, byte(op)) +} + +// output pushes the value v to the binary stack. +func (c *Compiler) outputBytes(b []byte) { if c.debug { - fmt.Printf("%d: %v\n", len(c.binary), v) + fmt.Printf("%d: %x\n", len(c.out), b) } - c.binary = append(c.binary, v) + c.out = append(c.out, b...) }   // isPush returns whether the string op is either any of @@ -263,13 +280,13 @@ lineno int }   func (err compileError) Error() string { - return fmt.Sprintf("%d syntax error: unexpected %v, expected %v", err.lineno, err.got, err.want) + return fmt.Sprintf("%d: syntax error: unexpected %v, expected %v", err.lineno, err.got, err.want) }   func compileErr(c token, got, want string) error { return compileError{ got: got, want: want, - lineno: c.lineno, + lineno: c.lineno + 1, } }
diff --git ethereum/go-ethereum/core/types/state_account.go taikoxyz/taiko-geth/core/types/state_account.go index 314f4943ecab386a288c7b33cae010f926840561..ad07ca3f3a3d110a588ce7455bbedf1e5aad029f 100644 --- ethereum/go-ethereum/core/types/state_account.go +++ taikoxyz/taiko-geth/core/types/state_account.go @@ -87,7 +87,7 @@ } return data }   -// FullAccount decodes the data on the 'slim RLP' format and return +// FullAccount decodes the data on the 'slim RLP' format and returns // the consensus format account. func FullAccount(data []byte) (*StateAccount, error) { var slim SlimAccount
diff --git ethereum/go-ethereum/core/rawdb/freezer_test.go taikoxyz/taiko-geth/core/rawdb/freezer_test.go index 96d24cc9473b6e110ff55d5b9d133c5ffdc82164..b4bd6a382a867e20470a2aad43bb44129b03e229 100644 --- ethereum/go-ethereum/core/rawdb/freezer_test.go +++ taikoxyz/taiko-geth/core/rawdb/freezer_test.go @@ -283,6 +283,57 @@ t.Fatal("readonly freezer should fail with differing table lengths") } }   +func TestFreezerConcurrentReadonly(t *testing.T) { + t.Parallel() + + tables := map[string]bool{"a": true} + dir := t.TempDir() + + f, err := NewFreezer(dir, "", false, 2049, tables) + if err != nil { + t.Fatal("can't open freezer", err) + } + var item = make([]byte, 1024) + batch := f.tables["a"].newBatch() + items := uint64(10) + for i := uint64(0); i < items; i++ { + require.NoError(t, batch.AppendRaw(i, item)) + } + require.NoError(t, batch.commit()) + if loaded := f.tables["a"].items.Load(); loaded != items { + t.Fatalf("unexpected number of items in table, want: %d, have: %d", items, loaded) + } + require.NoError(t, f.Close()) + + var ( + wg sync.WaitGroup + fs = make([]*Freezer, 5) + errs = make([]error, 5) + ) + for i := 0; i < 5; i++ { + wg.Add(1) + go func(i int) { + defer wg.Done() + + f, err := NewFreezer(dir, "", true, 2049, tables) + if err == nil { + fs[i] = f + } else { + errs[i] = err + } + }(i) + } + + wg.Wait() + + for i := range fs { + if err := errs[i]; err != nil { + t.Fatal("failed to open freezer", err) + } + require.NoError(t, fs[i].Close()) + } +} + func newFreezerForTesting(t *testing.T, tables map[string]bool) (*Freezer, string) { t.Helper()
diff --git ethereum/go-ethereum/core/types/transaction_marshalling.go taikoxyz/taiko-geth/core/types/transaction_marshalling.go index 1378cb40142258b233c461119fecd56a351616bb..e5d71a85d6b1c693ea7efe5235c554d8a4829f89 100644 --- ethereum/go-ethereum/core/types/transaction_marshalling.go +++ taikoxyz/taiko-geth/core/types/transaction_marshalling.go @@ -373,20 +373,20 @@ } itx.BlobHashes = dec.BlobVersionedHashes   // signature R - var ok bool + var overflow bool if dec.R == nil { return errors.New("missing required field 'r' in transaction") } - itx.R, ok = uint256.FromBig((*big.Int)(dec.R)) - if !ok { + itx.R, overflow = uint256.FromBig((*big.Int)(dec.R)) + if overflow { return errors.New("'r' value overflows uint256") } // signature S if dec.S == nil { return errors.New("missing required field 's' in transaction") } - itx.S, ok = uint256.FromBig((*big.Int)(dec.S)) - if !ok { + itx.S, overflow = uint256.FromBig((*big.Int)(dec.S)) + if overflow { return errors.New("'s' value overflows uint256") } // signature V @@ -394,8 +394,8 @@ vbig, err := dec.yParityValue() if err != nil { return err } - itx.V, ok = uint256.FromBig(vbig) - if !ok { + itx.V, overflow = uint256.FromBig(vbig) + if overflow { return errors.New("'v' value overflows uint256") } if itx.V.Sign() != 0 || itx.R.Sign() != 0 || itx.S.Sign() != 0 {
diff --git ethereum/go-ethereum/core/forkid/forkid_test.go taikoxyz/taiko-geth/core/forkid/forkid_test.go index 1dc65aec36b8bc1b61bb91617b1f17de43e125f3..db634bc14b90ded78efc9edbc4e46a5e0737ed53 100644 --- ethereum/go-ethereum/core/forkid/forkid_test.go +++ taikoxyz/taiko-geth/core/forkid/forkid_test.go @@ -18,10 +18,14 @@ package forkid   import ( "bytes" + "hash/crc32" "math" + "math/big" "testing"   "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/core" + "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/params" "github.com/ethereum/go-ethereum/rlp" ) @@ -36,13 +40,13 @@ want ID } tests := []struct { config *params.ChainConfig - genesis common.Hash + genesis *types.Block cases []testcase }{ // Mainnet test cases { params.MainnetChainConfig, - params.MainnetGenesisHash, + core.DefaultGenesisBlock().ToBlock(), []testcase{ {0, 0, ID{Hash: checksumToBytes(0xfc64ec04), Next: 1150000}}, // Unsynced {1149999, 0, ID{Hash: checksumToBytes(0xfc64ec04), Next: 1150000}}, // Last Frontier block @@ -77,7 +81,7 @@ }, // Goerli test cases { params.GoerliChainConfig, - params.GoerliGenesisHash, + core.DefaultGoerliGenesisBlock().ToBlock(), []testcase{ {0, 0, ID{Hash: checksumToBytes(0xa3f5ab08), Next: 1561651}}, // Unsynced, last Frontier, Homestead, Tangerine, Spurious, Byzantium, Constantinople and first Petersburg block {1561650, 0, ID{Hash: checksumToBytes(0xa3f5ab08), Next: 1561651}}, // Last Petersburg block @@ -94,13 +98,23 @@ }, // Sepolia test cases { params.SepoliaChainConfig, - params.SepoliaGenesisHash, + core.DefaultSepoliaGenesisBlock().ToBlock(), []testcase{ {0, 0, ID{Hash: checksumToBytes(0xfe3366e7), Next: 1735371}}, // Unsynced, last Frontier, Homestead, Tangerine, Spurious, Byzantium, Constantinople, Petersburg, Istanbul, Berlin and first London block {1735370, 0, ID{Hash: checksumToBytes(0xfe3366e7), Next: 1735371}}, // Last London block {1735371, 0, ID{Hash: checksumToBytes(0xb96cbd13), Next: 1677557088}}, // First MergeNetsplit block {1735372, 1677557087, ID{Hash: checksumToBytes(0xb96cbd13), Next: 1677557088}}, // Last MergeNetsplit block {1735372, 1677557088, ID{Hash: checksumToBytes(0xf7f9bc08), Next: 0}}, // First Shanghai block + }, + }, + // Holesky test cases + { + params.HoleskyChainConfig, + core.DefaultHoleskyGenesisBlock().ToBlock(), + []testcase{ + {0, 0, ID{Hash: checksumToBytes(0xc61a6098), Next: 1696000704}}, // Unsynced, last Frontier, Homestead, Tangerine, Spurious, Byzantium, Constantinople, Petersburg, Istanbul, Berlin, London, Paris block + {123, 0, ID{Hash: checksumToBytes(0xc61a6098), Next: 1696000704}}, // First MergeNetsplit block + {123, 1696000704, ID{Hash: checksumToBytes(0xfd4f016b), Next: 0}}, // Last MergeNetsplit block }, }, } @@ -353,7 +367,7 @@ // TODO(karalabe): Enable this when Cancun is specced //{params.MainnetChainConfig, 20999999, 1677999999, ID{Hash: checksumToBytes(0x71147644), Next: 1678000000}, ErrLocalIncompatibleOrStale}, } for i, tt := range tests { - filter := newFilter(tt.config, params.MainnetGenesisHash, func() (uint64, uint64) { return tt.head, tt.time }) + filter := newFilter(tt.config, core.DefaultGenesisBlock().ToBlock(), func() (uint64, uint64) { return tt.head, tt.time }) if err := filter(tt.id); err != tt.err { t.Errorf("test %d: validation error mismatch: have %v, want %v", i, err, tt.err) } @@ -382,3 +396,55 @@ t.Errorf("test %d: RLP mismatch: have %x, want %x", i, have, tt.want) } } } + +// Tests that time-based forks which are active at genesis are not included in +// forkid hash. +func TestTimeBasedForkInGenesis(t *testing.T) { + var ( + time = uint64(1690475657) + genesis = types.NewBlockWithHeader(&types.Header{Time: time}) + forkidHash = checksumToBytes(crc32.ChecksumIEEE(genesis.Hash().Bytes())) + config = func(shanghai, cancun uint64) *params.ChainConfig { + return &params.ChainConfig{ + ChainID: big.NewInt(1337), + HomesteadBlock: big.NewInt(0), + DAOForkBlock: nil, + DAOForkSupport: true, + EIP150Block: big.NewInt(0), + EIP155Block: big.NewInt(0), + EIP158Block: big.NewInt(0), + ByzantiumBlock: big.NewInt(0), + ConstantinopleBlock: big.NewInt(0), + PetersburgBlock: big.NewInt(0), + IstanbulBlock: big.NewInt(0), + MuirGlacierBlock: big.NewInt(0), + BerlinBlock: big.NewInt(0), + LondonBlock: big.NewInt(0), + TerminalTotalDifficulty: big.NewInt(0), + TerminalTotalDifficultyPassed: true, + MergeNetsplitBlock: big.NewInt(0), + ShanghaiTime: &shanghai, + CancunTime: &cancun, + Ethash: new(params.EthashConfig), + } + } + ) + tests := []struct { + config *params.ChainConfig + want ID + }{ + // Shanghai active before genesis, skip + {config(time-1, time+1), ID{Hash: forkidHash, Next: time + 1}}, + + // Shanghai active at genesis, skip + {config(time, time+1), ID{Hash: forkidHash, Next: time + 1}}, + + // Shanghai not active, skip + {config(time+1, time+2), ID{Hash: forkidHash, Next: time + 1}}, + } + for _, tt := range tests { + if have := NewID(tt.config, genesis, 0, time); have != tt.want { + t.Fatalf("incorrect forkid hash: have %x, want %x", have, tt.want) + } + } +}
diff --git ethereum/go-ethereum/core/state/sync.go taikoxyz/taiko-geth/core/state/sync.go index 61097c6462d4e22ab250e135ef9ce206c5a22089..d6775e889610900c68f8238350dbc97a0535c0e8 100644 --- ethereum/go-ethereum/core/state/sync.go +++ taikoxyz/taiko-geth/core/state/sync.go @@ -17,8 +17,6 @@ package state   import ( - "bytes" - "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/ethdb" @@ -45,7 +43,7 @@ return err } } var obj types.StateAccount - if err := rlp.Decode(bytes.NewReader(leaf), &obj); err != nil { + if err := rlp.DecodeBytes(leaf, &obj); err != nil { return err } syncer.AddSubTrie(obj.Root, path, parent, parentPath, onSlot)
diff --git ethereum/go-ethereum/core/rawdb/accessors_trie.go taikoxyz/taiko-geth/core/rawdb/accessors_trie.go index 12f1ecdf833ed52aa24a289a23fb1cf505dc3025..78f1a70b1c04bae371fbe75f6ec1826c618d1d0b 100644 --- ethereum/go-ethereum/core/rawdb/accessors_trie.go +++ taikoxyz/taiko-geth/core/rawdb/accessors_trie.go @@ -36,7 +36,7 @@ // with no data locality, and it's unfriendly for designing state pruning. // // Now this scheme is still kept for backward compatibility, and it will be used // for archive node and some other tries(e.g. light trie). -const HashScheme = "hashScheme" +const HashScheme = "hash"   // PathScheme is the new path-based state scheme with which trie nodes are stored // in the disk with node path as the database key. This scheme will only store one @@ -44,7 +44,7 @@ // version of state data in the disk, which means that the state pruning operation // is native. At the same time, this scheme will put adjacent trie nodes in the same // area of the disk with good data locality property. But this scheme needs to rely // on extra state diffs to survive deep reorg. -const PathScheme = "pathScheme" +const PathScheme = "path"   // hasher is used to compute the sha256 hash of the provided data. type hasher struct{ sha crypto.KeccakState } @@ -89,6 +89,16 @@ defer h.release() return h.hash(data) == hash }   +// ExistsAccountTrieNode checks the presence of the account trie node with the +// specified node path, regardless of the node hash. +func ExistsAccountTrieNode(db ethdb.KeyValueReader, path []byte) bool { + has, err := db.Has(accountTrieNodeKey(path)) + if err != nil { + return false + } + return has +} + // WriteAccountTrieNode writes the provided account trie node into database. func WriteAccountTrieNode(db ethdb.KeyValueWriter, path []byte, node []byte) { if err := db.Put(accountTrieNodeKey(path), node); err != nil { @@ -125,6 +135,16 @@ } h := newHasher() defer h.release() return h.hash(data) == hash +} + +// ExistsStorageTrieNode checks the presence of the storage trie node with the +// specified account hash and node path, regardless of the node hash. +func ExistsStorageTrieNode(db ethdb.KeyValueReader, accountHash common.Hash, path []byte) bool { + has, err := db.Has(storageTrieNodeKey(accountHash, path)) + if err != nil { + return false + } + return has }   // WriteStorageTrieNode writes the provided storage trie node into database. @@ -263,3 +283,60 @@ default: panic(fmt.Sprintf("Unknown scheme %v", scheme)) } } + +// ReadStateScheme reads the state scheme of persistent state, or none +// if the state is not present in database. +func ReadStateScheme(db ethdb.Reader) string { + // Check if state in path-based scheme is present + blob, _ := ReadAccountTrieNode(db, nil) + if len(blob) != 0 { + return PathScheme + } + // In a hash-based scheme, the genesis state is consistently stored + // on the disk. To assess the scheme of the persistent state, it + // suffices to inspect the scheme of the genesis state. + header := ReadHeader(db, ReadCanonicalHash(db, 0), 0) + if header == nil { + return "" // empty datadir + } + blob = ReadLegacyTrieNode(db, header.Root) + if len(blob) == 0 { + return "" // no state in disk + } + return HashScheme +} + +// ParseStateScheme checks if the specified state scheme is compatible with +// the stored state. +// +// - If the provided scheme is none, use the scheme consistent with persistent +// state, or fallback to hash-based scheme if state is empty. +// +// - If the provided scheme is hash, use hash-based scheme or error out if not +// compatible with persistent state scheme. +// +// - If the provided scheme is path: use path-based scheme or error out if not +// compatible with persistent state scheme. +func ParseStateScheme(provided string, disk ethdb.Database) (string, error) { + // If state scheme is not specified, use the scheme consistent + // with persistent state, or fallback to hash mode if database + // is empty. + stored := ReadStateScheme(disk) + if provided == "" { + if stored == "" { + // use default scheme for empty database, flip it when + // path mode is chosen as default + log.Info("State schema set to default", "scheme", "hash") + return HashScheme, nil + } + log.Info("State scheme set to already existing", "scheme", stored) + return stored, nil // reuse scheme of persistent scheme + } + // If state scheme is specified, ensure it's compatible with + // persistent state. + if stored == "" || provided == stored { + log.Info("State scheme set by user", "scheme", provided) + return provided, nil + } + return "", fmt.Errorf("incompatible state scheme, stored: %s, provided: %s", stored, provided) +}
diff --git ethereum/go-ethereum/core/rawdb/schema.go taikoxyz/taiko-geth/core/rawdb/schema.go index 940ce01549cd59df18c0deee765cc2e25edc57c2..8e82459e8225598b7a945a9bbeea75a88bd5c028 100644 --- ethereum/go-ethereum/core/rawdb/schema.go +++ taikoxyz/taiko-geth/core/rawdb/schema.go @@ -91,6 +91,9 @@ // transitionStatusKey tracks the eth2 transition status. transitionStatusKey = []byte("eth2-transition")   + // snapSyncStatusFlagKey flags that status of snap sync. + snapSyncStatusFlagKey = []byte("SnapSyncStatus") + // Data item prefixes (use single byte to avoid mixing data types, avoid `i`, used for indexes). headerPrefix = []byte("h") // headerPrefix + num (uint64 big endian) + hash -> header headerTDSuffix = []byte("t") // headerPrefix + num (uint64 big endian) + hash + headerTDSuffix -> td @@ -195,7 +198,11 @@ }   // storageSnapshotKey = SnapshotStoragePrefix + account hash + storage hash func storageSnapshotKey(accountHash, storageHash common.Hash) []byte { - return append(append(SnapshotStoragePrefix, accountHash.Bytes()...), storageHash.Bytes()...) + buf := make([]byte, len(SnapshotStoragePrefix)+common.HashLength+common.HashLength) + n := copy(buf, SnapshotStoragePrefix) + n += copy(buf[n:], accountHash.Bytes()) + copy(buf[n:], storageHash.Bytes()) + return buf }   // storageSnapshotsKey = SnapshotStoragePrefix + account hash + storage hash @@ -259,7 +266,11 @@ }   // storageTrieNodeKey = trieNodeStoragePrefix + accountHash + nodePath. func storageTrieNodeKey(accountHash common.Hash, path []byte) []byte { - return append(append(trieNodeStoragePrefix, accountHash.Bytes()...), path...) + buf := make([]byte, len(trieNodeStoragePrefix)+common.HashLength+len(path)) + n := copy(buf, trieNodeStoragePrefix) + n += copy(buf[n:], accountHash.Bytes()) + copy(buf[n:], path) + return buf }   // IsLegacyTrieNode reports whether a provided database entry is a legacy trie @@ -273,9 +284,10 @@ } return bytes.Equal(key, crypto.Keccak256(val)) }   -// IsAccountTrieNode reports whether a provided database entry is an account -// trie node in path-based state scheme. -func IsAccountTrieNode(key []byte) (bool, []byte) { +// ResolveAccountTrieNodeKey reports whether a provided database entry is an +// account trie node in path-based state scheme, and returns the resolved +// node path if so. +func ResolveAccountTrieNodeKey(key []byte) (bool, []byte) { if !bytes.HasPrefix(key, trieNodeAccountPrefix) { return false, nil } @@ -288,9 +300,17 @@ } return true, key[len(trieNodeAccountPrefix):] }   -// IsStorageTrieNode reports whether a provided database entry is a storage +// IsAccountTrieNode reports whether a provided database entry is an account // trie node in path-based state scheme. -func IsStorageTrieNode(key []byte) (bool, common.Hash, []byte) { +func IsAccountTrieNode(key []byte) bool { + ok, _ := ResolveAccountTrieNodeKey(key) + return ok +} + +// ResolveStorageTrieNode reports whether a provided database entry is a storage +// trie node in path-based state scheme, and returns the resolved account hash +// and node path if so. +func ResolveStorageTrieNode(key []byte) (bool, common.Hash, []byte) { if !bytes.HasPrefix(key, trieNodeStoragePrefix) { return false, common.Hash{}, nil } @@ -306,3 +326,10 @@ } accountHash := common.BytesToHash(key[len(trieNodeStoragePrefix) : len(trieNodeStoragePrefix)+common.HashLength]) return true, accountHash, key[len(trieNodeStoragePrefix)+common.HashLength:] } + +// IsStorageTrieNode reports whether a provided database entry is a storage +// trie node in path-based state scheme. +func IsStorageTrieNode(key []byte) bool { + ok, _, _ := ResolveStorageTrieNode(key) + return ok +}
diff --git ethereum/go-ethereum/core/types/tx_blob.go taikoxyz/taiko-geth/core/types/tx_blob.go index a08121bf1416a1b202e332c120c2a2bbd385987c..da4a9b72f17aaa1a438e0b89ce591550e76cb8d9 100644 --- ethereum/go-ethereum/core/types/tx_blob.go +++ taikoxyz/taiko-geth/core/types/tx_blob.go @@ -17,10 +17,14 @@ package types   import ( + "bytes" + "crypto/sha256" "math/big"   "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/crypto/kzg4844" "github.com/ethereum/go-ethereum/params" + "github.com/ethereum/go-ethereum/rlp" "github.com/holiman/uint256" )   @@ -38,12 +42,56 @@ AccessList AccessList BlobFeeCap *uint256.Int // a.k.a. maxFeePerBlobGas BlobHashes []common.Hash   + // A blob transaction can optionally contain blobs. This field must be set when BlobTx + // is used to create a transaction for sigining. + Sidecar *BlobTxSidecar `rlp:"-"` + // Signature values V *uint256.Int `json:"v" gencodec:"required"` R *uint256.Int `json:"r" gencodec:"required"` S *uint256.Int `json:"s" gencodec:"required"` }   +// BlobTxSidecar contains the blobs of a blob transaction. +type BlobTxSidecar struct { + Blobs []kzg4844.Blob // Blobs needed by the blob pool + Commitments []kzg4844.Commitment // Commitments needed by the blob pool + Proofs []kzg4844.Proof // Proofs needed by the blob pool +} + +// BlobHashes computes the blob hashes of the given blobs. +func (sc *BlobTxSidecar) BlobHashes() []common.Hash { + h := make([]common.Hash, len(sc.Commitments)) + for i := range sc.Blobs { + h[i] = blobHash(&sc.Commitments[i]) + } + return h +} + +// encodedSize computes the RLP size of the sidecar elements. This does NOT return the +// encoded size of the BlobTxSidecar, it's just a helper for tx.Size(). +func (sc *BlobTxSidecar) encodedSize() uint64 { + var blobs, commitments, proofs uint64 + for i := range sc.Blobs { + blobs += rlp.BytesSize(sc.Blobs[i][:]) + } + for i := range sc.Commitments { + commitments += rlp.BytesSize(sc.Commitments[i][:]) + } + for i := range sc.Proofs { + proofs += rlp.BytesSize(sc.Proofs[i][:]) + } + return rlp.ListSize(blobs) + rlp.ListSize(commitments) + rlp.ListSize(proofs) +} + +// blobTxWithBlobs is used for encoding of transactions when blobs are present. +type blobTxWithBlobs struct { + BlobTx *BlobTx + Blobs []kzg4844.Blob + Commitments []kzg4844.Commitment + Proofs []kzg4844.Proof +} + // copy creates a deep copy of the transaction data and initializes all fields. func (tx *BlobTx) copy() TxData { cpy := &BlobTx{ @@ -90,24 +138,29 @@ } if tx.S != nil { cpy.S.Set(tx.S) } + if tx.Sidecar != nil { + cpy.Sidecar = &BlobTxSidecar{ + Blobs: append([]kzg4844.Blob(nil), tx.Sidecar.Blobs...), + Commitments: append([]kzg4844.Commitment(nil), tx.Sidecar.Commitments...), + Proofs: append([]kzg4844.Proof(nil), tx.Sidecar.Proofs...), + } + } return cpy }   // accessors for innerTx. -func (tx *BlobTx) txType() byte { return BlobTxType } -func (tx *BlobTx) chainID() *big.Int { return tx.ChainID.ToBig() } -func (tx *BlobTx) accessList() AccessList { return tx.AccessList } -func (tx *BlobTx) data() []byte { return tx.Data } -func (tx *BlobTx) gas() uint64 { return tx.Gas } -func (tx *BlobTx) gasFeeCap() *big.Int { return tx.GasFeeCap.ToBig() } -func (tx *BlobTx) gasTipCap() *big.Int { return tx.GasTipCap.ToBig() } -func (tx *BlobTx) gasPrice() *big.Int { return tx.GasFeeCap.ToBig() } -func (tx *BlobTx) value() *big.Int { return tx.Value.ToBig() } -func (tx *BlobTx) nonce() uint64 { return tx.Nonce } -func (tx *BlobTx) to() *common.Address { tmp := tx.To; return &tmp } -func (tx *BlobTx) blobGas() uint64 { return params.BlobTxBlobGasPerBlob * uint64(len(tx.BlobHashes)) } -func (tx *BlobTx) blobGasFeeCap() *big.Int { return tx.BlobFeeCap.ToBig() } -func (tx *BlobTx) blobHashes() []common.Hash { return tx.BlobHashes } +func (tx *BlobTx) txType() byte { return BlobTxType } +func (tx *BlobTx) chainID() *big.Int { return tx.ChainID.ToBig() } +func (tx *BlobTx) accessList() AccessList { return tx.AccessList } +func (tx *BlobTx) data() []byte { return tx.Data } +func (tx *BlobTx) gas() uint64 { return tx.Gas } +func (tx *BlobTx) gasFeeCap() *big.Int { return tx.GasFeeCap.ToBig() } +func (tx *BlobTx) gasTipCap() *big.Int { return tx.GasTipCap.ToBig() } +func (tx *BlobTx) gasPrice() *big.Int { return tx.GasFeeCap.ToBig() } +func (tx *BlobTx) value() *big.Int { return tx.Value.ToBig() } +func (tx *BlobTx) nonce() uint64 { return tx.Nonce } +func (tx *BlobTx) to() *common.Address { tmp := tx.To; return &tmp } +func (tx *BlobTx) blobGas() uint64 { return params.BlobTxBlobGasPerBlob * uint64(len(tx.BlobHashes)) }   func (tx *BlobTx) effectiveGasPrice(dst *big.Int, baseFee *big.Int) *big.Int { if baseFee == nil { @@ -130,3 +183,64 @@ tx.V.SetFromBig(v) tx.R.SetFromBig(r) tx.S.SetFromBig(s) } + +func (tx *BlobTx) withoutSidecar() *BlobTx { + cpy := *tx + cpy.Sidecar = nil + return &cpy +} + +func (tx *BlobTx) encode(b *bytes.Buffer) error { + if tx.Sidecar == nil { + return rlp.Encode(b, tx) + } + inner := &blobTxWithBlobs{ + BlobTx: tx, + Blobs: tx.Sidecar.Blobs, + Commitments: tx.Sidecar.Commitments, + Proofs: tx.Sidecar.Proofs, + } + return rlp.Encode(b, inner) +} + +func (tx *BlobTx) decode(input []byte) error { + // Here we need to support two formats: the network protocol encoding of the tx (with + // blobs) or the canonical encoding without blobs. + // + // The two encodings can be distinguished by checking whether the first element of the + // input list is itself a list. + + outerList, _, err := rlp.SplitList(input) + if err != nil { + return err + } + firstElemKind, _, _, err := rlp.Split(outerList) + if err != nil { + return err + } + + if firstElemKind != rlp.List { + return rlp.DecodeBytes(input, tx) + } + // It's a tx with blobs. + var inner blobTxWithBlobs + if err := rlp.DecodeBytes(input, &inner); err != nil { + return err + } + *tx = *inner.BlobTx + tx.Sidecar = &BlobTxSidecar{ + Blobs: inner.Blobs, + Commitments: inner.Commitments, + Proofs: inner.Proofs, + } + return nil +} + +func blobHash(commit *kzg4844.Commitment) common.Hash { + hasher := sha256.New() + hasher.Write(commit[:]) + var vhash common.Hash + hasher.Sum(vhash[:0]) + vhash[0] = params.BlobTxHashVersion + return vhash +}
diff --git ethereum/go-ethereum/core/bloombits/matcher.go taikoxyz/taiko-geth/core/bloombits/matcher.go index d8f932041bc0d28ce2af5428068ca46912269f4f..6a4cfb23db19b1cbf364ded80f11ab3fb5c1f7dd 100644 --- ethereum/go-ethereum/core/bloombits/matcher.go +++ taikoxyz/taiko-geth/core/bloombits/matcher.go @@ -58,7 +58,7 @@ // Retrieval represents a request for retrieval task assignments for a given // bit with the given number of fetch elements, or a response for such a request. // It can also have the actual results set to be used as a delivery data struct. // -// The contest and error fields are used by the light client to terminate matching +// The context and error fields are used by the light client to terminate matching // early if an error is encountered on some path of the pipeline. type Retrieval struct { Bit uint @@ -389,7 +389,7 @@ allocs int // Number of active allocations to handle graceful shutdown requests shutdown = session.quit // Shutdown request channel, will gracefully wait for pending requests )   - // assign is a helper method fo try to assign a pending bit an actively + // assign is a helper method to try to assign a pending bit an actively // listening servicer, or schedule it up for later when one arrives. assign := func(bit uint) { select { @@ -630,13 +630,16 @@ // Retrieval accepted, something must arrive before we're aborting request <- &Retrieval{Bit: bit, Sections: sections, Context: s.ctx}   result := <-request + + // Deliver a result before s.Close() to avoid a deadlock + s.deliverSections(result.Bit, result.Sections, result.Bitsets) + if result.Error != nil { s.errLock.Lock() s.err = result.Error s.errLock.Unlock() s.Close() } - s.deliverSections(result.Bit, result.Sections, result.Bitsets) } } }
diff --git ethereum/go-ethereum/core/rawdb/accessors_chain_test.go taikoxyz/taiko-geth/core/rawdb/accessors_chain_test.go index beeec9f5a6157092ad684fdafcc469f4f7ce1cdd..a7ceb72998a115653130a19932f443dfda3f7cc4 100644 --- ethereum/go-ethereum/core/rawdb/accessors_chain_test.go +++ taikoxyz/taiko-geth/core/rawdb/accessors_chain_test.go @@ -435,12 +435,12 @@ func TestAncientStorage(t *testing.T) { // Freezer style fast import the chain. frdir := t.TempDir() - db, err := NewDatabaseWithFreezer(NewMemoryDatabase(), frdir, "", false) if err != nil { t.Fatalf("failed to create database with ancient backend") } defer db.Close() + // Create a test block block := types.NewBlockWithHeader(&types.Header{ Number: big.NewInt(0), @@ -736,7 +736,7 @@ // Insert the receipt slice into the database and check presence WriteReceipts(db, hash, 0, receipts)   - logs := ReadLogs(db, hash, 0, params.TestChainConfig) + logs := ReadLogs(db, hash, 0) if len(logs) == 0 { t.Fatalf("no logs returned") }
diff --git ethereum/go-ethereum/core/rawdb/database.go taikoxyz/taiko-geth/core/rawdb/database.go index 7bc91090619f89635f9e0cda90f7ae5c933ddc4b..1d7b7d1ca89cb77d00966e5baafc825f6a43ffc8 100644 --- ethereum/go-ethereum/core/rawdb/database.go +++ taikoxyz/taiko-geth/core/rawdb/database.go @@ -30,11 +30,12 @@ "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/ethdb" "github.com/ethereum/go-ethereum/ethdb/leveldb" "github.com/ethereum/go-ethereum/ethdb/memorydb" + "github.com/ethereum/go-ethereum/ethdb/pebble" "github.com/ethereum/go-ethereum/log" "github.com/olekukonko/tablewriter" )   -// freezerdb is a database wrapper that enabled freezer data retrievals. +// freezerdb is a database wrapper that enables freezer data retrievals. type freezerdb struct { ancientRoot string ethdb.KeyValueStore @@ -141,7 +142,7 @@ func (db *nofreezedb) ReadAncients(fn func(reader ethdb.AncientReaderOp) error) (err error) { // Unlike other ancient-related methods, this method does not return // errNotSupported when invoked. // The reason for this is that the caller might want to do several things: - // 1. Check if something is in freezer, + // 1. Check if something is in the freezer, // 2. If not, check leveldb. // // This will work, since the ancient-checks inside 'fn' will return errors, @@ -209,7 +210,7 @@ // there's a fairly high probability that the user requests invalid combinations // of the freezer and database. Ensure that we don't shoot ourselves in the foot // by serving up conflicting data, leading to both datastores getting corrupted. // - // - If both the freezer and key-value store is empty (no genesis), we just + // - If both the freezer and key-value store are empty (no genesis), we just // initialized a new empty freezer, so everything's fine. // - If the key-value store is empty, but the freezer is not, we need to make // sure the user's genesis matches the freezer. That will be checked in the @@ -218,7 +219,7 @@ // this point care, the key-value/freezer combo is valid). // - If neither the key-value store nor the freezer is empty, cross validate // the genesis hashes to make sure they are compatible. If they are, also // ensure that there's no gap between the freezer and subsequently leveldb. - // - If the key-value store is not empty, but the freezer is we might just be + // - If the key-value store is not empty, but the freezer is, we might just be // upgrading to the freezer release, or we might have had a small chain and // not frozen anything yet. Ensure that no blocks are missing yet from the // key-value store, since that would mean we already had an old freezer. @@ -253,7 +254,7 @@ if present, _ := db.Has(headerHashKey(number)); present { break } } - // We are about to exit on error. Print database metdata beore exiting + // We are about to exit on error. Print database metadata before exiting printChainMetadata(db) return nil, fmt.Errorf("gap in the chain between ancients [0 - #%d] and leveldb [#%d - #%d] ", frozen-1, number, head) @@ -321,15 +322,25 @@ log.Info("Using LevelDB as the backing database") return NewDatabase(db), nil }   +// NewPebbleDBDatabase creates a persistent key-value database without a freezer +// moving immutable chain segments into cold storage. +func NewPebbleDBDatabase(file string, cache int, handles int, namespace string, readonly, ephemeral bool) (ethdb.Database, error) { + db, err := pebble.New(file, cache, handles, namespace, readonly, ephemeral) + if err != nil { + return nil, err + } + return NewDatabase(db), nil +} + const ( dbPebble = "pebble" dbLeveldb = "leveldb" )   -// hasPreexistingDb checks the given data directory whether a database is already +// PreexistingDatabase checks the given data directory whether a database is already // instantiated at that location, and if so, returns the type of database (or the // empty string). -func hasPreexistingDb(path string) string { +func PreexistingDatabase(path string) string { if _, err := os.Stat(filepath.Join(path, "CURRENT")); err != nil { return "" // No pre-existing db } @@ -352,6 +363,9 @@ Namespace string // the namespace for database relevant metrics Cache int // the capacity(in megabytes) of the data caching Handles int // number of files to be open simultaneously ReadOnly bool + // Ephemeral means that filesystem sync operations should be avoided: data integrity in the face of + // a crash is not important. This option should typically be used in tests. + Ephemeral bool }   // openKeyValueDatabase opens a disk-based key-value database, e.g. leveldb or pebble. @@ -367,31 +381,21 @@ return nil, fmt.Errorf("unknown db.engine %v", o.Type) } // Retrieve any pre-existing database's type and use that or the requested one // as long as there's no conflict between the two types - existingDb := hasPreexistingDb(o.Directory) + existingDb := PreexistingDatabase(o.Directory) if len(existingDb) != 0 && len(o.Type) != 0 && o.Type != existingDb { return nil, fmt.Errorf("db.engine choice was %v but found pre-existing %v database in specified data directory", o.Type, existingDb) } if o.Type == dbPebble || existingDb == dbPebble { - if PebbleEnabled { - log.Info("Using pebble as the backing database") - return NewPebbleDBDatabase(o.Directory, o.Cache, o.Handles, o.Namespace, o.ReadOnly) - } else { - return nil, errors.New("db.engine 'pebble' not supported on this platform") - } + log.Info("Using pebble as the backing database") + return NewPebbleDBDatabase(o.Directory, o.Cache, o.Handles, o.Namespace, o.ReadOnly, o.Ephemeral) } if o.Type == dbLeveldb || existingDb == dbLeveldb { log.Info("Using leveldb as the backing database") return NewLevelDBDatabase(o.Directory, o.Cache, o.Handles, o.Namespace, o.ReadOnly) } - // No pre-existing database, no user-requested one either. Default to Pebble - // on supported platforms and LevelDB on anything else. - if PebbleEnabled { - log.Info("Defaulting to pebble as the backing database") - return NewPebbleDBDatabase(o.Directory, o.Cache, o.Handles, o.Namespace, o.ReadOnly) - } else { - log.Info("Defaulting to leveldb as the backing database") - return NewLevelDBDatabase(o.Directory, o.Cache, o.Handles, o.Namespace, o.ReadOnly) - } + // No pre-existing database, no user-requested one either. Default to Pebble. + log.Info("Defaulting to pebble as the backing database") + return NewPebbleDBDatabase(o.Directory, o.Cache, o.Handles, o.Namespace, o.ReadOnly, o.Ephemeral) }   // Open opens both a disk-based key-value database such as leveldb or pebble, but also @@ -463,7 +467,10 @@ receipts stat tds stat numHashPairings stat hashNumPairings stat - tries stat + legacyTries stat + stateLookups stat + accountTries stat + storageTries stat codes stat txLookups stat accountSnaps stat @@ -504,8 +511,14 @@ case bytes.HasPrefix(key, headerPrefix) && bytes.HasSuffix(key, headerHashSuffix): numHashPairings.Add(size) case bytes.HasPrefix(key, headerNumberPrefix) && len(key) == (len(headerNumberPrefix)+common.HashLength): hashNumPairings.Add(size) - case len(key) == common.HashLength: - tries.Add(size) + case IsLegacyTrieNode(key, it.Value()): + legacyTries.Add(size) + case bytes.HasPrefix(key, stateIDPrefix) && len(key) == len(stateIDPrefix)+common.HashLength: + stateLookups.Add(size) + case IsAccountTrieNode(key): + accountTries.Add(size) + case IsStorageTrieNode(key): + storageTries.Add(size) case bytes.HasPrefix(key, CodePrefix) && len(key) == len(CodePrefix)+common.HashLength: codes.Add(size) case bytes.HasPrefix(key, txLookupPrefix) && len(key) == (len(txLookupPrefix)+common.HashLength): @@ -543,6 +556,7 @@ databaseVersionKey, headHeaderKey, headBlockKey, headFastBlockKey, headFinalizedBlockKey, lastPivotKey, fastTrieProgressKey, snapshotDisabledKey, SnapshotRootKey, snapshotJournalKey, snapshotGeneratorKey, snapshotRecoveryKey, txIndexTailKey, fastTxLookupLimitKey, uncleanShutdownKey, badBlockKey, transitionStatusKey, skeletonSyncStatusKey, + persistentStateIDKey, trieJournalKey, snapshotSyncStatusKey, snapSyncStatusFlagKey, } { if bytes.Equal(key, meta) { metadata.Add(size) @@ -571,7 +585,10 @@ {"Key-Value store", "Block hash->number", hashNumPairings.Size(), hashNumPairings.Count()}, {"Key-Value store", "Transaction index", txLookups.Size(), txLookups.Count()}, {"Key-Value store", "Bloombit index", bloomBits.Size(), bloomBits.Count()}, {"Key-Value store", "Contract codes", codes.Size(), codes.Count()}, - {"Key-Value store", "Trie nodes", tries.Size(), tries.Count()}, + {"Key-Value store", "Hash trie nodes", legacyTries.Size(), legacyTries.Count()}, + {"Key-Value store", "Path trie state lookups", stateLookups.Size(), stateLookups.Count()}, + {"Key-Value store", "Path trie account nodes", accountTries.Size(), accountTries.Count()}, + {"Key-Value store", "Path trie storage nodes", storageTries.Size(), storageTries.Count()}, {"Key-Value store", "Trie preimages", preimages.Size(), preimages.Count()}, {"Key-Value store", "Account snapshot", accountSnaps.Size(), accountSnaps.Count()}, {"Key-Value store", "Storage snapshot", storageSnaps.Size(), storageSnaps.Count()}, @@ -618,7 +635,7 @@ } fmt.Fprintf(os.Stderr, "\n\n") }   -// ReadChainMetadata returns a set of key/value pairs that contains informatin +// ReadChainMetadata returns a set of key/value pairs that contains information // about the database chain status. This can be used for diagnostic purposes // when investigating the state of the node. func ReadChainMetadata(db ethdb.KeyValueStore) [][]string {
diff --git ethereum/go-ethereum/core/types/log.go taikoxyz/taiko-geth/core/types/log.go index e48919136889dfe6b1e59ca11f96c2cf7404e84d..54c7ff6372c8cea11d20c2515d10c45ef12aa963 100644 --- ethereum/go-ethereum/core/types/log.go +++ taikoxyz/taiko-geth/core/types/log.go @@ -17,13 +17,11 @@ package types   import ( - "io" - "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common/hexutil" - "github.com/ethereum/go-ethereum/rlp" )   +//go:generate go run ../../rlp/rlpgen -type Log -out gen_log_rlp.go //go:generate go run github.com/fjl/gencodec -type Log -field-override logMarshaling -out gen_log_json.go   // Log represents a contract log event. These events are generated by the LOG opcode and @@ -40,19 +38,19 @@ // Derived fields. These fields are filled in by the node // but not secured by consensus. // block in which the transaction was included - BlockNumber uint64 `json:"blockNumber"` + BlockNumber uint64 `json:"blockNumber" rlp:"-"` // hash of the transaction - TxHash common.Hash `json:"transactionHash" gencodec:"required"` + TxHash common.Hash `json:"transactionHash" gencodec:"required" rlp:"-"` // index of the transaction in the block - TxIndex uint `json:"transactionIndex"` + TxIndex uint `json:"transactionIndex" rlp:"-"` // hash of the block in which the transaction was included - BlockHash common.Hash `json:"blockHash"` + BlockHash common.Hash `json:"blockHash" rlp:"-"` // index of the log in the block - Index uint `json:"logIndex"` + Index uint `json:"logIndex" rlp:"-"`   // The Removed field is true if this log was reverted due to a chain reorganisation. // You must pay attention to this field if you receive logs through a filter query. - Removed bool `json:"removed"` + Removed bool `json:"removed" rlp:"-"` }   type logMarshaling struct { @@ -61,28 +59,3 @@ BlockNumber hexutil.Uint64 TxIndex hexutil.Uint Index hexutil.Uint } - -//go:generate go run ../../rlp/rlpgen -type rlpLog -out gen_log_rlp.go - -// rlpLog is used to RLP-encode both the consensus and storage formats. -type rlpLog struct { - Address common.Address - Topics []common.Hash - Data []byte -} - -// EncodeRLP implements rlp.Encoder. -func (l *Log) EncodeRLP(w io.Writer) error { - rl := rlpLog{Address: l.Address, Topics: l.Topics, Data: l.Data} - return rlp.Encode(w, &rl) -} - -// DecodeRLP implements rlp.Decoder. -func (l *Log) DecodeRLP(s *rlp.Stream) error { - var dec rlpLog - err := s.Decode(&dec) - if err == nil { - l.Address, l.Topics, l.Data = dec.Address, dec.Topics, dec.Data - } - return err -}
diff --git ethereum/go-ethereum/core/state/database.go taikoxyz/taiko-geth/core/state/database.go index a3b6322ae31335e4804d97112633695e28034ebe..9467c8f72ee30397cab068ce897f16139ed12886 100644 --- ethereum/go-ethereum/core/state/database.go +++ taikoxyz/taiko-geth/core/state/database.go @@ -58,7 +58,7 @@ // DiskDB returns the underlying key-value disk database. DiskDB() ethdb.KeyValueStore   - // TrieDB retrieves the low level trie database used for data storage. + // TrieDB returns the underlying trie database for managing trie nodes. TrieDB() *trie.Database }   @@ -147,7 +147,7 @@ return &cachingDB{ disk: db, codeSizeCache: lru.NewCache[common.Hash, int](codeSizeCacheSize), codeCache: lru.NewSizeConstrainedCache[common.Hash, []byte](codeCacheSize), - triedb: trie.NewDatabaseWithConfig(db, config), + triedb: trie.NewDatabase(db, config), } }
diff --git ethereum/go-ethereum/core/txpool/subpool.go taikoxyz/taiko-geth/core/txpool/subpool.go index 70c0918e140c2d16d0e449db0cf0736d845fdfb0..de05b38d433d6b507991e892d723bb08eb01d4a2 100644 --- ethereum/go-ethereum/core/txpool/subpool.go +++ taikoxyz/taiko-geth/core/txpool/subpool.go @@ -23,40 +23,40 @@ "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/core" "github.com/ethereum/go-ethereum/core/types" - "github.com/ethereum/go-ethereum/crypto/kzg4844" "github.com/ethereum/go-ethereum/event" )   -// Transaction is a helper struct to group together a canonical transaction with -// satellite data items that are needed by the pool but are not part of the chain. -type Transaction struct { - Tx *types.Transaction // Canonical transaction - - BlobTxBlobs []kzg4844.Blob // Blobs needed by the blob pool - BlobTxCommits []kzg4844.Commitment // Commitments needed by the blob pool - BlobTxProofs []kzg4844.Proof // Proofs needed by the blob pool -} - // LazyTransaction contains a small subset of the transaction properties that is // enough for the miner and other APIs to handle large batches of transactions; // and supports pulling up the entire transaction when really needed. type LazyTransaction struct { - Pool SubPool // Transaction subpool to pull the real transaction up - Hash common.Hash // Transaction hash to pull up if needed - Tx *Transaction // Transaction if already resolved + Pool LazyResolver // Transaction resolver to pull the real transaction up + Hash common.Hash // Transaction hash to pull up if needed + Tx *types.Transaction // Transaction if already resolved   Time time.Time // Time when the transaction was first seen GasFeeCap *big.Int // Maximum fee per gas the transaction may consume GasTipCap *big.Int // Maximum miner tip per gas the transaction can pay + + Gas uint64 // Amount of gas required by the transaction + BlobGas uint64 // Amount of blob gas required by the transaction }   // Resolve retrieves the full transaction belonging to a lazy handle if it is still // maintained by the transaction pool. -func (ltx *LazyTransaction) Resolve() *Transaction { +func (ltx *LazyTransaction) Resolve() *types.Transaction { if ltx.Tx == nil { ltx.Tx = ltx.Pool.Get(ltx.Hash) } return ltx.Tx +} + +// LazyResolver is a minimal interface needed for a transaction pool to satisfy +// resolving lazy transactions. It's mostly a helper to avoid the entire sub- +// pool being injected into the lazy transaction. +type LazyResolver interface { + // Get returns a transaction if it is contained in the pool, or nil otherwise. + Get(hash common.Hash) *types.Transaction }   // AddressReserver is passed by the main transaction pool to subpools, so they @@ -99,19 +99,21 @@ // given hash. Has(hash common.Hash) bool   // Get returns a transaction if it is contained in the pool, or nil otherwise. - Get(hash common.Hash) *Transaction + Get(hash common.Hash) *types.Transaction   // Add enqueues a batch of transactions into the pool if they are valid. Due // to the large transaction churn, add may postpone fully integrating the tx // to a later point to batch multiple ones together. - Add(txs []*Transaction, local bool, sync bool) []error + Add(txs []*types.Transaction, local bool, sync bool) []error   // Pending retrieves all currently processable transactions, grouped by origin // account and sorted by nonce. Pending(enforceTips bool) map[common.Address][]*LazyTransaction   - // SubscribeTransactions subscribes to new transaction events. - SubscribeTransactions(ch chan<- core.NewTxsEvent) event.Subscription + // SubscribeTransactions subscribes to new transaction events. The subscriber + // can decide whether to receive notifications only for newly seen transactions + // or also for reorged out ones. + SubscribeTransactions(ch chan<- core.NewTxsEvent, reorgs bool) event.Subscription   // Nonce returns the next nonce of an account, with all transactions executable // by the pool already applied on top.
diff --git ethereum/go-ethereum/core/types/transaction_signing.go taikoxyz/taiko-geth/core/types/transaction_signing.go index 8633440824157b691114d410daa322b1a2819e52..9e26642f753db4f0b370aef0ce84f327defbf7b7 100644 --- ethereum/go-ethereum/core/types/transaction_signing.go +++ taikoxyz/taiko-geth/core/types/transaction_signing.go @@ -57,7 +57,7 @@ return signer }   // LatestSigner returns the 'most permissive' Signer available for the given chain -// configuration. Specifically, this enables support of all types of transacrions +// configuration. Specifically, this enables support of all types of transactions // when their respective forks are scheduled to occur at any block number (or time) // in the chain config. // @@ -331,11 +331,7 @@ func (s eip2930Signer) Sender(tx *Transaction) (common.Address, error) { V, R, S := tx.RawSignatureValues() switch tx.Type() { case LegacyTxType: - if !tx.Protected() { - return HomesteadSigner{}.Sender(tx) - } - V = new(big.Int).Sub(V, s.chainIdMul) - V.Sub(V, big8) + return s.EIP155Signer.Sender(tx) case AccessListTxType: // AL txs are defined to use 0 and 1 as their recovery // id, add 27 to become equivalent to unprotected Homestead signatures. @@ -372,15 +368,7 @@ // It does not uniquely identify the transaction. func (s eip2930Signer) Hash(tx *Transaction) common.Hash { switch tx.Type() { case LegacyTxType: - return rlpHash([]interface{}{ - tx.Nonce(), - tx.GasPrice(), - tx.Gas(), - tx.To(), - tx.Value(), - tx.Data(), - s.chainId, uint(0), uint(0), - }) + return s.EIP155Signer.Hash(tx) case AccessListTxType: return prefixedRlpHash( tx.Type(),
diff --git ethereum/go-ethereum/core/vm/contract.go taikoxyz/taiko-geth/core/vm/contract.go index bb0902969ec78d4a8392276da5f5cfa37fb3b330..e4b03bd74fecfcd86db78ef794529f8a557c64b4 100644 --- ethereum/go-ethereum/core/vm/contract.go +++ taikoxyz/taiko-geth/core/vm/contract.go @@ -31,13 +31,13 @@ // AccountRef implements ContractRef. // // Account references are used during EVM initialisation and -// it's primary use is to fetch addresses. Removing this object +// its primary use is to fetch addresses. Removing this object // proves difficult because of the cached jump destinations which // are fetched from the parent contract (i.e. the caller), which // is a ContractRef. type AccountRef common.Address   -// Address casts AccountRef to a Address +// Address casts AccountRef to an Address func (ar AccountRef) Address() common.Address { return (common.Address)(ar) }   // Contract represents an ethereum contract in the state database. It contains
diff --git ethereum/go-ethereum/core/vm/opcodes.go taikoxyz/taiko-geth/core/vm/opcodes.go index 2929b8ce920ccf0a7df8d01b2829477332e616c7..a11cf05a1578935a7a97f411fcc8d678a017364f 100644 --- ethereum/go-ethereum/core/vm/opcodes.go +++ taikoxyz/taiko-geth/core/vm/opcodes.go @@ -101,6 +101,7 @@ CHAINID OpCode = 0x46 SELFBALANCE OpCode = 0x47 BASEFEE OpCode = 0x48 BLOBHASH OpCode = 0x49 + BLOBBASEFEE OpCode = 0x4a )   // 0x50 range - 'storage' and execution. @@ -287,6 +288,7 @@ CHAINID: "CHAINID", SELFBALANCE: "SELFBALANCE", BASEFEE: "BASEFEE", BLOBHASH: "BLOBHASH", + BLOBBASEFEE: "BLOBBASEFEE",   // 0x50 range - 'storage' and execution. POP: "POP", @@ -444,6 +446,7 @@ "CALLDATACOPY": CALLDATACOPY, "CHAINID": CHAINID, "BASEFEE": BASEFEE, "BLOBHASH": BLOBHASH, + "BLOBBASEFEE": BLOBBASEFEE, "DELEGATECALL": DELEGATECALL, "STATICCALL": STATICCALL, "CODESIZE": CODESIZE,
diff --git ethereum/go-ethereum/core/asm/asm.go taikoxyz/taiko-geth/core/asm/asm.go index 7c1e14ec01eadac24d539834545fecd206a748ac..294eb6ffaad7cad2873e36fb715d90a2ab5967fb 100644 --- ethereum/go-ethereum/core/asm/asm.go +++ taikoxyz/taiko-geth/core/asm/asm.go @@ -34,7 +34,7 @@ error error started bool }   -// NewInstructionIterator create a new instruction iterator. +// NewInstructionIterator creates a new instruction iterator. func NewInstructionIterator(code []byte) *instructionIterator { it := new(instructionIterator) it.code = code
diff --git ethereum/go-ethereum/core/forkid/forkid.go taikoxyz/taiko-geth/core/forkid/forkid.go index 8964558845d31a143fa27c6367992bac7d82e01e..76825d3befc16f8fab6f38560df5c376f1509017 100644 --- ethereum/go-ethereum/core/forkid/forkid.go +++ taikoxyz/taiko-geth/core/forkid/forkid.go @@ -26,7 +26,6 @@ "math/big" "reflect" "strings"   - "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/log" "github.com/ethereum/go-ethereum/params" @@ -73,12 +72,12 @@ // Filter is a fork id filter to validate a remotely advertised ID. type Filter func(id ID) error   // NewID calculates the Ethereum fork ID from the chain config, genesis hash, head and time. -func NewID(config *params.ChainConfig, genesis common.Hash, head, time uint64) ID { +func NewID(config *params.ChainConfig, genesis *types.Block, head, time uint64) ID { // Calculate the starting checksum from the genesis hash - hash := crc32.ChecksumIEEE(genesis[:]) + hash := crc32.ChecksumIEEE(genesis.Hash().Bytes())   // Calculate the current fork checksum and the next fork block - forksByBlock, forksByTime := gatherForks(config) + forksByBlock, forksByTime := gatherForks(config, genesis.Time()) for _, fork := range forksByBlock { if fork <= head { // Fork already passed, checksum the previous hash and the fork number @@ -104,7 +103,7 @@ head := chain.CurrentHeader()   return NewID( chain.Config(), - chain.Genesis().Hash(), + chain.Genesis(), head.Number.Uint64(), head.Time, ) @@ -115,7 +114,7 @@ // based on the local chain's status. func NewFilter(chain Blockchain) Filter { return newFilter( chain.Config(), - chain.Genesis().Hash(), + chain.Genesis(), func() (uint64, uint64) { head := chain.CurrentHeader() return head.Number.Uint64(), head.Time @@ -124,7 +123,7 @@ ) }   // NewStaticFilter creates a filter at block zero. -func NewStaticFilter(config *params.ChainConfig, genesis common.Hash) Filter { +func NewStaticFilter(config *params.ChainConfig, genesis *types.Block) Filter { head := func() (uint64, uint64) { return 0, 0 } return newFilter(config, genesis, head) } @@ -132,14 +131,14 @@ // newFilter is the internal version of NewFilter, taking closures as its arguments // instead of a chain. The reason is to allow testing it without having to simulate // an entire blockchain. -func newFilter(config *params.ChainConfig, genesis common.Hash, headfn func() (uint64, uint64)) Filter { +func newFilter(config *params.ChainConfig, genesis *types.Block, headfn func() (uint64, uint64)) Filter { // Calculate the all the valid fork hash and fork next combos var ( - forksByBlock, forksByTime = gatherForks(config) + forksByBlock, forksByTime = gatherForks(config, genesis.Time()) forks = append(append([]uint64{}, forksByBlock...), forksByTime...) sums = make([][4]byte, len(forks)+1) // 0th is the genesis ) - hash := crc32.ChecksumIEEE(genesis[:]) + hash := crc32.ChecksumIEEE(genesis.Hash().Bytes()) sums[0] = checksumToBytes(hash) for i, fork := range forks { hash = checksumUpdate(hash, fork) @@ -240,7 +239,7 @@ }   // gatherForks gathers all the known forks and creates two sorted lists out of // them, one for the block number based forks and the second for the timestamps. -func gatherForks(config *params.ChainConfig) ([]uint64, []uint64) { +func gatherForks(config *params.ChainConfig, genesis uint64) ([]uint64, []uint64) { // Gather all the fork block numbers via reflection kind := reflect.TypeOf(params.ChainConfig{}) conf := reflect.ValueOf(config).Elem() @@ -290,7 +289,8 @@ // Skip any forks in block 0, that's the genesis ruleset if len(forksByBlock) > 0 && forksByBlock[0] == 0 { forksByBlock = forksByBlock[1:] } - if len(forksByTime) > 0 && forksByTime[0] == 0 { + // Skip any forks before genesis. + for len(forksByTime) > 0 && forksByTime[0] <= genesis { forksByTime = forksByTime[1:] } return forksByBlock, forksByTime
diff --git ethereum/go-ethereum/core/state/iterator_test.go taikoxyz/taiko-geth/core/state/iterator_test.go index c8e1a181eb6f30c4b8a33ff537eb8cd1c2d3cafa..73cc22490b6ea7e976dbcb885a896f1692efbc59 100644 --- ethereum/go-ethereum/core/state/iterator_test.go +++ taikoxyz/taiko-geth/core/state/iterator_test.go @@ -26,9 +26,14 @@ )   // Tests that the node iterator indeed walks over the entire database contents. func TestNodeIteratorCoverage(t *testing.T) { + testNodeIteratorCoverage(t, rawdb.HashScheme) + testNodeIteratorCoverage(t, rawdb.PathScheme) +} + +func testNodeIteratorCoverage(t *testing.T, scheme string) { // Create some arbitrary test state to iterate - db, sdb, root, _ := makeTestState() - sdb.TrieDB().Commit(root, false) + db, sdb, ndb, root, _ := makeTestState(scheme) + ndb.Commit(root, false)   state, err := New(root, sdb, nil) if err != nil { @@ -48,7 +53,7 @@ seenCodes = make(map[common.Hash]struct{}) ) it := db.NewIterator(nil, nil) for it.Next() { - ok, hash := isTrieNode(sdb.TrieDB().Scheme(), it.Key(), it.Value()) + ok, hash := isTrieNode(scheme, it.Key(), it.Value()) if !ok { continue } @@ -90,11 +95,11 @@ if rawdb.IsLegacyTrieNode(key, val) { return true, common.BytesToHash(key) } } else { - ok, _ := rawdb.IsAccountTrieNode(key) + ok := rawdb.IsAccountTrieNode(key) if ok { return true, crypto.Keccak256Hash(val) } - ok, _, _ = rawdb.IsStorageTrieNode(key) + ok = rawdb.IsStorageTrieNode(key) if ok { return true, crypto.Keccak256Hash(val) }
diff --git ethereum/go-ethereum/core/vm/jump_table.go taikoxyz/taiko-geth/core/vm/jump_table.go index 702b18661545b3adb2c5da7720bd823eb3326f9b..fb87258326bd3699cca7a88a032285e8abd7686e 100644 --- ethereum/go-ethereum/core/vm/jump_table.go +++ taikoxyz/taiko-geth/core/vm/jump_table.go @@ -82,7 +82,8 @@ }   func newCancunInstructionSet() JumpTable { instructionSet := newShanghaiInstructionSet() - enable4844(&instructionSet) // EIP-4844 (DATAHASH opcode) + enable4844(&instructionSet) // EIP-4844 (BLOBHASH opcode) + enable7516(&instructionSet) // EIP-7516 (BLOBBASEFEE opcode) enable1153(&instructionSet) // EIP-1153 "Transient Storage" enable5656(&instructionSet) // EIP-5656 (MCOPY opcode) enable6780(&instructionSet) // EIP-6780 SELFDESTRUCT only in same transaction
diff --git ethereum/go-ethereum/core/vm/jump_table_export.go taikoxyz/taiko-geth/core/vm/jump_table_export.go index 6ea47d63a281eacba893e15c869dc48ffc1281dd..b74109da0ad14b02ec33e3dfa3e969ecb25ad850 100644 --- ethereum/go-ethereum/core/vm/jump_table_export.go +++ taikoxyz/taiko-geth/core/vm/jump_table_export.go @@ -22,7 +22,7 @@ "github.com/ethereum/go-ethereum/params" )   -// LookupInstructionSet returns the instructionset for the fork configured by +// LookupInstructionSet returns the instruction set for the fork configured by // the rules. func LookupInstructionSet(rules params.Rules) (JumpTable, error) { switch { @@ -56,7 +56,7 @@ } return newFrontierInstructionSet(), nil }   -// Stack returns the mininum and maximum stack requirements. +// Stack returns the minimum and maximum stack requirements. func (op *operation) Stack() (int, int) { return op.minStack, op.maxStack }
diff --git ethereum/go-ethereum/core/types/taiko_transaction.go taikoxyz/taiko-geth/core/types/taiko_transaction.go new file mode 100644 index 0000000000000000000000000000000000000000..d9cd9fb4a42d96124b3a338a18cf7280db17e420 --- /dev/null +++ taikoxyz/taiko-geth/core/types/taiko_transaction.go @@ -0,0 +1,42 @@ +package types + +func (tx *Transaction) MarkAsAnchor() error { + return tx.inner.markAsAnchor() +} + +func (tx *Transaction) IsAnchor() bool { + return tx.inner.isAnchor() +} + +func (tx *DynamicFeeTx) isAnchor() bool { + return tx.isAnhcor +} + +func (tx *LegacyTx) isAnchor() bool { + return false +} + +func (tx *AccessListTx) isAnchor() bool { + return false +} + +func (tx *BlobTx) isAnchor() bool { + return false +} + +func (tx *DynamicFeeTx) markAsAnchor() error { + tx.isAnhcor = true + return nil +} + +func (tx *LegacyTx) markAsAnchor() error { + return ErrInvalidTxType +} + +func (tx *AccessListTx) markAsAnchor() error { + return ErrInvalidTxType +} + +func (tx *BlobTx) markAsAnchor() error { + return ErrInvalidTxType +}
diff --git ethereum/go-ethereum/core/types/tx_dynamic_fee.go taikoxyz/taiko-geth/core/types/tx_dynamic_fee.go index 47b870abbf5c028fef7984dc00b320a1b5848ec8..96a3f105d58c060121e99d12d1b6b63e3dbf5c93 100644 --- ethereum/go-ethereum/core/types/tx_dynamic_fee.go +++ taikoxyz/taiko-geth/core/types/tx_dynamic_fee.go @@ -17,9 +17,11 @@ package types   import ( + "bytes" "math/big"   "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/rlp" )   // DynamicFeeTx represents an EIP-1559 transaction. @@ -38,6 +40,9 @@ // Signature values V *big.Int `json:"v" gencodec:"required"` R *big.Int `json:"r" gencodec:"required"` S *big.Int `json:"s" gencodec:"required"` + + // CHANGE(taiko): if this transaction is the first TaikoL2.anchor transaction in a block + isAnhcor bool }   // copy creates a deep copy of the transaction data and initializes all fields. @@ -56,6 +61,7 @@ GasFeeCap: new(big.Int), V: new(big.Int), R: new(big.Int), S: new(big.Int), + isAnhcor: tx.isAnhcor, } copy(cpy.AccessList, tx.AccessList) if tx.Value != nil { @@ -83,20 +89,17 @@ return cpy }   // accessors for innerTx. -func (tx *DynamicFeeTx) txType() byte { return DynamicFeeTxType } -func (tx *DynamicFeeTx) chainID() *big.Int { return tx.ChainID } -func (tx *DynamicFeeTx) accessList() AccessList { return tx.AccessList } -func (tx *DynamicFeeTx) data() []byte { return tx.Data } -func (tx *DynamicFeeTx) gas() uint64 { return tx.Gas } -func (tx *DynamicFeeTx) gasFeeCap() *big.Int { return tx.GasFeeCap } -func (tx *DynamicFeeTx) gasTipCap() *big.Int { return tx.GasTipCap } -func (tx *DynamicFeeTx) gasPrice() *big.Int { return tx.GasFeeCap } -func (tx *DynamicFeeTx) value() *big.Int { return tx.Value } -func (tx *DynamicFeeTx) nonce() uint64 { return tx.Nonce } -func (tx *DynamicFeeTx) to() *common.Address { return tx.To } -func (tx *DynamicFeeTx) blobGas() uint64 { return 0 } -func (tx *DynamicFeeTx) blobGasFeeCap() *big.Int { return nil } -func (tx *DynamicFeeTx) blobHashes() []common.Hash { return nil } +func (tx *DynamicFeeTx) txType() byte { return DynamicFeeTxType } +func (tx *DynamicFeeTx) chainID() *big.Int { return tx.ChainID } +func (tx *DynamicFeeTx) accessList() AccessList { return tx.AccessList } +func (tx *DynamicFeeTx) data() []byte { return tx.Data } +func (tx *DynamicFeeTx) gas() uint64 { return tx.Gas } +func (tx *DynamicFeeTx) gasFeeCap() *big.Int { return tx.GasFeeCap } +func (tx *DynamicFeeTx) gasTipCap() *big.Int { return tx.GasTipCap } +func (tx *DynamicFeeTx) gasPrice() *big.Int { return tx.GasFeeCap } +func (tx *DynamicFeeTx) value() *big.Int { return tx.Value } +func (tx *DynamicFeeTx) nonce() uint64 { return tx.Nonce } +func (tx *DynamicFeeTx) to() *common.Address { return tx.To }   func (tx *DynamicFeeTx) effectiveGasPrice(dst *big.Int, baseFee *big.Int) *big.Int { if baseFee == nil { @@ -116,3 +119,11 @@ func (tx *DynamicFeeTx) setSignatureValues(chainID, v, r, s *big.Int) { tx.ChainID, tx.V, tx.R, tx.S = chainID, v, r, s } + +func (tx *DynamicFeeTx) encode(b *bytes.Buffer) error { + return rlp.Encode(b, tx) +} + +func (tx *DynamicFeeTx) decode(input []byte) error { + return rlp.DecodeBytes(input, tx) +}
diff --git ethereum/go-ethereum/core/asm/compiler_test.go taikoxyz/taiko-geth/core/asm/compiler_test.go index ce9df436bd404c47bbf8c87be95a6aa63c992d94..3d64c96bc80b41f73b8f04c4df6fe839857e89bb 100644 --- ethereum/go-ethereum/core/asm/compiler_test.go +++ taikoxyz/taiko-geth/core/asm/compiler_test.go @@ -54,6 +54,14 @@ label: `, output: "6300000006565b", }, + { + input: ` + JUMP @label +label: ;; comment + ADD ;; comment +`, + output: "6300000006565b01", + }, } for _, test := range tests { ch := Lex([]byte(test.input), false)
diff --git ethereum/go-ethereum/core/rawdb/taiko_l1_origin_test.go taikoxyz/taiko-geth/core/rawdb/taiko_l1_origin_test.go new file mode 100644 index 0000000000000000000000000000000000000000..dae37a354fa5a6f9afae623e30cc2e9e8e1d69e8 --- /dev/null +++ taikoxyz/taiko-geth/core/rawdb/taiko_l1_origin_test.go @@ -0,0 +1,59 @@ +package rawdb + +import ( + "crypto/rand" + "math/big" + "testing" + + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/log" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" +) + +// randomBigInt generates a random big integer. +func randomBigInt() *big.Int { + randomBigInt, err := rand.Int(rand.Reader, common.Big256) + if err != nil { + log.Crit(err.Error()) + } + + return randomBigInt +} + +// randomHash generates a random blob of data and returns it as a hash. +func randomHash() common.Hash { + var hash common.Hash + if n, err := rand.Read(hash[:]); n != common.HashLength || err != nil { + panic(err) + } + return hash +} + +func TestL1Origin(t *testing.T) { + db := NewMemoryDatabase() + testL1Origin := &L1Origin{ + BlockID: randomBigInt(), + L2BlockHash: randomHash(), + L1BlockHeight: randomBigInt(), + L1BlockHash: randomHash(), + } + WriteL1Origin(db, testL1Origin.BlockID, testL1Origin) + l1Origin, err := ReadL1Origin(db, testL1Origin.BlockID) + require.Nil(t, err) + require.NotNil(t, l1Origin) + assert.Equal(t, testL1Origin.BlockID, l1Origin.BlockID) + assert.Equal(t, testL1Origin.L2BlockHash, l1Origin.L2BlockHash) + assert.Equal(t, testL1Origin.L1BlockHeight, l1Origin.L1BlockHeight) + assert.Equal(t, testL1Origin.L1BlockHash, l1Origin.L1BlockHash) +} + +func TestHeadL1Origin(t *testing.T) { + db := NewMemoryDatabase() + testBlockID := randomBigInt() + WriteHeadL1Origin(db, testBlockID) + blockID, err := ReadHeadL1Origin(db) + require.Nil(t, err) + require.NotNil(t, blockID) + assert.Equal(t, testBlockID, blockID) +}
diff --git ethereum/go-ethereum/core/types/tx_legacy.go taikoxyz/taiko-geth/core/types/tx_legacy.go index 902e70cf94b9607bb1a6b667e4a81070813f5e01..71025b78fc060692c1d034f84b59b4cdc8e6cf65 100644 --- ethereum/go-ethereum/core/types/tx_legacy.go +++ taikoxyz/taiko-geth/core/types/tx_legacy.go @@ -17,6 +17,7 @@ package types   import ( + "bytes" "math/big"   "github.com/ethereum/go-ethereum/common" @@ -91,20 +92,17 @@ return cpy }   // accessors for innerTx. -func (tx *LegacyTx) txType() byte { return LegacyTxType } -func (tx *LegacyTx) chainID() *big.Int { return deriveChainId(tx.V) } -func (tx *LegacyTx) accessList() AccessList { return nil } -func (tx *LegacyTx) data() []byte { return tx.Data } -func (tx *LegacyTx) gas() uint64 { return tx.Gas } -func (tx *LegacyTx) gasPrice() *big.Int { return tx.GasPrice } -func (tx *LegacyTx) gasTipCap() *big.Int { return tx.GasPrice } -func (tx *LegacyTx) gasFeeCap() *big.Int { return tx.GasPrice } -func (tx *LegacyTx) value() *big.Int { return tx.Value } -func (tx *LegacyTx) nonce() uint64 { return tx.Nonce } -func (tx *LegacyTx) to() *common.Address { return tx.To } -func (tx *LegacyTx) blobGas() uint64 { return 0 } -func (tx *LegacyTx) blobGasFeeCap() *big.Int { return nil } -func (tx *LegacyTx) blobHashes() []common.Hash { return nil } +func (tx *LegacyTx) txType() byte { return LegacyTxType } +func (tx *LegacyTx) chainID() *big.Int { return deriveChainId(tx.V) } +func (tx *LegacyTx) accessList() AccessList { return nil } +func (tx *LegacyTx) data() []byte { return tx.Data } +func (tx *LegacyTx) gas() uint64 { return tx.Gas } +func (tx *LegacyTx) gasPrice() *big.Int { return tx.GasPrice } +func (tx *LegacyTx) gasTipCap() *big.Int { return tx.GasPrice } +func (tx *LegacyTx) gasFeeCap() *big.Int { return tx.GasPrice } +func (tx *LegacyTx) value() *big.Int { return tx.Value } +func (tx *LegacyTx) nonce() uint64 { return tx.Nonce } +func (tx *LegacyTx) to() *common.Address { return tx.To }   func (tx *LegacyTx) effectiveGasPrice(dst *big.Int, baseFee *big.Int) *big.Int { return dst.Set(tx.GasPrice) @@ -117,3 +115,11 @@ func (tx *LegacyTx) setSignatureValues(chainID, v, r, s *big.Int) { tx.V, tx.R, tx.S = v, r, s } + +func (tx *LegacyTx) encode(*bytes.Buffer) error { + panic("encode called on LegacyTx") +} + +func (tx *LegacyTx) decode([]byte) error { + panic("decode called on LegacyTx)") +}
diff --git ethereum/go-ethereum/core/asm/lexer.go taikoxyz/taiko-geth/core/asm/lexer.go index d1b79a1fb922d5bcf8735a2ec592d42feb5bbd76..e025c6f363c6cd51e3974adafd683992cd541eaf 100644 --- ethereum/go-ethereum/core/asm/lexer.go +++ taikoxyz/taiko-geth/core/asm/lexer.go @@ -42,6 +42,8 @@ // tokenType are the different types the lexer // is able to parse and return. type tokenType int   +//go:generate go run golang.org/x/tools/cmd/stringer -type tokenType + const ( eof tokenType = iota // end of file lineStart // emitted when a line starts @@ -52,31 +54,13 @@ label // label is emitted when a label is found labelDef // label definition is emitted when a new label is found number // number is emitted when a number is found stringValue // stringValue is emitted when a string has been found - - Numbers = "1234567890" // characters representing any decimal number - HexadecimalNumbers = Numbers + "aAbBcCdDeEfF" // characters representing any hexadecimal - Alpha = "abcdefghijklmnopqrstuwvxyzABCDEFGHIJKLMNOPQRSTUWVXYZ" // characters representing alphanumeric )   -// String implements stringer -func (it tokenType) String() string { - if int(it) > len(stringtokenTypes) { - return "invalid" - } - return stringtokenTypes[it] -} - -var stringtokenTypes = []string{ - eof: "EOF", - lineStart: "new line", - lineEnd: "end of line", - invalidStatement: "invalid statement", - element: "element", - label: "label", - labelDef: "label definition", - number: "number", - stringValue: "string", -} +const ( + decimalNumbers = "1234567890" // characters representing any decimal number + hexNumbers = decimalNumbers + "aAbBcCdDeEfF" // characters representing any hexadecimal + alpha = "abcdefghijklmnopqrstuwvxyzABCDEFGHIJKLMNOPQRSTUWVXYZ" // characters representing alphanumeric +)   // lexer is the basic construct for parsing // source code and turning them in to tokens. @@ -200,7 +184,6 @@ case r == '\n': l.emit(lineEnd) l.ignore() l.lineno++ - l.emit(lineStart) case r == ';' && l.peek() == ';': return lexComment @@ -225,6 +208,7 @@ // lexComment parses the current position until the end // of the line and discards the text. func lexComment(l *lexer) stateFn { l.acceptRunUntil('\n') + l.backup() l.ignore()   return lexLine @@ -234,7 +218,7 @@ // lexLabel parses the current label, emits and returns // the lex text state function to advance the parsing // process. func lexLabel(l *lexer) stateFn { - l.acceptRun(Alpha + "_" + Numbers) + l.acceptRun(alpha + "_" + decimalNumbers)   l.emit(label)   @@ -253,9 +237,9 @@ return lexLine }   func lexNumber(l *lexer) stateFn { - acceptance := Numbers + acceptance := decimalNumbers if l.accept("xX") { - acceptance = HexadecimalNumbers + acceptance = hexNumbers } l.acceptRun(acceptance)   @@ -265,7 +249,7 @@ return lexLine }   func lexElement(l *lexer) stateFn { - l.acceptRun(Alpha + "_" + Numbers) + l.acceptRun(alpha + "_" + decimalNumbers)   if l.peek() == ':' { l.emit(labelDef)
diff --git ethereum/go-ethereum/core/vm/interpreter.go taikoxyz/taiko-geth/core/vm/interpreter.go index 873337850e6f3fb787a71bd0ffca8a334ec4f6e5..28da2e80e60eca0aaec4d7e8199297e35044ba38 100644 --- ethereum/go-ethereum/core/vm/interpreter.go +++ taikoxyz/taiko-geth/core/vm/interpreter.go @@ -45,7 +45,7 @@ evm *EVM table *JumpTable   hasher crypto.KeccakState // Keccak256 hasher instance shared across opcodes - hasherBuf common.Hash // Keccak256 hasher result array shared aross opcodes + hasherBuf common.Hash // Keccak256 hasher result array shared across opcodes   readOnly bool // Whether to throw on stateful modifications returnData []byte // Last CALL's return data for subsequent reuse
diff --git ethereum/go-ethereum/core/state/iterator.go taikoxyz/taiko-geth/core/state/iterator.go index bb9af082061f25d036375997bd9e6207e85eaca7..683efd73de706f9652f7546990684fd09cfdf2e2 100644 --- ethereum/go-ethereum/core/state/iterator.go +++ taikoxyz/taiko-geth/core/state/iterator.go @@ -112,7 +112,7 @@ return nil } // Otherwise we've reached an account node, initiate data iteration var account types.StateAccount - if err := rlp.Decode(bytes.NewReader(it.stateIt.LeafBlob()), &account); err != nil { + if err := rlp.DecodeBytes(it.stateIt.LeafBlob(), &account); err != nil { return err } // Lookup the preimage of account hash
diff --git ethereum/go-ethereum/core/rawdb/table.go taikoxyz/taiko-geth/core/rawdb/table.go index 1895f61da200c398d45f9793439196595563564d..19e4ed5b5c4b5deedc12286639e2ff3655782c0d 100644 --- ethereum/go-ethereum/core/rawdb/table.go +++ taikoxyz/taiko-geth/core/rawdb/table.go @@ -219,7 +219,7 @@ func (b *tableBatch) Put(key, value []byte) error { return b.batch.Put(append([]byte(b.prefix), key...), value) }   -// Delete inserts the a key removal into the batch for later committing. +// Delete inserts a key removal into the batch for later committing. func (b *tableBatch) Delete(key []byte) error { return b.batch.Delete(append([]byte(b.prefix), key...)) }
diff --git ethereum/go-ethereum/core/rawdb/ancient_scheme.go taikoxyz/taiko-geth/core/rawdb/ancient_scheme.go index c1cd7fda17f2434aa1d2f348aba18968b01ecbd3..6f409fff1d0a7cb389f80a84d9788ca2295ca91f 100644 --- ethereum/go-ethereum/core/rawdb/ancient_scheme.go +++ taikoxyz/taiko-geth/core/rawdb/ancient_scheme.go @@ -58,7 +58,7 @@ stateHistoryAccountData = "account.data" stateHistoryStorageData = "storage.data" )   -var stateHistoryFreezerNoSnappy = map[string]bool{ +var stateFreezerNoSnappy = map[string]bool{ stateHistoryMeta: true, stateHistoryAccountIndex: false, stateHistoryStorageIndex: false, @@ -75,7 +75,7 @@ // freezers the collections of all builtin freezers. var freezers = []string{chainFreezerName, stateFreezerName}   -// NewStateHistoryFreezer initializes the freezer for state history. -func NewStateHistoryFreezer(ancientDir string, readOnly bool) (*ResettableFreezer, error) { - return NewResettableFreezer(filepath.Join(ancientDir, stateFreezerName), "eth/db/state", readOnly, stateHistoryTableSize, stateHistoryFreezerNoSnappy) +// NewStateFreezer initializes the freezer for state history. +func NewStateFreezer(ancientDir string, readOnly bool) (*ResettableFreezer, error) { + return NewResettableFreezer(filepath.Join(ancientDir, stateFreezerName), "eth/db/state", readOnly, stateHistoryTableSize, stateFreezerNoSnappy) }
diff --git ethereum/go-ethereum/core/asm/lex_test.go taikoxyz/taiko-geth/core/asm/lex_test.go index 53e05fbbba0ccee827499830f4e145d5b9525fc7..1e62d776d4016cfe914d4ed9bd0a0661fa43928b 100644 --- ethereum/go-ethereum/core/asm/lex_test.go +++ taikoxyz/taiko-geth/core/asm/lex_test.go @@ -72,6 +72,16 @@ { input: "@label123", tokens: []token{{typ: lineStart}, {typ: label, text: "label123"}, {typ: eof}}, }, + // Comment after label + { + input: "@label123 ;; comment", + tokens: []token{{typ: lineStart}, {typ: label, text: "label123"}, {typ: eof}}, + }, + // Comment after instruction + { + input: "push 3 ;; comment\nadd", + tokens: []token{{typ: lineStart}, {typ: element, text: "push"}, {typ: number, text: "3"}, {typ: lineEnd, text: "\n"}, {typ: lineStart, lineno: 1}, {typ: element, lineno: 1, text: "add"}, {typ: eof, lineno: 1}}, + }, }   for _, test := range tests {
diff --git ethereum/go-ethereum/core/rawdb/taiko_l1_origin.go taikoxyz/taiko-geth/core/rawdb/taiko_l1_origin.go new file mode 100644 index 0000000000000000000000000000000000000000..aaa5c14832f39b524e863ad9ef0a64c044a9a1d6 --- /dev/null +++ taikoxyz/taiko-geth/core/rawdb/taiko_l1_origin.go @@ -0,0 +1,92 @@ +package rawdb + +import ( + "bytes" + "fmt" + "math/big" + + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/common/math" + "github.com/ethereum/go-ethereum/ethdb" + "github.com/ethereum/go-ethereum/log" + "github.com/ethereum/go-ethereum/rlp" +) + +var ( + // Database key prefix for L2 block's L1Origin. + l1OriginPrefix = []byte("TKO:L1O") + headL1OriginKey = []byte("TKO:LastL1O") +) + +// l1OriginKey calculates the L1Origin key. +// l1OriginPrefix + l2HeaderHash -> l1OriginKey +func l1OriginKey(blockID *big.Int) []byte { + data, _ := (*math.HexOrDecimal256)(blockID).MarshalText() + return append(l1OriginPrefix, data...) +} + +//go:generate go run github.com/fjl/gencodec -type L1Origin -field-override l1OriginMarshaling -out gen_taiko_l1_origin.go + +// L1Origin represents a L1Origin of a L2 block. +type L1Origin struct { + BlockID *big.Int `json:"blockID" gencodec:"required"` + L2BlockHash common.Hash `json:"l2BlockHash"` + L1BlockHeight *big.Int `json:"l1BlockHeight" gencodec:"required"` + L1BlockHash common.Hash `json:"l1BlockHash" gencodec:"required"` +} + +type l1OriginMarshaling struct { + BlockID *math.HexOrDecimal256 + L1BlockHeight *math.HexOrDecimal256 +} + +// WriteL1Origin stores a L1Origin into the database. +func WriteL1Origin(db ethdb.KeyValueWriter, blockID *big.Int, l1Origin *L1Origin) { + data, err := rlp.EncodeToBytes(l1Origin) + if err != nil { + log.Crit("Failed to encode L1Origin", "err", err) + } + + if err := db.Put(l1OriginKey(blockID), data); err != nil { + log.Crit("Failed to store L1Origin", "err", err) + } +} + +// ReadL1Origin retrieves the given L2 block's L1Origin from database. +func ReadL1Origin(db ethdb.KeyValueReader, blockID *big.Int) (*L1Origin, error) { + data, _ := db.Get(l1OriginKey(blockID)) + if len(data) == 0 { + return nil, nil + } + + l1Origin := new(L1Origin) + if err := rlp.Decode(bytes.NewReader(data), l1Origin); err != nil { + return nil, fmt.Errorf("invalid L1Origin RLP bytes: %w", err) + } + + return l1Origin, nil +} + +// WriteHeadL1Origin stores the given L1Origin as the last L1Origin. +func WriteHeadL1Origin(db ethdb.KeyValueWriter, blockID *big.Int) { + data, _ := (*math.HexOrDecimal256)(blockID).MarshalText() + if err := db.Put(headL1OriginKey, data); err != nil { + log.Crit("Failed to store head L1Origin", "error", err) + } +} + +// ReadHeadL1Origin retrieves the last L1Origin from database. +func ReadHeadL1Origin(db ethdb.KeyValueReader) (*big.Int, error) { + data, _ := db.Get(headL1OriginKey) + if len(data) == 0 { + return nil, nil + } + + blockID := new(math.HexOrDecimal256) + if err := blockID.UnmarshalText(data); err != nil { + log.Error("Unmarshal L1Origin unmarshal error", "error", err) + return nil, fmt.Errorf("invalid L1Origin unmarshal: %w", err) + } + + return (*big.Int)(blockID), nil +}
diff --git ethereum/go-ethereum/core/state/statedb_test.go taikoxyz/taiko-geth/core/state/statedb_test.go index 66dda238e11e13603dccb7b8447a5f59b934387c..ad829a0c8f091ffbcd8a546a53d860b73014d1a8 100644 --- ethereum/go-ethereum/core/state/statedb_test.go +++ taikoxyz/taiko-geth/core/state/statedb_test.go @@ -35,15 +35,23 @@ "github.com/ethereum/go-ethereum/core/rawdb" "github.com/ethereum/go-ethereum/core/state/snapshot" "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/crypto" + "github.com/ethereum/go-ethereum/rlp" "github.com/ethereum/go-ethereum/trie" + "github.com/ethereum/go-ethereum/trie/triedb/hashdb" + "github.com/ethereum/go-ethereum/trie/triedb/pathdb" + "github.com/ethereum/go-ethereum/trie/trienode" + "github.com/holiman/uint256" )   // Tests that updating a state trie does not leak any database writes prior to // actually committing the state. func TestUpdateLeaks(t *testing.T) { // Create an empty state database - db := rawdb.NewMemoryDatabase() - state, _ := New(types.EmptyRootHash, NewDatabase(db), nil) + var ( + db = rawdb.NewMemoryDatabase() + tdb = trie.NewDatabase(db, nil) + ) + state, _ := New(types.EmptyRootHash, NewDatabaseWithNodeDB(db, tdb), nil)   // Update it with some accounts for i := byte(0); i < 255; i++ { @@ -59,7 +67,7 @@ } }   root := state.IntermediateRoot(false) - if err := state.Database().TrieDB().Commit(root, false); err != nil { + if err := tdb.Commit(root, false); err != nil { t.Errorf("can not commit trie %v to persistent database", root.Hex()) }   @@ -77,8 +85,10 @@ func TestIntermediateLeaks(t *testing.T) { // Create two state databases, one transitioning to the final state, the other final from the beginning transDb := rawdb.NewMemoryDatabase() finalDb := rawdb.NewMemoryDatabase() - transState, _ := New(types.EmptyRootHash, NewDatabase(transDb), nil) - finalState, _ := New(types.EmptyRootHash, NewDatabase(finalDb), nil) + transNdb := trie.NewDatabase(transDb, nil) + finalNdb := trie.NewDatabase(finalDb, nil) + transState, _ := New(types.EmptyRootHash, NewDatabaseWithNodeDB(transDb, transNdb), nil) + finalState, _ := New(types.EmptyRootHash, NewDatabaseWithNodeDB(finalDb, finalNdb), nil)   modify := func(state *StateDB, addr common.Address, i, tweak byte) { state.SetBalance(addr, big.NewInt(int64(11*i)+int64(tweak))) @@ -110,7 +120,7 @@ transRoot, err := transState.Commit(0, false) if err != nil { t.Fatalf("failed to commit transition state: %v", err) } - if err = transState.Database().TrieDB().Commit(transRoot, false); err != nil { + if err = transNdb.Commit(transRoot, false); err != nil { t.Errorf("can not commit trie %v to persistent database", transRoot.Hex()) }   @@ -118,7 +128,7 @@ finalRoot, err := finalState.Commit(0, false) if err != nil { t.Fatalf("failed to commit final state: %v", err) } - if err = finalState.Database().TrieDB().Commit(finalRoot, false); err != nil { + if err = finalNdb.Commit(finalRoot, false); err != nil { t.Errorf("can not commit trie %v to persistent database", finalRoot.Hex()) }   @@ -440,6 +450,43 @@ } return true }   +func forEachStorage(s *StateDB, addr common.Address, cb func(key, value common.Hash) bool) error { + so := s.getStateObject(addr) + if so == nil { + return nil + } + tr, err := so.getTrie() + if err != nil { + return err + } + trieIt, err := tr.NodeIterator(nil) + if err != nil { + return err + } + it := trie.NewIterator(trieIt) + + for it.Next() { + key := common.BytesToHash(s.trie.GetKey(it.Key)) + if value, dirty := so.dirtyStorage[key]; dirty { + if !cb(key, value) { + return nil + } + continue + } + + if len(it.Value) > 0 { + _, content, _, err := rlp.Split(it.Value) + if err != nil { + return err + } + if !cb(key, common.BytesToHash(content)) { + return nil + } + } + } + return nil +} + // checkEqual checks that methods of state and checkstate return the same values. func (test *snapshotTest) checkEqual(state, checkstate *StateDB) error { for _, addr := range test.addrs { @@ -461,10 +508,10 @@ checkeq("GetCodeHash", state.GetCodeHash(addr), checkstate.GetCodeHash(addr)) checkeq("GetCodeSize", state.GetCodeSize(addr), checkstate.GetCodeSize(addr)) // Check storage. if obj := state.getStateObject(addr); obj != nil { - state.ForEachStorage(addr, func(key, value common.Hash) bool { + forEachStorage(state, addr, func(key, value common.Hash) bool { return checkeq("GetState("+key.Hex()+")", checkstate.GetState(addr, key), value) }) - checkstate.ForEachStorage(addr, func(key, value common.Hash) bool { + forEachStorage(checkstate, addr, func(key, value common.Hash) bool { return checkeq("GetState("+key.Hex()+")", checkstate.GetState(addr, key), value) }) } @@ -747,9 +794,28 @@ // TestMissingTrieNodes tests that if the StateDB fails to load parts of the trie, // the Commit operation fails with an error // If we are missing trie nodes, we should not continue writing to the trie func TestMissingTrieNodes(t *testing.T) { + testMissingTrieNodes(t, rawdb.HashScheme) + testMissingTrieNodes(t, rawdb.PathScheme) +} + +func testMissingTrieNodes(t *testing.T, scheme string) { // Create an initial state with a few accounts - memDb := rawdb.NewMemoryDatabase() - db := NewDatabase(memDb) + var ( + triedb *trie.Database + memDb = rawdb.NewMemoryDatabase() + ) + if scheme == rawdb.PathScheme { + triedb = trie.NewDatabase(memDb, &trie.Config{PathDB: &pathdb.Config{ + CleanCacheSize: 0, + DirtyCacheSize: 0, + }}) // disable caching + } else { + triedb = trie.NewDatabase(memDb, &trie.Config{HashDB: &hashdb.Config{ + CleanCacheSize: 0, + }}) // disable caching + } + db := NewDatabaseWithNodeDB(memDb, triedb) + var root common.Hash state, _ := New(types.EmptyRootHash, db, nil) addr := common.BytesToAddress([]byte("so")) @@ -762,7 +828,7 @@ state.SetCode(a2, []byte{1, 2, 4}) root, _ = state.Commit(0, false) t.Logf("root: %x", root) // force-flush - state.Database().TrieDB().Cap(0) + triedb.Commit(root, false) } // Create a new state on the old root state, _ = New(root, db, nil) @@ -969,7 +1035,8 @@ func TestFlushOrderDataLoss(t *testing.T) { // Create a state trie with many accounts and slots var ( memdb = rawdb.NewMemoryDatabase() - statedb = NewDatabase(memdb) + triedb = trie.NewDatabase(memdb, nil) + statedb = NewDatabaseWithNodeDB(memdb, triedb) state, _ = New(types.EmptyRootHash, statedb, nil) ) for a := byte(0); a < 10; a++ { @@ -982,11 +1049,11 @@ root, err := state.Commit(0, false) if err != nil { t.Fatalf("failed to commit state trie: %v", err) } - statedb.TrieDB().Reference(root, common.Hash{}) - if err := statedb.TrieDB().Cap(1024); err != nil { + triedb.Reference(root, common.Hash{}) + if err := triedb.Cap(1024); err != nil { t.Fatalf("failed to cap trie dirty cache: %v", err) } - if err := statedb.TrieDB().Commit(root, false); err != nil { + if err := triedb.Commit(root, false); err != nil { t.Fatalf("failed to commit state trie: %v", err) } // Reopen the state trie from flushed disk and verify it @@ -1040,7 +1107,7 @@ func TestResetObject(t *testing.T) { var ( disk = rawdb.NewMemoryDatabase() - tdb = trie.NewDatabase(disk) + tdb = trie.NewDatabase(disk, nil) db = NewDatabaseWithNodeDB(disk, tdb) snaps, _ = snapshot.New(snapshot.Config{CacheSize: 10}, disk, tdb, types.EmptyRootHash) state, _ = New(types.EmptyRootHash, db, snaps) @@ -1070,3 +1137,57 @@ if !bytes.Equal(slot, []byte{0x2}) { t.Fatalf("Unexpected storage slot value %v", slot) } } + +func TestDeleteStorage(t *testing.T) { + var ( + disk = rawdb.NewMemoryDatabase() + tdb = trie.NewDatabase(disk, nil) + db = NewDatabaseWithNodeDB(disk, tdb) + snaps, _ = snapshot.New(snapshot.Config{CacheSize: 10}, disk, tdb, types.EmptyRootHash) + state, _ = New(types.EmptyRootHash, db, snaps) + addr = common.HexToAddress("0x1") + ) + // Initialize account and populate storage + state.SetBalance(addr, big.NewInt(1)) + state.CreateAccount(addr) + for i := 0; i < 1000; i++ { + slot := common.Hash(uint256.NewInt(uint64(i)).Bytes32()) + value := common.Hash(uint256.NewInt(uint64(10 * i)).Bytes32()) + state.SetState(addr, slot, value) + } + root, _ := state.Commit(0, true) + // Init phase done, create two states, one with snap and one without + fastState, _ := New(root, db, snaps) + slowState, _ := New(root, db, nil) + + obj := fastState.GetOrNewStateObject(addr) + storageRoot := obj.data.Root + + _, _, fastNodes, err := fastState.deleteStorage(addr, crypto.Keccak256Hash(addr[:]), storageRoot) + if err != nil { + t.Fatal(err) + } + + _, _, slowNodes, err := slowState.deleteStorage(addr, crypto.Keccak256Hash(addr[:]), storageRoot) + if err != nil { + t.Fatal(err) + } + check := func(set *trienode.NodeSet) string { + var a []string + set.ForEachWithOrder(func(path string, n *trienode.Node) { + if n.Hash != (common.Hash{}) { + t.Fatal("delete should have empty hashes") + } + if len(n.Blob) != 0 { + t.Fatal("delete should have have empty blobs") + } + a = append(a, fmt.Sprintf("%x", path)) + }) + return strings.Join(a, ",") + } + slowRes := check(slowNodes) + fastRes := check(fastNodes) + if slowRes != fastRes { + t.Fatalf("difference found:\nfast: %v\nslow: %v\n", fastRes, slowRes) + } +}
diff --git ethereum/go-ethereum/core/taiko_genesis/genesis_alloc.go taikoxyz/taiko-geth/core/taiko_genesis/genesis_alloc.go new file mode 100644 index 0000000000000000000000000000000000000000..763ef7550e676883b515b911d27e7a8f6fb332ad --- /dev/null +++ taikoxyz/taiko-geth/core/taiko_genesis/genesis_alloc.go @@ -0,0 +1,26 @@ +package taiko_genesis + +import ( + _ "embed" +) + +//go:embed internal.json +var InternalGenesisAllocJSON []byte + +//go:embed internal_l3.json +var InternalL3GenesisAllocJSON []byte + +//go:embed snaefellsjokull.json +var SnaefellsjokullGenesisAllocJSON []byte + +//go:embed askja.json +var AskjaGenesisAllocJSON []byte + +//go:embed grimsvotn.json +var GrimsvotnGenesisAllocJSON []byte + +//go:embed eldfell.json +var EldfellGenesisAllocJSON []byte + +//go:embed jolnir.json +var JolnirGenesisAllocJSON []byte
diff --git ethereum/go-ethereum/core/vm/instructions.go taikoxyz/taiko-geth/core/vm/instructions.go index 2105201fce42875995250c29df5060e35d080558..56ff3502011c9e7f855a9821baaba0b3fc4de73a 100644 --- ethereum/go-ethereum/core/vm/instructions.go +++ taikoxyz/taiko-geth/core/vm/instructions.go @@ -251,6 +251,7 @@ size.SetBytes(interpreter.hasherBuf[:]) return nil, nil } + func opAddress(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) { scope.Stack.push(new(uint256.Int).SetBytes(scope.Contract.Address().Bytes())) return nil, nil @@ -267,6 +268,7 @@ func opOrigin(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) { scope.Stack.push(new(uint256.Int).SetBytes(interpreter.evm.Origin.Bytes())) return nil, nil } + func opCaller(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) { scope.Stack.push(new(uint256.Int).SetBytes(scope.Contract.Caller().Bytes())) return nil, nil
diff --git ethereum/go-ethereum/core/txpool/txpool.go taikoxyz/taiko-geth/core/txpool/txpool.go index b0e91fee6c4462e569d8bd119372962e623802a9..0d4e05da4c1876989b407dbb062481d80c75efbd 100644 --- ethereum/go-ethereum/core/txpool/txpool.go +++ taikoxyz/taiko-geth/core/txpool/txpool.go @@ -70,7 +70,7 @@ reservations map[common.Address]SubPool // Map with the account to pool reservations reserveLock sync.Mutex // Lock protecting the account reservations   - subs event.SubscriptionScope // Subscription scope to unscubscribe all on shutdown + subs event.SubscriptionScope // Subscription scope to unsubscribe all on shutdown quit chan chan error // Quit channel to tear down the head updater }   @@ -155,13 +155,15 @@ p.quit <- errc if err := <-errc; err != nil { errs = append(errs, err) } - // Terminate each subpool for _, subpool := range p.subpools { if err := subpool.Close(); err != nil { errs = append(errs, err) } } + // Unsubscribe anyone still listening for tx events + p.subs.Close() + if len(errs) > 0 { return fmt.Errorf("subpool close errors: %v", errs) } @@ -249,7 +251,7 @@ return false }   // Get returns a transaction if it is contained in the pool, or nil otherwise. -func (p *TxPool) Get(hash common.Hash) *Transaction { +func (p *TxPool) Get(hash common.Hash) *types.Transaction { for _, subpool := range p.subpools { if tx := subpool.Get(hash); tx != nil { return tx @@ -261,14 +263,14 @@ // Add enqueues a batch of transactions into the pool if they are valid. Due // to the large transaction churn, add may postpone fully integrating the tx // to a later point to batch multiple ones together. -func (p *TxPool) Add(txs []*Transaction, local bool, sync bool) []error { +func (p *TxPool) Add(txs []*types.Transaction, local bool, sync bool) []error { // Split the input transactions between the subpools. It shouldn't really // happen that we receive merged batches, but better graceful than strange // errors. // // We also need to track how the transactions were split across the subpools, // so we can piece back the returned errors into the original order. - txsets := make([][]*Transaction, len(p.subpools)) + txsets := make([][]*types.Transaction, len(p.subpools)) splits := make([]int, len(txs))   for i, tx := range txs { @@ -277,7 +279,7 @@ splits[i] = -1   // Try to find a subpool that accepts the transaction for j, subpool := range p.subpools { - if subpool.Filter(tx.Tx) { + if subpool.Filter(tx) { txsets[j] = append(txsets[j], tx) splits[i] = j break @@ -316,12 +318,12 @@ } return txs }   -// SubscribeNewTxsEvent registers a subscription of NewTxsEvent and starts sending -// events to the given channel. -func (p *TxPool) SubscribeNewTxsEvent(ch chan<- core.NewTxsEvent) event.Subscription { +// SubscribeTransactions registers a subscription for new transaction events, +// supporting feeding only newly seen or also resurrected transactions. +func (p *TxPool) SubscribeTransactions(ch chan<- core.NewTxsEvent, reorgs bool) event.Subscription { subs := make([]event.Subscription, len(p.subpools)) for i, subpool := range p.subpools { - subs[i] = subpool.SubscribeTransactions(ch) + subs[i] = subpool.SubscribeTransactions(ch, reorgs) } return p.subs.Track(event.JoinSubscriptions(subs...)) } @@ -404,7 +406,7 @@ return flat }   // Status returns the known status (unknown/pending/queued) of a transaction -// identified by their hashes. +// identified by its hash. func (p *TxPool) Status(hash common.Hash) TxStatus { for _, subpool := range p.subpools { if status := subpool.Status(hash); status != TxStatusUnknown {
diff --git ethereum/go-ethereum/core/types/receipt.go taikoxyz/taiko-geth/core/types/receipt.go index a96eb6b8d603b220497bb6d9e1b8df4a0cb4278a..4f96fde59c44278beee06e9846e158c2501644e6 100644 --- ethereum/go-ethereum/core/types/receipt.go +++ taikoxyz/taiko-geth/core/types/receipt.go @@ -153,7 +153,7 @@ // DecodeRLP implements rlp.Decoder, and loads the consensus fields of a receipt // from an RLP stream. func (r *Receipt) DecodeRLP(s *rlp.Stream) error { - kind, _, err := s.Kind() + kind, size, err := s.Kind() switch { case err != nil: return err @@ -165,10 +165,16 @@ return err } r.Type = LegacyTxType return r.setFromRLP(dec) + case kind == rlp.Byte: + return errShortTypedReceipt default: // It's an EIP-2718 typed tx receipt. - b, err := s.Bytes() + b, buf, err := getPooledBuffer(size) if err != nil { + return err + } + defer encodeBufferPool.Put(buf) + if err := s.ReadBytes(b); err != nil { return err } return r.decodeTyped(b) @@ -264,7 +270,7 @@ w.WriteBytes((*Receipt)(r).statusEncoding()) w.WriteUint64(r.CumulativeGasUsed) logList := w.List() for _, log := range r.Logs { - if err := rlp.Encode(w, log); err != nil { + if err := log.EncodeRLP(w); err != nil { return err } }
diff --git ethereum/go-ethereum/core/types/transaction_test.go taikoxyz/taiko-geth/core/types/transaction_test.go index a984a9c70952da9729fd6b5002ebd049d1d62736..25ced0841ba1944c442061bfd62bd6bda0ddc76e 100644 --- ethereum/go-ethereum/core/types/transaction_test.go +++ taikoxyz/taiko-geth/core/types/transaction_test.go @@ -214,7 +214,7 @@ }   func decodeTx(data []byte) (*Transaction, error) { var tx Transaction - t, err := &tx, rlp.Decode(bytes.NewReader(data), &tx) + t, err := &tx, rlp.DecodeBytes(data, &tx) return t, err }
diff --git ethereum/go-ethereum/core/types/tx_access_list.go taikoxyz/taiko-geth/core/types/tx_access_list.go index 7ce9da73ecbe4a34d91803738c15b501dbaed134..730a77b752866afb5e6ba3d7ea8f4a5af6456d00 100644 --- ethereum/go-ethereum/core/types/tx_access_list.go +++ taikoxyz/taiko-geth/core/types/tx_access_list.go @@ -17,9 +17,11 @@ package types   import ( + "bytes" "math/big"   "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/rlp" )   //go:generate go run github.com/fjl/gencodec -type AccessTuple -out gen_access_tuple.go @@ -94,20 +96,17 @@ return cpy }   // accessors for innerTx. -func (tx *AccessListTx) txType() byte { return AccessListTxType } -func (tx *AccessListTx) chainID() *big.Int { return tx.ChainID } -func (tx *AccessListTx) accessList() AccessList { return tx.AccessList } -func (tx *AccessListTx) data() []byte { return tx.Data } -func (tx *AccessListTx) gas() uint64 { return tx.Gas } -func (tx *AccessListTx) gasPrice() *big.Int { return tx.GasPrice } -func (tx *AccessListTx) gasTipCap() *big.Int { return tx.GasPrice } -func (tx *AccessListTx) gasFeeCap() *big.Int { return tx.GasPrice } -func (tx *AccessListTx) value() *big.Int { return tx.Value } -func (tx *AccessListTx) nonce() uint64 { return tx.Nonce } -func (tx *AccessListTx) to() *common.Address { return tx.To } -func (tx *AccessListTx) blobGas() uint64 { return 0 } -func (tx *AccessListTx) blobGasFeeCap() *big.Int { return nil } -func (tx *AccessListTx) blobHashes() []common.Hash { return nil } +func (tx *AccessListTx) txType() byte { return AccessListTxType } +func (tx *AccessListTx) chainID() *big.Int { return tx.ChainID } +func (tx *AccessListTx) accessList() AccessList { return tx.AccessList } +func (tx *AccessListTx) data() []byte { return tx.Data } +func (tx *AccessListTx) gas() uint64 { return tx.Gas } +func (tx *AccessListTx) gasPrice() *big.Int { return tx.GasPrice } +func (tx *AccessListTx) gasTipCap() *big.Int { return tx.GasPrice } +func (tx *AccessListTx) gasFeeCap() *big.Int { return tx.GasPrice } +func (tx *AccessListTx) value() *big.Int { return tx.Value } +func (tx *AccessListTx) nonce() uint64 { return tx.Nonce } +func (tx *AccessListTx) to() *common.Address { return tx.To }   func (tx *AccessListTx) effectiveGasPrice(dst *big.Int, baseFee *big.Int) *big.Int { return dst.Set(tx.GasPrice) @@ -120,3 +119,11 @@ func (tx *AccessListTx) setSignatureValues(chainID, v, r, s *big.Int) { tx.ChainID, tx.V, tx.R, tx.S = chainID, v, r, s } + +func (tx *AccessListTx) encode(b *bytes.Buffer) error { + return rlp.Encode(b, tx) +} + +func (tx *AccessListTx) decode(input []byte) error { + return rlp.DecodeBytes(input, tx) +}
diff --git ethereum/go-ethereum/core/vm/evm.go taikoxyz/taiko-geth/core/vm/evm.go index 40e2f3554f4665839c06be647f736e1de143f721..2c6cc7d4846689d4d4c862ec38fc86a051fb30ad 100644 --- ethereum/go-ethereum/core/vm/evm.go +++ taikoxyz/taiko-geth/core/vm/evm.go @@ -67,14 +67,14 @@ // GetHash returns the hash corresponding to n GetHash GetHashFunc   // Block information - Coinbase common.Address // Provides information for COINBASE - GasLimit uint64 // Provides information for GASLIMIT - BlockNumber *big.Int // Provides information for NUMBER - Time uint64 // Provides information for TIME - Difficulty *big.Int // Provides information for DIFFICULTY - BaseFee *big.Int // Provides information for BASEFEE - Random *common.Hash // Provides information for PREVRANDAO - ExcessBlobGas *uint64 // ExcessBlobGas field in the header, needed to compute the data + Coinbase common.Address // Provides information for COINBASE + GasLimit uint64 // Provides information for GASLIMIT + BlockNumber *big.Int // Provides information for NUMBER + Time uint64 // Provides information for TIME + Difficulty *big.Int // Provides information for DIFFICULTY + BaseFee *big.Int // Provides information for BASEFEE + BlobBaseFee *big.Int // Provides information for BLOBBASEFEE + Random *common.Hash // Provides information for PREVRANDAO }   // TxContext provides the EVM with information about a transaction.
diff --git ethereum/go-ethereum/core/types/transaction.go taikoxyz/taiko-geth/core/types/transaction.go index e774809c29d97392171f70bb3cfe5c33d65834f8..f245f1eacb8c8fff3f5d2dcc46729cc8c111959c 100644 --- ethereum/go-ethereum/core/types/transaction.go +++ taikoxyz/taiko-geth/core/types/transaction.go @@ -82,9 +82,10 @@ gasFeeCap() *big.Int value() *big.Int nonce() uint64 to() *common.Address - blobGas() uint64 - blobGasFeeCap() *big.Int - blobHashes() []common.Hash + + // CHANGE(taiko): anchor transaction related. + isAnchor() bool + markAsAnchor() error   rawSignatureValues() (v, r, s *big.Int) setSignatureValues(chainID, v, r, s *big.Int) @@ -96,6 +97,9 @@ // Unlike other TxData methods, the returned *big.Int should be an independent // copy of the computed value, i.e. callers are allowed to mutate the result. // Method implementations can use 'dst' to store the result. effectiveGasPrice(dst *big.Int, baseFee *big.Int) *big.Int + + encode(*bytes.Buffer) error + decode([]byte) error }   // EncodeRLP implements rlp.Encoder @@ -116,7 +120,7 @@ // encodeTyped writes the canonical encoding of a typed transaction to w. func (tx *Transaction) encodeTyped(w *bytes.Buffer) error { w.WriteByte(tx.Type()) - return rlp.Encode(w, tx.inner) + return tx.inner.encode(w) }   // MarshalBinary returns the canonical encoding of the transaction. @@ -145,22 +149,30 @@ if err == nil { tx.setDecoded(&inner, rlp.ListSize(size)) } return err + case kind == rlp.Byte: + return errShortTypedTx default: // It's an EIP-2718 typed TX envelope. - var b []byte - if b, err = s.Bytes(); err != nil { + // First read the tx payload bytes into a temporary buffer. + b, buf, err := getPooledBuffer(size) + if err != nil { return err } + defer encodeBufferPool.Put(buf) + if err := s.ReadBytes(b); err != nil { + return err + } + // Now decode the inner transaction. inner, err := tx.decodeTyped(b) if err == nil { - tx.setDecoded(inner, uint64(len(b))) + tx.setDecoded(inner, size) } return err } }   // UnmarshalBinary decodes the canonical encoding of transactions. -// It supports legacy RLP transactions and EIP2718 typed transactions. +// It supports legacy RLP transactions and EIP-2718 typed transactions. func (tx *Transaction) UnmarshalBinary(b []byte) error { if len(b) > 0 && b[0] > 0x7f { // It's a legacy transaction. @@ -172,7 +184,7 @@ } tx.setDecoded(&data, uint64(len(b))) return nil } - // It's an EIP2718 typed transaction envelope. + // It's an EIP-2718 typed transaction envelope. inner, err := tx.decodeTyped(b) if err != nil { return err @@ -186,22 +198,19 @@ func (tx *Transaction) decodeTyped(b []byte) (TxData, error) { if len(b) <= 1 { return nil, errShortTypedTx } + var inner TxData switch b[0] { case AccessListTxType: - var inner AccessListTx - err := rlp.DecodeBytes(b[1:], &inner) - return &inner, err + inner = new(AccessListTx) case DynamicFeeTxType: - var inner DynamicFeeTx - err := rlp.DecodeBytes(b[1:], &inner) - return &inner, err + inner = new(DynamicFeeTx) case BlobTxType: - var inner BlobTx - err := rlp.DecodeBytes(b[1:], &inner) - return &inner, err + inner = new(BlobTx) default: return nil, ErrTxTypeNotSupported } + err := inner.decode(b[1:]) + return inner, err }   // setDecoded sets the inner transaction and size after decoding. @@ -288,15 +297,6 @@ // GasFeeCap returns the fee cap per gas of the transaction. func (tx *Transaction) GasFeeCap() *big.Int { return new(big.Int).Set(tx.inner.gasFeeCap()) }   -// BlobGas returns the blob gas limit of the transaction for blob transactions, 0 otherwise. -func (tx *Transaction) BlobGas() uint64 { return tx.inner.blobGas() } - -// BlobGasFeeCap returns the blob gas fee cap per blob gas of the transaction for blob transactions, nil otherwise. -func (tx *Transaction) BlobGasFeeCap() *big.Int { return tx.inner.blobGasFeeCap() } - -// BlobHashes returns the hases of the blob commitments for blob transactions, nil otherwise. -func (tx *Transaction) BlobHashes() []common.Hash { return tx.inner.blobHashes() } - // Value returns the ether amount of the transaction. func (tx *Transaction) Value() *big.Int { return new(big.Int).Set(tx.inner.value()) }   @@ -383,14 +383,66 @@ } return tx.EffectiveGasTipValue(baseFee).Cmp(other) }   +// BlobGas returns the blob gas limit of the transaction for blob transactions, 0 otherwise. +func (tx *Transaction) BlobGas() uint64 { + if blobtx, ok := tx.inner.(*BlobTx); ok { + return blobtx.blobGas() + } + return 0 +} + +// BlobGasFeeCap returns the blob gas fee cap per blob gas of the transaction for blob transactions, nil otherwise. +func (tx *Transaction) BlobGasFeeCap() *big.Int { + if blobtx, ok := tx.inner.(*BlobTx); ok { + return blobtx.BlobFeeCap.ToBig() + } + return nil +} + +// BlobHashes returns the hashes of the blob commitments for blob transactions, nil otherwise. +func (tx *Transaction) BlobHashes() []common.Hash { + if blobtx, ok := tx.inner.(*BlobTx); ok { + return blobtx.BlobHashes + } + return nil +} + +// BlobTxSidecar returns the sidecar of a blob transaction, nil otherwise. +func (tx *Transaction) BlobTxSidecar() *BlobTxSidecar { + if blobtx, ok := tx.inner.(*BlobTx); ok { + return blobtx.Sidecar + } + return nil +} + // BlobGasFeeCapCmp compares the blob fee cap of two transactions. func (tx *Transaction) BlobGasFeeCapCmp(other *Transaction) int { - return tx.inner.blobGasFeeCap().Cmp(other.inner.blobGasFeeCap()) + return tx.BlobGasFeeCap().Cmp(other.BlobGasFeeCap()) }   // BlobGasFeeCapIntCmp compares the blob fee cap of the transaction against the given blob fee cap. func (tx *Transaction) BlobGasFeeCapIntCmp(other *big.Int) int { - return tx.inner.blobGasFeeCap().Cmp(other) + return tx.BlobGasFeeCap().Cmp(other) +} + +// WithoutBlobTxSidecar returns a copy of tx with the blob sidecar removed. +func (tx *Transaction) WithoutBlobTxSidecar() *Transaction { + blobtx, ok := tx.inner.(*BlobTx) + if !ok { + return tx + } + cpy := &Transaction{ + inner: blobtx.withoutSidecar(), + time: tx.time, + } + // Note: tx.size cache not carried over because the sidecar is included in size! + if h := tx.hash.Load(); h != nil { + cpy.hash.Store(h) + } + if f := tx.from.Load(); f != nil { + cpy.from.Store(f) + } + return cpy }   // SetTime sets the decoding time of a transaction. This is used by tests to set @@ -428,13 +480,24 @@ func (tx *Transaction) Size() uint64 { if size := tx.size.Load(); size != nil { return size.(uint64) } + + // Cache miss, encode and cache. + // Note we rely on the assumption that all tx.inner values are RLP-encoded! c := writeCounter(0) rlp.Encode(&c, &tx.inner) + size := uint64(c)   - size := uint64(c) + // For blob transactions, add the size of the blob content and the outer list of the + // tx + sidecar encoding. + if sc := tx.BlobTxSidecar(); sc != nil { + size += rlp.ListSize(sc.encodedSize()) + } + + // For typed transactions, the encoding also includes the leading type byte. if tx.Type() != LegacyTxType { - size += 1 // type byte + size += 1 } + tx.size.Store(size) return size }
diff --git ethereum/go-ethereum/core/types/block.go taikoxyz/taiko-geth/core/types/block.go index 1b5c7fc8f90e07c58e9c9878c72225a793998cc7..1a357baa3a4152470233bec308804044ce37c76b 100644 --- ethereum/go-ethereum/core/types/block.go +++ taikoxyz/taiko-geth/core/types/block.go @@ -90,6 +90,9 @@ BlobGasUsed *uint64 `json:"blobGasUsed" rlp:"optional"`   // ExcessBlobGas was added by EIP-4844 and is ignored in legacy headers. ExcessBlobGas *uint64 `json:"excessBlobGas" rlp:"optional"` + + // ParentBeaconRoot was added by EIP-4788 and is ignored in legacy headers. + ParentBeaconRoot *common.Hash `json:"parentBeaconBlockRoot" rlp:"optional"` }   // field type overrides for gencodec @@ -297,6 +300,10 @@ if h.BlobGasUsed != nil { cpy.BlobGasUsed = new(uint64) *cpy.BlobGasUsed = *h.BlobGasUsed } + if h.ParentBeaconRoot != nil { + cpy.ParentBeaconRoot = new(common.Hash) + *cpy.ParentBeaconRoot = *h.ParentBeaconRoot + } return &cpy }   @@ -375,6 +382,8 @@ return nil } return new(big.Int).Set(b.header.BaseFee) } + +func (b *Block) BeaconRoot() *common.Hash { return b.header.ParentBeaconRoot }   func (b *Block) ExcessBlobGas() *uint64 { var excessBlobGas *uint64
diff --git ethereum/go-ethereum/core/rawdb/accessors_sync.go taikoxyz/taiko-geth/core/rawdb/accessors_sync.go index e87ad43c3600da999482f93820d09a1ffbd0564f..2dc08b3b72858d84e19e3827ee4d1db183b35f0e 100644 --- ethereum/go-ethereum/core/rawdb/accessors_sync.go +++ taikoxyz/taiko-geth/core/rawdb/accessors_sync.go @@ -17,8 +17,6 @@ package rawdb   import ( - "bytes" - "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/ethdb" "github.com/ethereum/go-ethereum/log" @@ -53,7 +51,7 @@ if len(data) == 0 { return nil } header := new(types.Header) - if err := rlp.Decode(bytes.NewReader(data), header); err != nil { + if err := rlp.DecodeBytes(data, header); err != nil { log.Error("Invalid skeleton header RLP", "number", number, "err", err) return nil } @@ -78,3 +76,25 @@ if err := db.Delete(skeletonHeaderKey(number)); err != nil { log.Crit("Failed to delete skeleton header", "err", err) } } + +const ( + StateSyncUnknown = uint8(0) // flags the state snap sync is unknown + StateSyncRunning = uint8(1) // flags the state snap sync is not completed yet + StateSyncFinished = uint8(2) // flags the state snap sync is completed +) + +// ReadSnapSyncStatusFlag retrieves the state snap sync status flag. +func ReadSnapSyncStatusFlag(db ethdb.KeyValueReader) uint8 { + blob, err := db.Get(snapSyncStatusFlagKey) + if err != nil || len(blob) != 1 { + return StateSyncUnknown + } + return blob[0] +} + +// WriteSnapSyncStatusFlag stores the state snap sync status flag into database. +func WriteSnapSyncStatusFlag(db ethdb.KeyValueWriter, flag uint8) { + if err := db.Put(snapSyncStatusFlagKey, []byte{flag}); err != nil { + log.Crit("Failed to store sync status flag", "err", err) + } +}
diff --git ethereum/go-ethereum/core/txpool/errors.go taikoxyz/taiko-geth/core/txpool/errors.go index bc26550f78ca27a90e41286f77d1dfe3d1a774b1..61daa999ffdc0d0c1631d9d3a5e62071a6265541 100644 --- ethereum/go-ethereum/core/txpool/errors.go +++ taikoxyz/taiko-geth/core/txpool/errors.go @@ -52,6 +52,6 @@ // making the transaction invalid, rather a DOS protection. ErrOversizedData = errors.New("oversized data")   // ErrFutureReplacePending is returned if a future transaction replaces a pending - // transaction. Future transactions should only be able to replace other future transactions. + // one. Future transactions should only be able to replace other future transactions. ErrFutureReplacePending = errors.New("future transaction tries to replace pending") )
diff --git ethereum/go-ethereum/core/rawdb/freezer_table.go taikoxyz/taiko-geth/core/rawdb/freezer_table.go index fc6316c95395c0f1c7fc1fc43aa75e6ee02c8b38..cb32d61ae8a90ecc2e1f8bd0ac346c69214cad84 100644 --- ethereum/go-ethereum/core/rawdb/freezer_table.go +++ taikoxyz/taiko-geth/core/rawdb/freezer_table.go @@ -212,6 +212,9 @@ } } // Ensure the index is a multiple of indexEntrySize bytes if overflow := stat.Size() % indexEntrySize; overflow != 0 { + if t.readonly { + return fmt.Errorf("index file(path: %s, name: %s) size is not a multiple of %d", t.path, t.name, indexEntrySize) + } truncateFreezerFile(t.index, stat.Size()-overflow) // New file can't trigger this path } // Retrieve the file sizes and prepare for truncation @@ -270,6 +273,9 @@ // Keep truncating both files until they come in sync contentExp = int64(lastIndex.offset) for contentExp != contentSize { + if t.readonly { + return fmt.Errorf("freezer table(path: %s, name: %s, num: %d) is corrupted", t.path, t.name, lastIndex.filenum) + } verbose = true // Truncate the head file to the last offset pointer if contentExp < contentSize {
diff --git ethereum/go-ethereum/core/txpool/validation.go taikoxyz/taiko-geth/core/txpool/validation.go index e1c0f314c789ee2da09c6fe32508b924c8c1309b..a96ef13e06817ec38f8b4081aa46580aac203ed0 100644 --- ethereum/go-ethereum/core/txpool/validation.go +++ taikoxyz/taiko-geth/core/txpool/validation.go @@ -18,8 +18,10 @@ package txpool   import ( "crypto/sha256" + "errors" "fmt" "math/big" + "os"   "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/core" @@ -46,7 +48,7 @@ // (balance, nonce, etc). // // This check is public to allow different transaction pools to check the basic // rules without duplicating code and running the risk of missed updates. -func ValidateTransaction(tx *types.Transaction, blobs []kzg4844.Blob, commits []kzg4844.Commitment, proofs []kzg4844.Proof, head *types.Header, signer types.Signer, opts *ValidationOptions) error { +func ValidateTransaction(tx *types.Transaction, head *types.Header, signer types.Signer, opts *ValidationOptions) error { // Ensure transactions not implemented by the calling pool are rejected if opts.Accept&(1<<tx.Type()) == 0 { return fmt.Errorf("%w: tx type %v not supported by this pool", core.ErrTxTypeNotSupported, tx.Type()) @@ -90,6 +92,10 @@ // Ensure gasFeeCap is greater than or equal to gasTipCap if tx.GasFeeCapIntCmp(tx.GasTipCap()) < 0 { return core.ErrTipAboveFeeCap } + // CHANGE(taiko): ensure gasFeeCap fee cap is not zero + if os.Getenv("TAIKO_TEST") == "" && tx.GasFeeCap().Cmp(common.Big0) == 0 { + return errors.New("max fee per gas is zero") + } // Make sure the transaction is signed properly if _, err := types.Sender(signer, tx); err != nil { return ErrInvalidSender @@ -110,46 +116,57 @@ return fmt.Errorf("%w: tip needed %v, tip permitted %v", ErrUnderpriced, opts.MinTip, tx.GasTipCap()) } // Ensure blob transactions have valid commitments if tx.Type() == types.BlobTxType { - // Ensure the number of items in the blob transaction and vairous side + sidecar := tx.BlobTxSidecar() + if sidecar == nil { + return fmt.Errorf("missing sidecar in blob transaction") + } + // Ensure the number of items in the blob transaction and various side // data match up before doing any expensive validations hashes := tx.BlobHashes() if len(hashes) == 0 { return fmt.Errorf("blobless blob transaction") } - if len(hashes) > params.BlobTxMaxBlobGasPerBlock/params.BlobTxBlobGasPerBlob { - return fmt.Errorf("too many blobs in transaction: have %d, permitted %d", len(hashes), params.BlobTxMaxBlobGasPerBlock/params.BlobTxBlobGasPerBlob) + if len(hashes) > params.MaxBlobGasPerBlock/params.BlobTxBlobGasPerBlob { + return fmt.Errorf("too many blobs in transaction: have %d, permitted %d", len(hashes), params.MaxBlobGasPerBlock/params.BlobTxBlobGasPerBlob) } - if len(blobs) != len(hashes) { - return fmt.Errorf("invalid number of %d blobs compared to %d blob hashes", len(blobs), len(hashes)) + if err := validateBlobSidecar(hashes, sidecar); err != nil { + return err } - if len(commits) != len(hashes) { - return fmt.Errorf("invalid number of %d blob commitments compared to %d blob hashes", len(commits), len(hashes)) - } - if len(proofs) != len(hashes) { - return fmt.Errorf("invalid number of %d blob proofs compared to %d blob hashes", len(proofs), len(hashes)) - } - // Blob quantities match up, validate that the provers match with the - // transaction hash before getting to the cryptography - hasher := sha256.New() - for i, want := range hashes { - hasher.Write(commits[i][:]) - hash := hasher.Sum(nil) - hasher.Reset() + } + return nil +} + +func validateBlobSidecar(hashes []common.Hash, sidecar *types.BlobTxSidecar) error { + if len(sidecar.Blobs) != len(hashes) { + return fmt.Errorf("invalid number of %d blobs compared to %d blob hashes", len(sidecar.Blobs), len(hashes)) + } + if len(sidecar.Commitments) != len(hashes) { + return fmt.Errorf("invalid number of %d blob commitments compared to %d blob hashes", len(sidecar.Commitments), len(hashes)) + } + if len(sidecar.Proofs) != len(hashes) { + return fmt.Errorf("invalid number of %d blob proofs compared to %d blob hashes", len(sidecar.Proofs), len(hashes)) + } + // Blob quantities match up, validate that the provers match with the + // transaction hash before getting to the cryptography + hasher := sha256.New() + for i, want := range hashes { + hasher.Write(sidecar.Commitments[i][:]) + hash := hasher.Sum(nil) + hasher.Reset()   - var vhash common.Hash - vhash[0] = params.BlobTxHashVersion - copy(vhash[1:], hash[1:]) + var vhash common.Hash + vhash[0] = params.BlobTxHashVersion + copy(vhash[1:], hash[1:])   - if vhash != want { - return fmt.Errorf("blob %d: computed hash %#x mismatches transaction one %#x", i, vhash, want) - } + if vhash != want { + return fmt.Errorf("blob %d: computed hash %#x mismatches transaction one %#x", i, vhash, want) } - // Blob commitments match with the hashes in the transaction, verify the - // blobs themselves via KZG - for i := range blobs { - if err := kzg4844.VerifyBlobProof(blobs[i], commits[i], proofs[i]); err != nil { - return fmt.Errorf("invalid blob %d: %v", i, err) - } + } + // Blob commitments match with the hashes in the transaction, verify the + // blobs themselves via KZG + for i := range sidecar.Blobs { + if err := kzg4844.VerifyBlobProof(sidecar.Blobs[i], sidecar.Commitments[i], sidecar.Proofs[i]); err != nil { + return fmt.Errorf("invalid blob %d: %v", i, err) } } return nil @@ -171,7 +188,7 @@ // used and the number still permitted for an account. New transactions will // be rejected once the number of remaining slots reaches zero. UsedAndLeftSlots func(addr common.Address) (int, int)   - // ExistingExpenditure is a mandatory callback to retrieve the cummulative + // ExistingExpenditure is a mandatory callback to retrieve the cumulative // cost of the already pooled transactions to check for overdrafts. ExistingExpenditure func(addr common.Address) *big.Int   @@ -226,7 +243,7 @@ if balance.Cmp(need) < 0 { return fmt.Errorf("%w: balance %v, queued cost %v, tx cost %v, overshot %v", core.ErrInsufficientFunds, balance, spent, cost, new(big.Int).Sub(need, balance)) } // Transaction takes a new nonce value out of the pool. Ensure it doesn't - // overflow the number of permitted transactions from a single accoun + // overflow the number of permitted transactions from a single account // (i.e. max cancellable via out-of-bound transaction). if used, left := opts.UsedAndLeftSlots(from); left <= 0 { return fmt.Errorf("%w: pooled %d txs", ErrAccountLimitExceeded, used)
diff --git ethereum/go-ethereum/core/bloombits/matcher_test.go taikoxyz/taiko-geth/core/bloombits/matcher_test.go index 36764c3f174b421cd52a1f0daa15009c1bce31e1..7f3d5f279ca389623e5bbd3933e92c11a1a4803e 100644 --- ethereum/go-ethereum/core/bloombits/matcher_test.go +++ taikoxyz/taiko-geth/core/bloombits/matcher_test.go @@ -85,7 +85,7 @@ } }   // Tests that the matcher can properly find matches if the starting block is -// shifter from a multiple of 8. This is needed to cover an optimisation with +// shifted from a multiple of 8. This is needed to cover an optimisation with // bitset matching https://github.com/ethereum/go-ethereum/issues/15309. func TestMatcherShifted(t *testing.T) { t.Parallel() @@ -106,7 +106,7 @@ t.Parallel() testMatcherBothModes(t, nil, 0, 10000, 0) }   -// makeRandomIndexes generates a random filter system, composed on multiple filter +// makeRandomIndexes generates a random filter system, composed of multiple filter // criteria, each having one bloom list component for the address and arbitrarily // many topic bloom list components. func makeRandomIndexes(lengths []int, max int) [][]bloomIndexes {

This shows changes to eth files.

This is our API backend, it handles l2 node related RPC calls.

diff --git ethereum/go-ethereum/eth/taiko_api_backend.go taikoxyz/taiko-geth/eth/taiko_api_backend.go new file mode 100644 index 0000000000000000000000000000000000000000..49e8580b664fe7c9a43be5493942ee1d2345817f --- /dev/null +++ taikoxyz/taiko-geth/eth/taiko_api_backend.go @@ -0,0 +1,91 @@ +package eth + +import ( + "math/big" + + "github.com/ethereum/go-ethereum" + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/common/math" + "github.com/ethereum/go-ethereum/core/rawdb" + "github.com/ethereum/go-ethereum/core/types" + "github.com/ethereum/go-ethereum/log" +) + +// TaikoAPIBackend handles l2 node related RPC calls. +type TaikoAPIBackend struct { + eth *Ethereum +} + +// NewTaikoAPIBackend creates a new TaikoAPIBackend instance. +func NewTaikoAPIBackend(eth *Ethereum) *TaikoAPIBackend { + return &TaikoAPIBackend{ + eth: eth, + } +} + +// HeadL1Origin returns the latest L2 block's corresponding L1 origin. +func (s *TaikoAPIBackend) HeadL1Origin() (*rawdb.L1Origin, error) { + blockID, err := rawdb.ReadHeadL1Origin(s.eth.ChainDb()) + if err != nil { + return nil, err + } + + if blockID == nil { + return nil, ethereum.NotFound + } + + l1Origin, err := rawdb.ReadL1Origin(s.eth.ChainDb(), blockID) + if err != nil { + return nil, err + } + + if l1Origin == nil { + return nil, ethereum.NotFound + } + + return l1Origin, nil +} + +// L1OriginByID returns the L2 block's corresponding L1 origin. +func (s *TaikoAPIBackend) L1OriginByID(blockID *math.HexOrDecimal256) (*rawdb.L1Origin, error) { + l1Origin, err := rawdb.ReadL1Origin(s.eth.ChainDb(), (*big.Int)(blockID)) + if err != nil { + return nil, err + } + + if l1Origin == nil { + return nil, ethereum.NotFound + } + + return l1Origin, nil +} + +// TxPoolContent retrieves the transaction pool content with the given upper limits. +func (s *TaikoAPIBackend) TxPoolContent( + beneficiary common.Address, + baseFee *big.Int, + maxTransactionsPerBlock uint64, + blockMaxGasLimit uint64, + maxBytesPerTxList uint64, + locals []string, + maxTransactionsLists uint64, +) ([]types.Transactions, error) { + log.Info( + "Fetching L2 pending transactions finished", + "maxTransactionsPerBlock", maxTransactionsPerBlock, + "blockMaxGasLimit", blockMaxGasLimit, + "maxBytesPerTxList", maxBytesPerTxList, + "maxTransactions", maxTransactionsLists, + "locals", locals, + ) + + return s.eth.Miner().BuildTransactionsLists( + beneficiary, + baseFee, + maxTransactionsPerBlock, + blockMaxGasLimit, + maxBytesPerTxList, + locals, + maxTransactionsLists, + ) +}
diff --git ethereum/go-ethereum/eth/api_debug.go taikoxyz/taiko-geth/eth/api_debug.go index 9cfa9103fb58c9ddaa77622a9f6ae80fde6ec2a0..dc9f56814699fcb26388741e29bd725cf0bcf225 100644 --- ethereum/go-ethereum/eth/api_debug.go +++ taikoxyz/taiko-geth/eth/api_debug.go @@ -27,6 +27,7 @@ "github.com/ethereum/go-ethereum/common/hexutil" "github.com/ethereum/go-ethereum/core/rawdb" "github.com/ethereum/go-ethereum/core/state" "github.com/ethereum/go-ethereum/core/types" + "github.com/ethereum/go-ethereum/crypto" "github.com/ethereum/go-ethereum/internal/ethapi" "github.com/ethereum/go-ethereum/log" "github.com/ethereum/go-ethereum/rlp" @@ -216,7 +217,6 @@ block, err := api.eth.APIBackend.BlockByNumberOrHash(ctx, blockNrOrHash) if err != nil { return StorageRangeResult{}, err } - if block == nil { return StorageRangeResult{}, fmt.Errorf("block %v not found", blockNrOrHash) } @@ -226,18 +226,20 @@ return StorageRangeResult{}, err } defer release()   - st, err := statedb.StorageTrie(contractAddress) + return storageRangeAt(statedb, block.Root(), contractAddress, keyStart, maxResult) +} + +func storageRangeAt(statedb *state.StateDB, root common.Hash, address common.Address, start []byte, maxResult int) (StorageRangeResult, error) { + storageRoot := statedb.GetStorageRoot(address) + if storageRoot == types.EmptyRootHash || storageRoot == (common.Hash{}) { + return StorageRangeResult{}, nil // empty storage + } + id := trie.StorageTrieID(root, crypto.Keccak256Hash(address.Bytes()), storageRoot) + tr, err := trie.NewStateTrie(id, statedb.Database().TrieDB()) if err != nil { return StorageRangeResult{}, err } - if st == nil { - return StorageRangeResult{}, fmt.Errorf("account %x doesn't exist", contractAddress) - } - return storageRangeAt(st, keyStart, maxResult) -} - -func storageRangeAt(st state.Trie, start []byte, maxResult int) (StorageRangeResult, error) { - trieIt, err := st.NodeIterator(start) + trieIt, err := tr.NodeIterator(start) if err != nil { return StorageRangeResult{}, err } @@ -249,7 +251,7 @@ if err != nil { return StorageRangeResult{}, err } e := storageEntry{Value: common.BytesToHash(content)} - if preimage := st.GetKey(it.Key); preimage != nil { + if preimage := tr.GetKey(it.Key); preimage != nil { preimage := common.BytesToHash(preimage) e.Key = &preimage } @@ -322,7 +324,7 @@ func (api *DebugAPI) getModifiedAccounts(startBlock, endBlock *types.Block) ([]common.Address, error) { if startBlock.Number().Uint64() >= endBlock.Number().Uint64() { return nil, fmt.Errorf("start block height (%d) must be less than end block height (%d)", startBlock.Number().Uint64(), endBlock.Number().Uint64()) } - triedb := api.eth.BlockChain().StateCache().TrieDB() + triedb := api.eth.BlockChain().TrieDB()   oldTrie, err := trie.NewStateTrie(trie.StateTrieID(startBlock.Root()), triedb) if err != nil { @@ -360,6 +362,9 @@ // of the next block. // The (from, to) parameters are the sequence of blocks to search, which can go // either forwards or backwards func (api *DebugAPI) GetAccessibleState(from, to rpc.BlockNumber) (uint64, error) { + if api.eth.blockchain.TrieDB().Scheme() == rawdb.PathScheme { + return 0, errors.New("state history is not yet available in path-based scheme") + } db := api.eth.ChainDb() var pivot uint64 if p := rawdb.ReadLastPivotNumber(db); p != nil { @@ -420,6 +425,9 @@ // to disk. The value is in terms of block processing time, not wall clock. // If the value is shorter than the block generation time, or even 0 or negative, // the node will flush trie after processing each block (effectively archive mode). func (api *DebugAPI) SetTrieFlushInterval(interval string) error { + if api.eth.blockchain.TrieDB().Scheme() == rawdb.PathScheme { + return errors.New("trie flush interval is undefined for path-based scheme") + } t, err := time.ParseDuration(interval) if err != nil { return err @@ -429,6 +437,9 @@ return nil }   // GetTrieFlushInterval gets the current value of in-memory trie flush interval -func (api *DebugAPI) GetTrieFlushInterval() string { - return api.eth.blockchain.GetTrieFlushInterval().String() +func (api *DebugAPI) GetTrieFlushInterval() (string, error) { + if api.eth.blockchain.TrieDB().Scheme() == rawdb.PathScheme { + return "", errors.New("trie flush interval is undefined for path-based scheme") + } + return api.eth.blockchain.GetTrieFlushInterval().String(), nil }
diff --git ethereum/go-ethereum/eth/api_admin.go taikoxyz/taiko-geth/eth/api_admin.go index 88d8f5a14d857bd609e537eccb0dbb933bd803f5..4a3ccb84e82dcf004b92e5a53dce42e8fed78e4a 100644 --- ethereum/go-ethereum/eth/api_admin.go +++ taikoxyz/taiko-geth/eth/api_admin.go @@ -118,6 +118,10 @@ break } else if err != nil { return false, fmt.Errorf("block %d: failed to parse: %v", index, err) } + // ignore the genesis block when importing blocks + if block.NumberU64() == 0 { + continue + } blocks = append(blocks, block) index++ }
diff --git ethereum/go-ethereum/eth/api_backend.go taikoxyz/taiko-geth/eth/api_backend.go index 30e2493684109cee50a98e1d92534f86cfa9ba64..601e5551585724b2d7d28c5295bd3b271037d821 100644 --- ethereum/go-ethereum/eth/api_backend.go +++ taikoxyz/taiko-geth/eth/api_backend.go @@ -78,24 +78,18 @@ if number == rpc.LatestBlockNumber { return b.eth.blockchain.CurrentBlock(), nil } if number == rpc.FinalizedBlockNumber { - if !b.eth.Merger().TDDReached() { - return nil, errors.New("'finalized' tag not supported on pre-merge network") - } block := b.eth.blockchain.CurrentFinalBlock() - if block != nil { - return block, nil + if block == nil { + return nil, errors.New("finalized block not found") } - return nil, errors.New("finalized block not found") + return block, nil } if number == rpc.SafeBlockNumber { - if !b.eth.Merger().TDDReached() { - return nil, errors.New("'safe' tag not supported on pre-merge network") - } block := b.eth.blockchain.CurrentSafeBlock() - if block != nil { - return block, nil + if block == nil { + return nil, errors.New("safe block not found") } - return nil, errors.New("safe block not found") + return block, nil } return b.eth.blockchain.GetHeaderByNumber(uint64(number)), nil } @@ -136,9 +130,6 @@ header := b.eth.blockchain.CurrentBlock() return b.eth.blockchain.GetBlock(header.Hash(), header.Number.Uint64()), nil } if number == rpc.FinalizedBlockNumber { - if !b.eth.Merger().TDDReached() { - return nil, errors.New("'finalized' tag not supported on pre-merge network") - } header := b.eth.blockchain.CurrentFinalBlock() if header == nil { return nil, errors.New("finalized block not found") @@ -146,9 +137,6 @@ } return b.eth.blockchain.GetBlock(header.Hash(), header.Number.Uint64()), nil } if number == rpc.SafeBlockNumber { - if !b.eth.Merger().TDDReached() { - return nil, errors.New("'safe' tag not supported on pre-merge network") - } header := b.eth.blockchain.CurrentSafeBlock() if header == nil { return nil, errors.New("safe block not found") @@ -216,7 +204,10 @@ if header == nil { return nil, nil, errors.New("header not found") } stateDb, err := b.eth.BlockChain().StateAt(header.Root) - return stateDb, header, err + if err != nil { + return nil, nil, err + } + return stateDb, header, nil }   func (b *EthAPIBackend) StateAndHeaderByNumberOrHash(ctx context.Context, blockNrOrHash rpc.BlockNumberOrHash) (*state.StateDB, *types.Header, error) { @@ -235,7 +226,10 @@ if blockNrOrHash.RequireCanonical && b.eth.blockchain.GetCanonicalHash(header.Number.Uint64()) != hash { return nil, nil, errors.New("hash is not currently canonical") } stateDb, err := b.eth.BlockChain().StateAt(header.Root) - return stateDb, header, err + if err != nil { + return nil, nil, err + } + return stateDb, header, nil } return nil, nil, errors.New("invalid arguments; neither block nor hash specified") } @@ -245,7 +239,7 @@ return b.eth.blockchain.GetReceiptsByHash(hash), nil }   func (b *EthAPIBackend) GetLogs(ctx context.Context, hash common.Hash, number uint64) ([][]*types.Log, error) { - return rawdb.ReadLogs(b.eth.chainDb, hash, number, b.ChainConfig()), nil + return rawdb.ReadLogs(b.eth.chainDb, hash, number), nil }   func (b *EthAPIBackend) GetTd(ctx context.Context, hash common.Hash) *big.Int { @@ -294,7 +288,7 @@ return b.eth.BlockChain().SubscribeLogsEvent(ch) }   func (b *EthAPIBackend) SendTx(ctx context.Context, signedTx *types.Transaction) error { - return b.eth.txPool.Add([]*txpool.Transaction{{Tx: signedTx}}, true, false)[0] + return b.eth.txPool.Add([]*types.Transaction{signedTx}, true, false)[0] }   func (b *EthAPIBackend) GetPoolTransactions() (types.Transactions, error) { @@ -303,7 +297,7 @@ var txs types.Transactions for _, batch := range pending { for _, lazy := range batch { if tx := lazy.Resolve(); tx != nil { - txs = append(txs, tx.Tx) + txs = append(txs, tx) } } } @@ -311,10 +305,7 @@ return txs, nil }   func (b *EthAPIBackend) GetPoolTransaction(hash common.Hash) *types.Transaction { - if tx := b.eth.txPool.Get(hash); tx != nil { - return tx.Tx - } - return nil + return b.eth.txPool.Get(hash) }   func (b *EthAPIBackend) GetTransaction(ctx context.Context, txHash common.Hash) (*types.Transaction, common.Hash, uint64, uint64, error) { @@ -343,7 +334,7 @@ return b.eth.txPool }   func (b *EthAPIBackend) SubscribeNewTxsEvent(ch chan<- core.NewTxsEvent) event.Subscription { - return b.eth.txPool.SubscribeNewTxsEvent(ch) + return b.eth.txPool.SubscribeTransactions(ch, true) }   func (b *EthAPIBackend) SyncProgress() ethereum.SyncProgress { @@ -418,7 +409,7 @@ return b.eth.StartMining() }   func (b *EthAPIBackend) StateAtBlock(ctx context.Context, block *types.Block, reexec uint64, base *state.StateDB, readOnly bool, preferDisk bool) (*state.StateDB, tracers.StateReleaseFunc, error) { - return b.eth.StateAtBlock(ctx, block, reexec, base, readOnly, preferDisk) + return b.eth.stateAtBlock(ctx, block, reexec, base, readOnly, preferDisk) }   func (b *EthAPIBackend) StateAtTransaction(ctx context.Context, block *types.Block, txIndex int, reexec uint64) (*core.Message, vm.BlockContext, *state.StateDB, tracers.StateReleaseFunc, error) {
diff --git ethereum/go-ethereum/eth/handler_eth.go taikoxyz/taiko-geth/eth/handler_eth.go index 3a5e6608bb3638cd852028413abcdcd2f9cfbc97..2a839f615f63be71674a4a55034c14c50b52ea6e 100644 --- ethereum/go-ethereum/eth/handler_eth.go +++ taikoxyz/taiko-geth/eth/handler_eth.go @@ -17,6 +17,7 @@ package eth   import ( + "errors" "fmt" "math/big" "time" @@ -51,7 +52,7 @@ // AcceptTxs retrieves whether transaction processing is enabled on the node // or if inbound transactions should simply be dropped. func (h *ethHandler) AcceptTxs() bool { - return h.acceptTxs.Load() + return h.synced.Load() }   // Handle is invoked from a peer's message handler when it receives a new remote @@ -66,16 +67,21 @@ case *eth.NewBlockPacket: return h.handleBlockBroadcast(peer, packet.Block, packet.TD)   - case *eth.NewPooledTransactionHashesPacket66: - return h.txFetcher.Notify(peer.ID(), *packet) + case *eth.NewPooledTransactionHashesPacket67: + return h.txFetcher.Notify(peer.ID(), nil, nil, *packet)   case *eth.NewPooledTransactionHashesPacket68: - return h.txFetcher.Notify(peer.ID(), packet.Hashes) + return h.txFetcher.Notify(peer.ID(), packet.Types, packet.Sizes, packet.Hashes)   case *eth.TransactionsPacket: + for _, tx := range *packet { + if tx.Type() == types.BlobTxType { + return errors.New("disallowed broadcast blob transaction") + } + } return h.txFetcher.Enqueue(peer.ID(), *packet, false)   - case *eth.PooledTransactionsPacket: + case *eth.PooledTransactionsResponse: return h.txFetcher.Enqueue(peer.ID(), *packet, true)   default: @@ -90,9 +96,7 @@ // Drop all incoming block announces from the p2p network if // the chain already entered the pos stage and disconnect the // remote peer. if h.merger.PoSFinalized() { - // TODO (MariusVanDerWijden) drop non-updated peers after the merge - return nil - // return errors.New("unexpected block announces") + return errors.New("disallowed block announcement") } // Schedule all the unknown hashes for retrieval var ( @@ -118,9 +122,7 @@ // Drop all incoming block announces from the p2p network if // the chain already entered the pos stage and disconnect the // remote peer. if h.merger.PoSFinalized() { - // TODO (MariusVanDerWijden) drop non-updated peers after the merge - return nil - // return errors.New("unexpected block announces") + return errors.New("disallowed block broadcast") } // Schedule the block for import h.blockFetcher.Enqueue(peer.ID(), block)
diff --git ethereum/go-ethereum/eth/handler.go taikoxyz/taiko-geth/eth/handler.go index 2453c08afbc05ca1e44b3143a6225ec017bdf3ee..f0021e56446ce30718de3a1b51b4d60865d5bf9d 100644 --- ethereum/go-ethereum/eth/handler.go +++ taikoxyz/taiko-geth/eth/handler.go @@ -29,6 +29,7 @@ "github.com/ethereum/go-ethereum/consensus" "github.com/ethereum/go-ethereum/consensus/beacon" "github.com/ethereum/go-ethereum/core" "github.com/ethereum/go-ethereum/core/forkid" + "github.com/ethereum/go-ethereum/core/rawdb" "github.com/ethereum/go-ethereum/core/txpool" "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/eth/downloader" @@ -40,6 +41,7 @@ "github.com/ethereum/go-ethereum/event" "github.com/ethereum/go-ethereum/log" "github.com/ethereum/go-ethereum/metrics" "github.com/ethereum/go-ethereum/p2p" + "github.com/ethereum/go-ethereum/trie/triedb/pathdb" )   const ( @@ -53,9 +55,7 @@ // by the peer. txMaxBroadcastSize = 4096 )   -var ( - syncChallengeTimeout = 15 * time.Second // Time allowance for a node to reply to the sync progress challenge -) +var syncChallengeTimeout = 15 * time.Second // Time allowance for a node to reply to the sync progress challenge   // txPool defines the methods needed from a transaction pool implementation to // support all the operations needed by the Ethereum chain protocols. @@ -66,18 +66,19 @@ Has(hash common.Hash) bool   // Get retrieves the transaction from local txpool with given // tx hash. - Get(hash common.Hash) *txpool.Transaction + Get(hash common.Hash) *types.Transaction   // Add should add the given transactions to the pool. - Add(txs []*txpool.Transaction, local bool, sync bool) []error + Add(txs []*types.Transaction, local bool, sync bool) []error   // Pending should return pending transactions. // The slice should be modifiable by the caller. Pending(enforceTips bool) map[common.Address][]*txpool.LazyTransaction   - // SubscribeNewTxsEvent should return an event subscription of - // NewTxsEvent and send events to the given channel. - SubscribeNewTxsEvent(chan<- core.NewTxsEvent) event.Subscription + // SubscribeTransactions subscribes to new transaction events. The subscriber + // can decide whether to receive notifications only for newly seen transactions + // or also for reorged out ones. + SubscribeTransactions(ch chan<- core.NewTxsEvent, reorgs bool) event.Subscription }   // handlerConfig is the collection of initialization parameters to create a full @@ -87,7 +88,7 @@ Database ethdb.Database // Database for direct sync insertions Chain *core.BlockChain // Blockchain to serve data from TxPool txPool // Transaction pool to propagate from Merger *consensus.Merger // The manager for eth1/2 transition - Network uint64 // Network identifier to adfvertise + Network uint64 // Network identifier to advertise Sync downloader.SyncMode // Whether to snap or full sync BloomCache uint64 // Megabytes to alloc for snap sync bloom EventMux *event.TypeMux // Legacy event mux, deprecate for `feed` @@ -98,8 +99,8 @@ type handler struct { networkID uint64 forkFilter forkid.Filter // Fork ID filter, constant across the lifetime of the node   - snapSync atomic.Bool // Flag whether snap sync is enabled (gets disabled if we already have blocks) - acceptTxs atomic.Bool // Flag whether we're considered synchronised (enables transaction processing) + snapSync atomic.Bool // Flag whether snap sync is enabled (gets disabled if we already have blocks) + synced atomic.Bool // Flag whether we're considered synchronised (enables transaction processing)   database ethdb.Database txpool txPool @@ -161,32 +162,24 @@ // In these cases however it's safe to reenable snap sync. fullBlock, snapBlock := h.chain.CurrentBlock(), h.chain.CurrentSnapBlock() if fullBlock.Number.Uint64() == 0 && snapBlock.Number.Uint64() > 0 { h.snapSync.Store(true) - log.Warn("Switch sync mode from full sync to snap sync") + log.Warn("Switch sync mode from full sync to snap sync", "reason", "snap sync incomplete") + } else if !h.chain.HasState(fullBlock.Root) { + h.snapSync.Store(true) + log.Warn("Switch sync mode from full sync to snap sync", "reason", "head state missing") } } else { - if h.chain.CurrentBlock().Number.Uint64() > 0 { + head := h.chain.CurrentBlock() + if head.Number.Uint64() > 0 && h.chain.HasState(head.Root) { // Print warning log if database is not empty to run snap sync. - log.Warn("Switch sync mode from snap sync to full sync") + log.Warn("Switch sync mode from snap sync to full sync", "reason", "snap sync complete") } else { // If snap sync was requested and our database is empty, grant it h.snapSync.Store(true) - } - } - // If sync succeeds, pass a callback to potentially disable snap sync mode - // and enable transaction propagation. - success := func() { - // If we were running snap sync and it finished, disable doing another - // round on next sync cycle - if h.snapSync.Load() { - log.Info("Snap sync complete, auto disabling") - h.snapSync.Store(false) + log.Info("Enabled snap sync", "head", head.Number, "hash", head.Hash()) } - // If we've successfully finished a sync cycle, accept transactions from - // the network - h.acceptTxs.Store(true) } // Construct the downloader (long sync) - h.downloader = downloader.New(config.Database, h.eventMux, h.chain, nil, h.removePeer, success) + h.downloader = downloader.New(config.Database, h.eventMux, h.chain, nil, h.removePeer, h.enableSyncedFeatures) if ttd := h.chain.Config().TerminalTotalDifficulty; ttd != nil { if h.chain.Config().TerminalTotalDifficultyPassed { log.Info("Chain post-merge, sync via beacon client") @@ -243,8 +236,8 @@ // clause when starting up a new network, because snap-syncing miners might not // accept each others' blocks until a restart. Unfortunately we haven't figured // out a way yet where nodes can decide unilaterally whether the network is new // or not. This should be fixed if we figure out a solution. - if h.snapSync.Load() { - log.Warn("Snap syncing, discarded propagated block", "number", blocks[0].Number(), "hash", blocks[0].Hash()) + if !h.synced.Load() { + log.Warn("Syncing, discarded propagated block", "number", blocks[0].Number(), "hash", blocks[0].Hash()) return 0, nil } if h.merger.TDDReached() { @@ -261,7 +254,7 @@ return 0, nil } td := new(big.Int).Add(ptd, block.Difficulty()) if !h.chain.Config().IsTerminalPoWBlock(ptd, td) { - log.Info("Filtered out non-termimal pow block", "number", block.NumberU64(), "hash", block.Hash()) + log.Info("Filtered out non-terminal pow block", "number", block.NumberU64(), "hash", block.Hash()) return 0, nil } if err := h.chain.InsertBlockWithoutSetHead(block); err != nil { @@ -270,11 +263,7 @@ } } return 0, nil } - n, err := h.chain.InsertChain(blocks) - if err == nil { - h.acceptTxs.Store(true) // Mark initial sync done on any fetcher import - } - return n, err + return h.chain.InsertChain(blocks) } h.blockFetcher = fetcher.NewBlockFetcher(false, nil, h.chain.GetBlockByHash, validator, h.BroadcastBlock, heighter, nil, inserter, h.removePeer)   @@ -285,10 +274,10 @@ return errors.New("unknown peer") } return p.RequestTxs(hashes) } - addTxs := func(txs []*txpool.Transaction) []error { + addTxs := func(txs []*types.Transaction) []error { return h.txpool.Add(txs, false, false) } - h.txFetcher = fetcher.NewTxFetcher(h.txpool.Has, addTxs, fetchTx) + h.txFetcher = fetcher.NewTxFetcher(h.txpool.Has, addTxs, fetchTx, h.removePeer) h.chainSync = newChainSyncer(h) return h, nil } @@ -353,7 +342,7 @@ hash = head.Hash() number = head.Number.Uint64() td = h.chain.GetTd(hash, number) ) - forkID := forkid.NewID(h.chain.Config(), genesis.Hash(), number, head.Time) + forkID := forkid.NewID(h.chain.Config(), genesis, number, head.Time) if err := peer.Handshake(h.networkID, td, hash, genesis.Hash(), forkID, h.forkFilter); err != nil { peer.Log().Debug("Ethereum handshake failed", "err", err) return err @@ -426,7 +415,7 @@ defer timeout.Stop()   select { case res := <-resCh: - headers := ([]*types.Header)(*res.Res.(*eth.BlockHeadersPacket)) + headers := ([]*types.Header)(*res.Res.(*eth.BlockHeadersRequest)) if len(headers) == 0 { // Required blocks are allowed to be missing if the remote // node is not yet synced @@ -473,7 +462,7 @@ } else { snap.EgressRegistrationErrorMeter.Mark(1) } } - peer.Log().Warn("Snapshot extension registration failed", "err", err) + peer.Log().Debug("Snapshot extension registration failed", "err", err) return err } return handler(peer) @@ -521,10 +510,10 @@ func (h *handler) Start(maxPeers int) { h.maxPeers = maxPeers   - // broadcast transactions + // broadcast and announce transactions (only new ones, not resurrected ones) h.wg.Add(1) h.txsCh = make(chan core.NewTxsEvent, txChanSize) - h.txsSub = h.txpool.SubscribeNewTxsEvent(h.txsCh) + h.txsSub = h.txpool.SubscribeTransactions(h.txsCh, false) go h.txBroadcastLoop()   // broadcast mined blocks @@ -604,26 +593,33 @@ } }   // BroadcastTransactions will propagate a batch of transactions -// - To a square root of all peers +// - To a square root of all peers for non-blob transactions // - And, separately, as announcements to all peers which are not known to // already have the given transaction. func (h *handler) BroadcastTransactions(txs types.Transactions) { var ( - annoCount int // Count of announcements made - annoPeers int - directCount int // Count of the txs sent directly to peers - directPeers int // Count of the peers that were sent transactions directly + blobTxs int // Number of blob transactions to announce only + largeTxs int // Number of large transactions to announce only + + directCount int // Number of transactions sent directly to peers (duplicates included) + directPeers int // Number of peers that were sent transactions directly + annCount int // Number of transactions announced across all peers (duplicates included) + annPeers int // Number of peers announced about transactions   txset = make(map[*ethPeer][]common.Hash) // Set peer->hash to transfer directly annos = make(map[*ethPeer][]common.Hash) // Set peer->hash to announce - ) // Broadcast transactions to a batch of peers not knowing about it for _, tx := range txs { peers := h.peers.peersWithoutTransaction(tx.Hash())   var numDirect int - if tx.Size() <= txMaxBroadcastSize { + switch { + case tx.Type() == types.BlobTxType: + blobTxs++ + case tx.Size() > txMaxBroadcastSize: + largeTxs++ + default: numDirect = int(math.Sqrt(float64(len(peers)))) } // Send the tx unconditionally to a subset of our peers @@ -641,13 +637,12 @@ directCount += len(hashes) peer.AsyncSendTransactions(hashes) } for peer, hashes := range annos { - annoPeers++ - annoCount += len(hashes) + annPeers++ + annCount += len(hashes) peer.AsyncSendPooledTransactionHashes(hashes) } - log.Debug("Transaction broadcast", "txs", len(txs), - "announce packs", annoPeers, "announced hashes", annoCount, - "tx packs", directPeers, "broadcast txs", directCount) + log.Debug("Distributed transactions", "plaintxs", len(txs)-blobTxs-largeTxs, "blobtxs", blobTxs, "largetxs", largeTxs, + "bcastpeers", directPeers, "bcastcount", directCount, "annpeers", annPeers, "anncount", annCount) }   // minedBroadcastLoop sends mined blocks to connected peers. @@ -674,3 +669,20 @@ return } } } + +// enableSyncedFeatures enables the post-sync functionalities when the initial +// sync is finished. +func (h *handler) enableSyncedFeatures() { + // Mark the local node as synced. + h.synced.Store(true) + + // If we were running snap sync and it finished, disable doing another + // round on next sync cycle + if h.snapSync.Load() { + log.Info("Snap sync complete, auto disabling") + h.snapSync.Store(false) + } + if h.chain.TrieDB().Scheme() == rawdb.PathScheme { + h.chain.TrieDB().SetBufferSize(pathdb.DefaultBufferSize) + } +}
diff --git ethereum/go-ethereum/eth/sync_test.go taikoxyz/taiko-geth/eth/sync_test.go index b5e00298b9e9fcf7a5291164c1c0c215ec31f9e2..d26cbb66ea6174af8ed8597ef49bf4e2786f4f5a 100644 --- ethereum/go-ethereum/eth/sync_test.go +++ taikoxyz/taiko-geth/eth/sync_test.go @@ -28,8 +28,8 @@ "github.com/ethereum/go-ethereum/p2p/enode" )   // Tests that snap sync is disabled after a successful sync cycle. -func TestSnapSyncDisabling66(t *testing.T) { testSnapSyncDisabling(t, eth.ETH66, snap.SNAP1) } func TestSnapSyncDisabling67(t *testing.T) { testSnapSyncDisabling(t, eth.ETH67, snap.SNAP1) } +func TestSnapSyncDisabling68(t *testing.T) { testSnapSyncDisabling(t, eth.ETH68, snap.SNAP1) }   // Tests that snap sync gets disabled as soon as a real block is successfully // imported into the blockchain.
diff --git ethereum/go-ethereum/eth/handler_eth_test.go taikoxyz/taiko-geth/eth/handler_eth_test.go index a9ce83e2ee4428c029037e100631be69d8567c3a..bb342acc18f7a34dca1408ec22e407c51d56336c 100644 --- ethereum/go-ethereum/eth/handler_eth_test.go +++ taikoxyz/taiko-geth/eth/handler_eth_test.go @@ -28,7 +28,6 @@ "github.com/ethereum/go-ethereum/consensus/ethash" "github.com/ethereum/go-ethereum/core" "github.com/ethereum/go-ethereum/core/forkid" "github.com/ethereum/go-ethereum/core/rawdb" - "github.com/ethereum/go-ethereum/core/txpool" "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/core/vm" "github.com/ethereum/go-ethereum/eth/downloader" @@ -59,7 +58,7 @@ case *eth.NewBlockPacket: h.blockBroadcasts.Send(packet.Block) return nil   - case *eth.NewPooledTransactionHashesPacket66: + case *eth.NewPooledTransactionHashesPacket67: h.txAnnounces.Send(([]common.Hash)(*packet)) return nil   @@ -71,7 +70,7 @@ case *eth.TransactionsPacket: h.txBroadcasts.Send(([]*types.Transaction)(*packet)) return nil   - case *eth.PooledTransactionsPacket: + case *eth.PooledTransactionsResponse: h.txBroadcasts.Send(([]*types.Transaction)(*packet)) return nil   @@ -82,7 +81,6 @@ }   // Tests that peers are correctly accepted (or rejected) based on the advertised // fork IDs in the protocol handshake. -func TestForkIDSplit66(t *testing.T) { testForkIDSplit(t, eth.ETH66) } func TestForkIDSplit67(t *testing.T) { testForkIDSplit(t, eth.ETH67) } func TestForkIDSplit68(t *testing.T) { testForkIDSplit(t, eth.ETH68) }   @@ -238,7 +236,6 @@ } }   // Tests that received transactions are added to the local pool. -func TestRecvTransactions66(t *testing.T) { testRecvTransactions(t, eth.ETH66) } func TestRecvTransactions67(t *testing.T) { testRecvTransactions(t, eth.ETH67) } func TestRecvTransactions68(t *testing.T) { testRecvTransactions(t, eth.ETH68) }   @@ -249,10 +246,10 @@ // Create a message handler, configure it to accept transactions and watch them handler := newTestHandler() defer handler.close()   - handler.handler.acceptTxs.Store(true) // mark synced to accept transactions + handler.handler.synced.Store(true) // mark synced to accept transactions   txs := make(chan core.NewTxsEvent) - sub := handler.txpool.SubscribeNewTxsEvent(txs) + sub := handler.txpool.SubscribeTransactions(txs, false) defer sub.Unsubscribe()   // Create a source peer to send messages through and a sink handler to receive them @@ -297,7 +294,6 @@ } }   // This test checks that pending transactions are sent. -func TestSendTransactions66(t *testing.T) { testSendTransactions(t, eth.ETH66) } func TestSendTransactions67(t *testing.T) { testSendTransactions(t, eth.ETH67) } func TestSendTransactions68(t *testing.T) { testSendTransactions(t, eth.ETH68) }   @@ -308,12 +304,11 @@ // Create a message handler and fill the pool with big transactions handler := newTestHandler() defer handler.close()   - insert := make([]*txpool.Transaction, 100) + insert := make([]*types.Transaction, 100) for nonce := range insert { tx := types.NewTransaction(uint64(nonce), common.Address{}, big.NewInt(0), 100000, big.NewInt(0), make([]byte, 10240)) tx, _ = types.SignTx(tx, types.HomesteadSigner{}, testKey) - - insert[nonce] = &txpool.Transaction{Tx: tx} + insert[nonce] = tx } go handler.txpool.Add(insert, false, false) // Need goroutine to not block on feed time.Sleep(250 * time.Millisecond) // Wait until tx events get out of the system (can't use events, tx broadcaster races with peer join) @@ -358,7 +353,7 @@ // Make sure we get all the transactions on the correct channels seen := make(map[common.Hash]struct{}) for len(seen) < len(insert) { switch protocol { - case 66, 67, 68: + case 67, 68: select { case hashes := <-anns: for _, hash := range hashes { @@ -376,15 +371,14 @@ panic("unsupported protocol, please extend test") } } for _, tx := range insert { - if _, ok := seen[tx.Tx.Hash()]; !ok { - t.Errorf("missing transaction: %x", tx.Tx.Hash()) + if _, ok := seen[tx.Hash()]; !ok { + t.Errorf("missing transaction: %x", tx.Hash()) } } }   // Tests that transactions get propagated to all attached peers, either via direct // broadcasts or via announcements/retrievals. -func TestTransactionPropagation66(t *testing.T) { testTransactionPropagation(t, eth.ETH66) } func TestTransactionPropagation67(t *testing.T) { testTransactionPropagation(t, eth.ETH67) } func TestTransactionPropagation68(t *testing.T) { testTransactionPropagation(t, eth.ETH68) }   @@ -403,7 +397,7 @@ for i := 0; i < len(sinks); i++ { sinks[i] = newTestHandler() defer sinks[i].close()   - sinks[i].handler.acceptTxs.Store(true) // mark synced to accept transactions + sinks[i].handler.synced.Store(true) // mark synced to accept transactions } // Interconnect all the sink handlers with the source handler for i, sink := range sinks { @@ -430,16 +424,15 @@ txChs := make([]chan core.NewTxsEvent, len(sinks)) for i := 0; i < len(sinks); i++ { txChs[i] = make(chan core.NewTxsEvent, 1024)   - sub := sinks[i].txpool.SubscribeNewTxsEvent(txChs[i]) + sub := sinks[i].txpool.SubscribeTransactions(txChs[i], false) defer sub.Unsubscribe() } // Fill the source pool with transactions and wait for them at the sinks - txs := make([]*txpool.Transaction, 1024) + txs := make([]*types.Transaction, 1024) for nonce := range txs { tx := types.NewTransaction(uint64(nonce), common.Address{}, big.NewInt(0), 100000, big.NewInt(0), nil) tx, _ = types.SignTx(tx, types.HomesteadSigner{}, testKey) - - txs[nonce] = &txpool.Transaction{Tx: tx} + txs[nonce] = tx } source.txpool.Add(txs, false, false)   @@ -493,8 +486,8 @@ sourcePipe, sinkPipe := p2p.MsgPipe() defer sourcePipe.Close() defer sinkPipe.Close()   - sourcePeer := eth.NewPeer(eth.ETH66, p2p.NewPeerPipe(enode.ID{byte(i)}, "", nil, sourcePipe), sourcePipe, nil) - sinkPeer := eth.NewPeer(eth.ETH66, p2p.NewPeerPipe(enode.ID{0}, "", nil, sinkPipe), sinkPipe, nil) + sourcePeer := eth.NewPeer(eth.ETH67, p2p.NewPeerPipe(enode.ID{byte(i)}, "", nil, sourcePipe), sourcePipe, nil) + sinkPeer := eth.NewPeer(eth.ETH67, p2p.NewPeerPipe(enode.ID{0}, "", nil, sinkPipe), sinkPipe, nil) defer sourcePeer.Close() defer sinkPeer.Close()   @@ -546,7 +539,6 @@ }   // Tests that a propagated malformed block (uncles or transactions don't match // with the hashes in the header) gets discarded and not broadcast forward. -func TestBroadcastMalformedBlock66(t *testing.T) { testBroadcastMalformedBlock(t, eth.ETH66) } func TestBroadcastMalformedBlock67(t *testing.T) { testBroadcastMalformedBlock(t, eth.ETH67) } func TestBroadcastMalformedBlock68(t *testing.T) { testBroadcastMalformedBlock(t, eth.ETH68) }
diff --git ethereum/go-ethereum/eth/state_accessor.go taikoxyz/taiko-geth/eth/state_accessor.go index a725585e71208725f7d164514019ad3c72be52ed..24694df66c36cd814d2d631368bf29d75cf6d9f6 100644 --- ethereum/go-ethereum/eth/state_accessor.go +++ taikoxyz/taiko-geth/eth/state_accessor.go @@ -24,6 +24,7 @@ "time"   "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/core" + "github.com/ethereum/go-ethereum/core/rawdb" "github.com/ethereum/go-ethereum/core/state" "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/core/vm" @@ -36,31 +37,11 @@ // noopReleaser is returned in case there is no operation expected // for releasing state. var noopReleaser = tracers.StateReleaseFunc(func() {})   -// StateAtBlock retrieves the state database associated with a certain block. -// If no state is locally available for the given block, a number of blocks -// are attempted to be reexecuted to generate the desired state. The optional -// base layer statedb can be provided which is regarded as the statedb of the -// parent block. -// -// An additional release function will be returned if the requested state is -// available. Release is expected to be invoked when the returned state is no longer needed. -// Its purpose is to prevent resource leaking. Though it can be noop in some cases. -// -// Parameters: -// - block: The block for which we want the state(state = block.Root) -// - reexec: The maximum number of blocks to reprocess trying to obtain the desired state -// - base: If the caller is tracing multiple blocks, the caller can provide the parent -// state continuously from the callsite. -// - readOnly: If true, then the live 'blockchain' state database is used. No mutation should -// be made from caller, e.g. perform Commit or other 'save-to-disk' changes. -// Otherwise, the trash generated by caller may be persisted permanently. -// - preferDisk: this arg can be used by the caller to signal that even though the 'base' is -// provided, it would be preferable to start from a fresh state, if we have it -// on disk. -func (eth *Ethereum) StateAtBlock(ctx context.Context, block *types.Block, reexec uint64, base *state.StateDB, readOnly bool, preferDisk bool) (statedb *state.StateDB, release tracers.StateReleaseFunc, err error) { +func (eth *Ethereum) hashState(ctx context.Context, block *types.Block, reexec uint64, base *state.StateDB, readOnly bool, preferDisk bool) (statedb *state.StateDB, release tracers.StateReleaseFunc, err error) { var ( current *types.Block database state.Database + triedb *trie.Database report = true origin = block.NumberU64() ) @@ -71,9 +52,9 @@ // The state is available in live database, create a reference // on top to prevent garbage collection and return a release // function to deref it. if statedb, err = eth.blockchain.StateAt(block.Root()); err == nil { - statedb.Database().TrieDB().Reference(block.Root(), common.Hash{}) + eth.blockchain.TrieDB().Reference(block.Root(), common.Hash{}) return statedb, func() { - statedb.Database().TrieDB().Dereference(block.Root()) + eth.blockchain.TrieDB().Dereference(block.Root()) }, nil } } @@ -84,14 +65,16 @@ if base != nil { if preferDisk { // Create an ephemeral trie.Database for isolating the live one. Otherwise // the internal junks created by tracing will be persisted into the disk. - database = state.NewDatabaseWithConfig(eth.chainDb, &trie.Config{Cache: 16}) + // TODO(rjl493456442), clean cache is disabled to prevent memory leak, + // please re-enable it for better performance. + database = state.NewDatabaseWithConfig(eth.chainDb, trie.HashDefaults) if statedb, err = state.New(block.Root(), database, nil); err == nil { log.Info("Found disk backend for state trie", "root", block.Root(), "number", block.Number()) return statedb, noopReleaser, nil } } // The optional base statedb is given, mark the start point as parent block - statedb, database, report = base, base.Database(), false + statedb, database, triedb, report = base, base.Database(), base.Database().TrieDB(), false current = eth.blockchain.GetBlock(block.ParentHash(), block.NumberU64()-1) } else { // Otherwise, try to reexec blocks until we find a state or reach our limit @@ -99,7 +82,10 @@ current = block   // Create an ephemeral trie.Database for isolating the live one. Otherwise // the internal junks created by tracing will be persisted into the disk. - database = state.NewDatabaseWithConfig(eth.chainDb, &trie.Config{Cache: 16}) + // TODO(rjl493456442), clean cache is disabled to prevent memory leak, + // please re-enable it for better performance. + triedb = trie.NewDatabase(eth.chainDb, trie.HashDefaults) + database = state.NewDatabaseWithNodeDB(eth.chainDb, triedb)   // If we didn't check the live database, do check state over ephemeral database, // otherwise we would rewind past a persisted block (specific corner case is @@ -175,17 +161,58 @@ return nil, nil, fmt.Errorf("state reset after block %d failed: %v", current.NumberU64(), err) } // Hold the state reference and also drop the parent state // to prevent accumulating too many nodes in memory. - database.TrieDB().Reference(root, common.Hash{}) + triedb.Reference(root, common.Hash{}) if parent != (common.Hash{}) { - database.TrieDB().Dereference(parent) + triedb.Dereference(parent) } parent = root } if report { - nodes, imgs := database.TrieDB().Size() + _, nodes, imgs := triedb.Size() // all memory is contained within the nodes return in hashdb log.Info("Historical state regenerated", "block", current.NumberU64(), "elapsed", time.Since(start), "nodes", nodes, "preimages", imgs) } - return statedb, func() { database.TrieDB().Dereference(block.Root()) }, nil + return statedb, func() { triedb.Dereference(block.Root()) }, nil +} + +func (eth *Ethereum) pathState(block *types.Block) (*state.StateDB, func(), error) { + // Check if the requested state is available in the live chain. + statedb, err := eth.blockchain.StateAt(block.Root()) + if err == nil { + return statedb, noopReleaser, nil + } + // TODO historic state is not supported in path-based scheme. + // Fully archive node in pbss will be implemented by relying + // on state history, but needs more work on top. + return nil, nil, errors.New("historical state not available in path scheme yet") +} + +// stateAtBlock retrieves the state database associated with a certain block. +// If no state is locally available for the given block, a number of blocks +// are attempted to be reexecuted to generate the desired state. The optional +// base layer statedb can be provided which is regarded as the statedb of the +// parent block. +// +// An additional release function will be returned if the requested state is +// available. Release is expected to be invoked when the returned state is no +// longer needed. Its purpose is to prevent resource leaking. Though it can be +// noop in some cases. +// +// Parameters: +// - block: The block for which we want the state(state = block.Root) +// - reexec: The maximum number of blocks to reprocess trying to obtain the desired state +// - base: If the caller is tracing multiple blocks, the caller can provide the parent +// state continuously from the callsite. +// - readOnly: If true, then the live 'blockchain' state database is used. No mutation should +// be made from caller, e.g. perform Commit or other 'save-to-disk' changes. +// Otherwise, the trash generated by caller may be persisted permanently. +// - preferDisk: This arg can be used by the caller to signal that even though the 'base' is +// provided, it would be preferable to start from a fresh state, if we have it +// on disk. +func (eth *Ethereum) stateAtBlock(ctx context.Context, block *types.Block, reexec uint64, base *state.StateDB, readOnly bool, preferDisk bool) (statedb *state.StateDB, release tracers.StateReleaseFunc, err error) { + if eth.blockchain.TrieDB().Scheme() == rawdb.HashScheme { + return eth.hashState(ctx, block, reexec, base, readOnly, preferDisk) + } + return eth.pathState(block) }   // stateAtTransaction returns the execution environment of a certain transaction. @@ -201,7 +228,7 @@ return nil, vm.BlockContext{}, nil, nil, fmt.Errorf("parent %#x not found", block.ParentHash()) } // Lookup the statedb of parent block from the live database, // otherwise regenerate it on the flight. - statedb, release, err := eth.StateAtBlock(ctx, parent, reexec, nil, true, false) + statedb, release, err := eth.stateAtBlock(ctx, parent, reexec, nil, true, false) if err != nil { return nil, vm.BlockContext{}, nil, nil, err }
diff --git ethereum/go-ethereum/eth/sync.go taikoxyz/taiko-geth/eth/sync.go index ba7a7427a51a99ca226f8c67335df11ae45c4d72..c7ba7c93d6e970b0829db419b8e1940da6eb5afb 100644 --- ethereum/go-ethereum/eth/sync.go +++ taikoxyz/taiko-geth/eth/sync.go @@ -197,16 +197,25 @@ td := cs.handler.chain.GetTd(block.Hash(), block.Number.Uint64()) return downloader.SnapSync, td } // We are probably in full sync, but we might have rewound to before the - // snap sync pivot, check if we should reenable + // snap sync pivot, check if we should re-enable snap sync. + head := cs.handler.chain.CurrentBlock() if pivot := rawdb.ReadLastPivotNumber(cs.handler.database); pivot != nil { - if head := cs.handler.chain.CurrentBlock(); head.Number.Uint64() < *pivot { + if head.Number.Uint64() < *pivot { block := cs.handler.chain.CurrentSnapBlock() td := cs.handler.chain.GetTd(block.Hash(), block.Number.Uint64()) return downloader.SnapSync, td } } + // We are in a full sync, but the associated head state is missing. To complete + // the head state, forcefully rerun the snap sync. Note it doesn't mean the + // persistent state is corrupted, just mismatch with the head block. + if !cs.handler.chain.HasState(head.Root) { + block := cs.handler.chain.CurrentSnapBlock() + td := cs.handler.chain.GetTd(block.Hash(), block.Number.Uint64()) + log.Info("Reenabled snap sync as chain is stateless") + return downloader.SnapSync, td + } // Nope, we're really full syncing - head := cs.handler.chain.CurrentBlock() td := cs.handler.chain.GetTd(head.Hash(), head.Number.Uint64()) return downloader.FullSync, td } @@ -242,13 +251,7 @@ err := h.downloader.LegacySync(op.peer.ID(), op.head, op.td, h.chain.Config().TerminalTotalDifficulty, op.mode) if err != nil { return err } - if h.snapSync.Load() { - log.Info("Snap sync complete, auto disabling") - h.snapSync.Store(false) - } - // If we've successfully finished a sync cycle, enable accepting transactions - // from the network. - h.acceptTxs.Store(true) + h.enableSyncedFeatures()   head := h.chain.CurrentBlock() if head.Number.Uint64() > 0 {
diff --git ethereum/go-ethereum/eth/handler_test.go taikoxyz/taiko-geth/eth/handler_test.go index 7451e17012a008a2ee00ad598a462a31fae4144d..6d6132ee4ce893e29a378fb4f07bcc11bbd3c7d7 100644 --- ethereum/go-ethereum/eth/handler_test.go +++ taikoxyz/taiko-geth/eth/handler_test.go @@ -72,32 +72,23 @@ }   // Get retrieves the transaction from local txpool with given // tx hash. -func (p *testTxPool) Get(hash common.Hash) *txpool.Transaction { +func (p *testTxPool) Get(hash common.Hash) *types.Transaction { p.lock.Lock() defer p.lock.Unlock() - - if tx := p.pool[hash]; tx != nil { - return &txpool.Transaction{Tx: tx} - } - return nil + return p.pool[hash] }   // Add appends a batch of transactions to the pool, and notifies any // listeners if the addition channel is non nil -func (p *testTxPool) Add(txs []*txpool.Transaction, local bool, sync bool) []error { - unwrapped := make([]*types.Transaction, len(txs)) - for i, tx := range txs { - unwrapped[i] = tx.Tx - } +func (p *testTxPool) Add(txs []*types.Transaction, local bool, sync bool) []error { p.lock.Lock() defer p.lock.Unlock()   - for _, tx := range unwrapped { + for _, tx := range txs { p.pool[tx.Hash()] = tx } - - p.txFeed.Send(core.NewTxsEvent{Txs: unwrapped}) - return make([]error, len(unwrapped)) + p.txFeed.Send(core.NewTxsEvent{Txs: txs}) + return make([]error, len(txs)) }   // Pending returns all the transactions known to the pool @@ -118,19 +109,21 @@ for addr, batch := range batches { for _, tx := range batch { pending[addr] = append(pending[addr], &txpool.LazyTransaction{ Hash: tx.Hash(), - Tx: &txpool.Transaction{Tx: tx}, + Tx: tx, Time: tx.Time(), GasFeeCap: tx.GasFeeCap(), GasTipCap: tx.GasTipCap(), + Gas: tx.Gas(), + BlobGas: tx.BlobGas(), }) } } return pending }   -// SubscribeNewTxsEvent should return an event subscription of NewTxsEvent and +// SubscribeTransactions should return an event subscription of NewTxsEvent and // send events to the given channel. -func (p *testTxPool) SubscribeNewTxsEvent(ch chan<- core.NewTxsEvent) event.Subscription { +func (p *testTxPool) SubscribeTransactions(ch chan<- core.NewTxsEvent, reorgs bool) event.Subscription { return p.txFeed.Subscribe(ch) }
diff --git ethereum/go-ethereum/eth/peerset.go taikoxyz/taiko-geth/eth/peerset.go index b9cc1e03aca3d02289d5467092afcdf2b0c3ee62..b27d3964a119e2c6a1e86bb4d251f75779ffc1cb 100644 --- ethereum/go-ethereum/eth/peerset.go +++ taikoxyz/taiko-geth/eth/peerset.go @@ -18,6 +18,7 @@ package eth   import ( "errors" + "fmt" "math/big" "sync"   @@ -74,7 +75,7 @@ func (ps *peerSet) registerSnapExtension(peer *snap.Peer) error { // Reject the peer if it advertises `snap` without `eth` as `snap` is only a // satellite protocol meaningful with the chain selection of `eth` if !peer.RunningCap(eth.ProtocolName, eth.ProtocolVersions) { - return errSnapWithoutEth + return fmt.Errorf("%w: have %v", errSnapWithoutEth, peer.Caps()) } // Ensure nobody can double connect ps.lock.Lock()
diff --git ethereum/go-ethereum/eth/backend.go taikoxyz/taiko-geth/eth/backend.go index 667200bceddaff1cff8a61fde4591398f020d958..c6787870ca02becdafe7cd962cdb2d0a9c0b8d28 100644 --- ethereum/go-ethereum/eth/backend.go +++ taikoxyz/taiko-geth/eth/backend.go @@ -133,8 +133,15 @@ chainDb, err := stack.OpenDatabaseWithFreezer("chaindata", config.DatabaseCache, config.DatabaseHandles, config.DatabaseFreezer, "eth/db/chaindata/", false) if err != nil { return nil, err } - if err := pruner.RecoverPruning(stack.ResolvePath(""), chainDb); err != nil { - log.Error("Failed to recover state", "error", err) + scheme, err := rawdb.ParseStateScheme(config.StateScheme, chainDb) + if err != nil { + return nil, err + } + // Try to recover offline state pruning only in hash-based. + if scheme == rawdb.HashScheme { + if err := pruner.RecoverPruning(stack.ResolvePath(""), chainDb); err != nil { + log.Error("Failed to recover state", "error", err) + } } // Transfer mining-related config to the ethash config. chainConfig, err := core.LoadChainConfig(chainDb, config.Genesis) @@ -161,7 +168,6 @@ bloomIndexer: core.NewBloomIndexer(chainDb, params.BloomBitsBlocks, params.BloomConfirms), p2pServer: stack.Server(), shutdownTracker: shutdowncheck.NewShutdownTracker(chainDb), } - bcVersion := rawdb.ReadDatabaseVersion(chainDb) var dbVer = "<nil>" if bcVersion != nil { @@ -191,6 +197,8 @@ TrieDirtyDisabled: config.NoPruning, TrieTimeLimit: config.TrieTimeout, SnapshotLimit: config.SnapshotCache, Preimages: config.Preimages, + StateHistory: config.StateHistory, + StateScheme: scheme, } ) // Override the chain config with provided settings. @@ -201,7 +209,7 @@ } if config.OverrideVerkle != nil { overrides.OverrideVerkle = config.OverrideVerkle } - eth.blockchain, err = core.NewBlockChain(chainDb, cacheConfig, config.Genesis, &overrides, eth.engine, vmConfig, eth.shouldPreserve, &config.TxLookupLimit) + eth.blockchain, err = core.NewBlockChain(chainDb, cacheConfig, config.Genesis, &overrides, eth.engine, vmConfig, eth.shouldPreserve, &config.TransactionHistory) if err != nil { return nil, err } @@ -383,7 +391,7 @@ // r4 D // r5 A [X] F G // r6 [X] // - // In the round5, the inturn signer E is offline, so the worst case + // In the round5, the in-turn signer E is offline, so the worst case // is A, F and G sign the block of round5 and reject the block of opponents // and in the round6, the last available signer B is offline, the whole // network is stuck. @@ -438,7 +446,7 @@ cli.Authorize(eb, wallet.SignData) } // If mining is started, we can disable the transaction rejection mechanism // introduced to speed sync times. - s.handler.acceptTxs.Store(true) + s.handler.enableSyncedFeatures()   go s.miner.Start() } @@ -470,8 +478,8 @@ func (s *Ethereum) Engine() consensus.Engine { return s.engine } func (s *Ethereum) ChainDb() ethdb.Database { return s.chainDb } func (s *Ethereum) IsListening() bool { return true } // Always listening func (s *Ethereum) Downloader() *downloader.Downloader { return s.handler.downloader } -func (s *Ethereum) Synced() bool { return s.handler.acceptTxs.Load() } -func (s *Ethereum) SetSynced() { s.handler.acceptTxs.Store(true) } +func (s *Ethereum) Synced() bool { return s.handler.synced.Load() } +func (s *Ethereum) SetSynced() { s.handler.enableSyncedFeatures() } func (s *Ethereum) ArchiveMode() bool { return s.config.NoPruning } func (s *Ethereum) BloomIndexer() *core.ChainIndexer { return s.bloomIndexer } func (s *Ethereum) Merger() *consensus.Merger { return s.merger }
diff --git ethereum/go-ethereum/eth/api_debug_test.go taikoxyz/taiko-geth/eth/api_debug_test.go index 6a1b537c25ce71fb151ee9685597f37050ae963f..3d3444a87163ff6fbef1893c6d41e95a651d02f9 100644 --- ethereum/go-ethereum/eth/api_debug_test.go +++ taikoxyz/taiko-geth/eth/api_debug_test.go @@ -159,9 +159,10 @@ t.Parallel()   // Create a state where account 0x010000... has a few storage entries. var ( - state, _ = state.New(types.EmptyRootHash, state.NewDatabase(rawdb.NewMemoryDatabase()), nil) - addr = common.Address{0x01} - keys = []common.Hash{ // hashes of Keys of storage + db = state.NewDatabaseWithConfig(rawdb.NewMemoryDatabase(), &trie.Config{Preimages: true}) + sdb, _ = state.New(types.EmptyRootHash, db, nil) + addr = common.Address{0x01} + keys = []common.Hash{ // hashes of Keys of storage common.HexToHash("340dd630ad21bf010b4e676dbfa9ba9a02175262d1fa356232cfde6cb5b47ef2"), common.HexToHash("426fcb404ab2d5d8e61a3d918108006bbb0a9be65e92235bb10eefbdb6dcd053"), common.HexToHash("48078cfed56339ea54962e72c37c7f588fc4f8e5bc173827ba75cb10a63a96a5"), @@ -175,8 +176,10 @@ keys[3]: {Key: &common.Hash{0x03}, Value: common.Hash{0x04}}, } ) for _, entry := range storage { - state.SetState(addr, *entry.Key, entry.Value) + sdb.SetState(addr, *entry.Key, entry.Value) } + root, _ := sdb.Commit(0, false) + sdb, _ = state.New(root, db, nil)   // Check a few combinations of limit and start/end. tests := []struct { @@ -206,11 +209,7 @@ want: StorageRangeResult{storageMap{keys[1]: storage[keys[1]], keys[2]: storage[keys[2]]}, &keys[3]}, }, } for _, test := range tests { - tr, err := state.StorageTrie(addr) - if err != nil { - t.Error(err) - } - result, err := storageRangeAt(tr, test.start, test.limit) + result, err := storageRangeAt(sdb, root, addr, test.start, test.limit) if err != nil { t.Error(err) }

This adds Taiko protocol specific logic into the API.

diff --git ethereum/go-ethereum/eth/downloader/fetchers_concurrent_headers.go taikoxyz/taiko-geth/eth/downloader/fetchers_concurrent_headers.go index 84c7f209865a9e2aad029c7689422fafc6b883a9..8201f4ca74232e8e726b98557e453cd70e4166b5 100644 --- ethereum/go-ethereum/eth/downloader/fetchers_concurrent_headers.go +++ taikoxyz/taiko-geth/eth/downloader/fetchers_concurrent_headers.go @@ -81,7 +81,7 @@ // deliver is responsible for taking a generic response packet from the concurrent // fetcher, unpacking the header data and delivering it to the downloader's queue. func (q *headerQueue) deliver(peer *peerConnection, packet *eth.Response) (int, error) { - headers := *packet.Res.(*eth.BlockHeadersPacket) + headers := *packet.Res.(*eth.BlockHeadersRequest) hashes := packet.Meta.([]common.Hash)   accepted, err := q.queue.DeliverHeaders(peer.id, headers, hashes, q.headerProcCh)
diff --git ethereum/go-ethereum/eth/fetcher/block_fetcher_test.go taikoxyz/taiko-geth/eth/fetcher/block_fetcher_test.go index 6d8516fa6ac0280512f02b84317a5dd742cf5ee5..6927300b1d3406d6ee543740f908649318305675 100644 --- ethereum/go-ethereum/eth/fetcher/block_fetcher_test.go +++ taikoxyz/taiko-geth/eth/fetcher/block_fetcher_test.go @@ -44,7 +44,7 @@ Config: params.TestChainConfig, Alloc: core.GenesisAlloc{testAddress: {Balance: big.NewInt(1000000000000000)}}, BaseFee: big.NewInt(params.InitialBaseFee), } - genesis = gspec.MustCommit(testdb) + genesis = gspec.MustCommit(testdb, trie.NewDatabase(testdb, trie.HashDefaults)) unknownBlock = types.NewBlock(&types.Header{Root: types.EmptyRootHash, GasLimit: params.GenesisGasLimit, BaseFee: big.NewInt(params.InitialBaseFee)}, nil, nil, nil, trie.NewStackTrie(nil)) )   @@ -213,7 +213,7 @@ Peer: peer, } res := &eth.Response{ Req: req, - Res: (*eth.BlockHeadersPacket)(&headers), + Res: (*eth.BlockHeadersRequest)(&headers), Time: drift, Done: make(chan error, 1), // Ignore the returned status } @@ -255,7 +255,7 @@ Peer: peer, } res := &eth.Response{ Req: req, - Res: (*eth.BlockBodiesPacket)(&bodies), + Res: (*eth.BlockBodiesResponse)(&bodies), Time: drift, Done: make(chan error, 1), // Ignore the returned status }
diff --git ethereum/go-ethereum/eth/fetcher/tx_fetcher_test.go taikoxyz/taiko-geth/eth/fetcher/tx_fetcher_test.go index c5805d6ef388718f438e6455a2a1344ce2c55248..77b89085d317c5639f9d8e30f0c2664049b6ec46 100644 --- ethereum/go-ethereum/eth/fetcher/tx_fetcher_test.go +++ taikoxyz/taiko-geth/eth/fetcher/tx_fetcher_test.go @@ -27,6 +27,7 @@ "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common/mclock" "github.com/ethereum/go-ethereum/core/txpool" "github.com/ethereum/go-ethereum/core/types" + "github.com/ethereum/go-ethereum/params" )   var ( @@ -40,10 +41,21 @@ } // testTxsHashes is the hashes of the test transactions above testTxsHashes = []common.Hash{testTxs[0].Hash(), testTxs[1].Hash(), testTxs[2].Hash(), testTxs[3].Hash()} ) + +type announce struct { + hash common.Hash + kind *byte + size *uint32 +} + +func typeptr(t byte) *byte { return &t } +func sizeptr(n uint32) *uint32 { return &n }   type doTxNotify struct { peer string hashes []common.Hash + types []byte + sizes []uint32 } type doTxEnqueue struct { peer string @@ -57,7 +69,14 @@ } type doDrop string type doFunc func()   +type isWaitingWithMeta map[string][]announce type isWaiting map[string][]common.Hash + +type isScheduledWithMeta struct { + tracking map[string][]announce + fetching map[string][]common.Hash + dangling map[string][]common.Hash +} type isScheduled struct { tracking map[string][]common.Hash fetching map[string][]common.Hash @@ -81,6 +100,7 @@ return NewTxFetcher( func(common.Hash) bool { return false }, nil, func(string, []common.Hash) error { return nil }, + nil, ) }, steps: []interface{}{ @@ -162,6 +182,212 @@ }, }) }   +// Tests that transaction announcements with associated metadata are added to a +// waitlist, and none of them are scheduled for retrieval until the wait expires. +// +// This test is an extended version of TestTransactionFetcherWaiting. It's mostly +// to cover the metadata checkes without bloating up the basic behavioral tests +// with all the useless extra fields. +func TestTransactionFetcherWaitingWithMeta(t *testing.T) { + testTransactionFetcherParallel(t, txFetcherTest{ + init: func() *TxFetcher { + return NewTxFetcher( + func(common.Hash) bool { return false }, + nil, + func(string, []common.Hash) error { return nil }, + nil, + ) + }, + steps: []interface{}{ + // Initial announcement to get something into the waitlist + doTxNotify{peer: "A", hashes: []common.Hash{{0x01}, {0x02}}, types: []byte{types.LegacyTxType, types.LegacyTxType}, sizes: []uint32{111, 222}}, + isWaitingWithMeta(map[string][]announce{ + "A": { + {common.Hash{0x01}, typeptr(types.LegacyTxType), sizeptr(111)}, + {common.Hash{0x02}, typeptr(types.LegacyTxType), sizeptr(222)}, + }, + }), + // Announce from a new peer to check that no overwrite happens + doTxNotify{peer: "B", hashes: []common.Hash{{0x03}, {0x04}}, types: []byte{types.LegacyTxType, types.LegacyTxType}, sizes: []uint32{333, 444}}, + isWaitingWithMeta(map[string][]announce{ + "A": { + {common.Hash{0x01}, typeptr(types.LegacyTxType), sizeptr(111)}, + {common.Hash{0x02}, typeptr(types.LegacyTxType), sizeptr(222)}, + }, + "B": { + {common.Hash{0x03}, typeptr(types.LegacyTxType), sizeptr(333)}, + {common.Hash{0x04}, typeptr(types.LegacyTxType), sizeptr(444)}, + }, + }), + // Announce clashing hashes but unique new peer + doTxNotify{peer: "C", hashes: []common.Hash{{0x01}, {0x04}}, types: []byte{types.LegacyTxType, types.LegacyTxType}, sizes: []uint32{111, 444}}, + isWaitingWithMeta(map[string][]announce{ + "A": { + {common.Hash{0x01}, typeptr(types.LegacyTxType), sizeptr(111)}, + {common.Hash{0x02}, typeptr(types.LegacyTxType), sizeptr(222)}, + }, + "B": { + {common.Hash{0x03}, typeptr(types.LegacyTxType), sizeptr(333)}, + {common.Hash{0x04}, typeptr(types.LegacyTxType), sizeptr(444)}, + }, + "C": { + {common.Hash{0x01}, typeptr(types.LegacyTxType), sizeptr(111)}, + {common.Hash{0x04}, typeptr(types.LegacyTxType), sizeptr(444)}, + }, + }), + // Announce existing and clashing hashes from existing peer. Clashes + // should not overwrite previous announcements. + doTxNotify{peer: "A", hashes: []common.Hash{{0x01}, {0x03}, {0x05}}, types: []byte{types.LegacyTxType, types.LegacyTxType, types.LegacyTxType}, sizes: []uint32{999, 333, 555}}, + isWaitingWithMeta(map[string][]announce{ + "A": { + {common.Hash{0x01}, typeptr(types.LegacyTxType), sizeptr(111)}, + {common.Hash{0x02}, typeptr(types.LegacyTxType), sizeptr(222)}, + {common.Hash{0x03}, typeptr(types.LegacyTxType), sizeptr(333)}, + {common.Hash{0x05}, typeptr(types.LegacyTxType), sizeptr(555)}, + }, + "B": { + {common.Hash{0x03}, typeptr(types.LegacyTxType), sizeptr(333)}, + {common.Hash{0x04}, typeptr(types.LegacyTxType), sizeptr(444)}, + }, + "C": { + {common.Hash{0x01}, typeptr(types.LegacyTxType), sizeptr(111)}, + {common.Hash{0x04}, typeptr(types.LegacyTxType), sizeptr(444)}, + }, + }), + // Announce clashing hashes with conflicting metadata. Somebody will + // be in the wrong, but we don't know yet who. + doTxNotify{peer: "D", hashes: []common.Hash{{0x01}, {0x02}}, types: []byte{types.LegacyTxType, types.BlobTxType}, sizes: []uint32{999, 222}}, + isWaitingWithMeta(map[string][]announce{ + "A": { + {common.Hash{0x01}, typeptr(types.LegacyTxType), sizeptr(111)}, + {common.Hash{0x02}, typeptr(types.LegacyTxType), sizeptr(222)}, + {common.Hash{0x03}, typeptr(types.LegacyTxType), sizeptr(333)}, + {common.Hash{0x05}, typeptr(types.LegacyTxType), sizeptr(555)}, + }, + "B": { + {common.Hash{0x03}, typeptr(types.LegacyTxType), sizeptr(333)}, + {common.Hash{0x04}, typeptr(types.LegacyTxType), sizeptr(444)}, + }, + "C": { + {common.Hash{0x01}, typeptr(types.LegacyTxType), sizeptr(111)}, + {common.Hash{0x04}, typeptr(types.LegacyTxType), sizeptr(444)}, + }, + "D": { + {common.Hash{0x01}, typeptr(types.LegacyTxType), sizeptr(999)}, + {common.Hash{0x02}, typeptr(types.BlobTxType), sizeptr(222)}, + }, + }), + isScheduled{tracking: nil, fetching: nil}, + + // Wait for the arrival timeout which should move all expired items + // from the wait list to the scheduler + doWait{time: txArriveTimeout, step: true}, + isWaiting(nil), + isScheduledWithMeta{ + tracking: map[string][]announce{ + "A": { + {common.Hash{0x01}, typeptr(types.LegacyTxType), sizeptr(111)}, + {common.Hash{0x02}, typeptr(types.LegacyTxType), sizeptr(222)}, + {common.Hash{0x03}, typeptr(types.LegacyTxType), sizeptr(333)}, + {common.Hash{0x05}, typeptr(types.LegacyTxType), sizeptr(555)}, + }, + "B": { + {common.Hash{0x03}, typeptr(types.LegacyTxType), sizeptr(333)}, + {common.Hash{0x04}, typeptr(types.LegacyTxType), sizeptr(444)}, + }, + "C": { + {common.Hash{0x01}, typeptr(types.LegacyTxType), sizeptr(111)}, + {common.Hash{0x04}, typeptr(types.LegacyTxType), sizeptr(444)}, + }, + "D": { + {common.Hash{0x01}, typeptr(types.LegacyTxType), sizeptr(999)}, + {common.Hash{0x02}, typeptr(types.BlobTxType), sizeptr(222)}, + }, + }, + fetching: map[string][]common.Hash{ // Depends on deterministic test randomizer + "A": {{0x03}, {0x05}}, + "C": {{0x01}, {0x04}}, + "D": {{0x02}}, + }, + }, + // Queue up a non-fetchable transaction and then trigger it with a new + // peer (weird case to test 1 line in the fetcher) + doTxNotify{peer: "C", hashes: []common.Hash{{0x06}, {0x07}}, types: []byte{types.LegacyTxType, types.LegacyTxType}, sizes: []uint32{666, 777}}, + isWaitingWithMeta(map[string][]announce{ + "C": { + {common.Hash{0x06}, typeptr(types.LegacyTxType), sizeptr(666)}, + {common.Hash{0x07}, typeptr(types.LegacyTxType), sizeptr(777)}, + }, + }), + doWait{time: txArriveTimeout, step: true}, + isScheduledWithMeta{ + tracking: map[string][]announce{ + "A": { + {common.Hash{0x01}, typeptr(types.LegacyTxType), sizeptr(111)}, + {common.Hash{0x02}, typeptr(types.LegacyTxType), sizeptr(222)}, + {common.Hash{0x03}, typeptr(types.LegacyTxType), sizeptr(333)}, + {common.Hash{0x05}, typeptr(types.LegacyTxType), sizeptr(555)}, + }, + "B": { + {common.Hash{0x03}, typeptr(types.LegacyTxType), sizeptr(333)}, + {common.Hash{0x04}, typeptr(types.LegacyTxType), sizeptr(444)}, + }, + "C": { + {common.Hash{0x01}, typeptr(types.LegacyTxType), sizeptr(111)}, + {common.Hash{0x04}, typeptr(types.LegacyTxType), sizeptr(444)}, + {common.Hash{0x06}, typeptr(types.LegacyTxType), sizeptr(666)}, + {common.Hash{0x07}, typeptr(types.LegacyTxType), sizeptr(777)}, + }, + "D": { + {common.Hash{0x01}, typeptr(types.LegacyTxType), sizeptr(999)}, + {common.Hash{0x02}, typeptr(types.BlobTxType), sizeptr(222)}, + }, + }, + fetching: map[string][]common.Hash{ + "A": {{0x03}, {0x05}}, + "C": {{0x01}, {0x04}}, + "D": {{0x02}}, + }, + }, + doTxNotify{peer: "E", hashes: []common.Hash{{0x06}, {0x07}}, types: []byte{types.LegacyTxType, types.LegacyTxType}, sizes: []uint32{666, 777}}, + isScheduledWithMeta{ + tracking: map[string][]announce{ + "A": { + {common.Hash{0x01}, typeptr(types.LegacyTxType), sizeptr(111)}, + {common.Hash{0x02}, typeptr(types.LegacyTxType), sizeptr(222)}, + {common.Hash{0x03}, typeptr(types.LegacyTxType), sizeptr(333)}, + {common.Hash{0x05}, typeptr(types.LegacyTxType), sizeptr(555)}, + }, + "B": { + {common.Hash{0x03}, typeptr(types.LegacyTxType), sizeptr(333)}, + {common.Hash{0x04}, typeptr(types.LegacyTxType), sizeptr(444)}, + }, + "C": { + {common.Hash{0x01}, typeptr(types.LegacyTxType), sizeptr(111)}, + {common.Hash{0x04}, typeptr(types.LegacyTxType), sizeptr(444)}, + {common.Hash{0x06}, typeptr(types.LegacyTxType), sizeptr(666)}, + {common.Hash{0x07}, typeptr(types.LegacyTxType), sizeptr(777)}, + }, + "D": { + {common.Hash{0x01}, typeptr(types.LegacyTxType), sizeptr(999)}, + {common.Hash{0x02}, typeptr(types.BlobTxType), sizeptr(222)}, + }, + "E": { + {common.Hash{0x06}, typeptr(types.LegacyTxType), sizeptr(666)}, + {common.Hash{0x07}, typeptr(types.LegacyTxType), sizeptr(777)}, + }, + }, + fetching: map[string][]common.Hash{ + "A": {{0x03}, {0x05}}, + "C": {{0x01}, {0x04}}, + "D": {{0x02}}, + "E": {{0x06}, {0x07}}, + }, + }, + }, + }) +} + // Tests that transaction announcements skip the waiting list if they are // already scheduled. func TestTransactionFetcherSkipWaiting(t *testing.T) { @@ -171,6 +397,7 @@ return NewTxFetcher( func(common.Hash) bool { return false }, nil, func(string, []common.Hash) error { return nil }, + nil, ) }, steps: []interface{}{ @@ -234,6 +461,7 @@ return NewTxFetcher( func(common.Hash) bool { return false }, nil, func(string, []common.Hash) error { return nil }, + nil, ) }, steps: []interface{}{ @@ -313,6 +541,7 @@ func(origin string, hashes []common.Hash) error { <-proceed return errors.New("peer disconnected") }, + nil, ) }, steps: []interface{}{ @@ -378,10 +607,11 @@ testTransactionFetcherParallel(t, txFetcherTest{ init: func() *TxFetcher { return NewTxFetcher( func(common.Hash) bool { return false }, - func(txs []*txpool.Transaction) []error { + func(txs []*types.Transaction) []error { return make([]error, len(txs)) }, func(string, []common.Hash) error { return nil }, + nil, ) }, steps: []interface{}{ @@ -417,10 +647,11 @@ testTransactionFetcherParallel(t, txFetcherTest{ init: func() *TxFetcher { return NewTxFetcher( func(common.Hash) bool { return false }, - func(txs []*txpool.Transaction) []error { + func(txs []*types.Transaction) []error { return make([]error, len(txs)) }, func(string, []common.Hash) error { return nil }, + nil, ) }, steps: []interface{}{ @@ -455,10 +686,11 @@ testTransactionFetcherParallel(t, txFetcherTest{ init: func() *TxFetcher { return NewTxFetcher( func(common.Hash) bool { return false }, - func(txs []*txpool.Transaction) []error { + func(txs []*types.Transaction) []error { return make([]error, len(txs)) }, func(string, []common.Hash) error { return nil }, + nil, ) }, steps: []interface{}{ @@ -501,10 +733,11 @@ testTransactionFetcherParallel(t, txFetcherTest{ init: func() *TxFetcher { return NewTxFetcher( func(common.Hash) bool { return false }, - func(txs []*txpool.Transaction) []error { + func(txs []*types.Transaction) []error { return make([]error, len(txs)) }, func(string, []common.Hash) error { return nil }, + nil, ) }, steps: []interface{}{ @@ -539,10 +772,11 @@ testTransactionFetcherParallel(t, txFetcherTest{ init: func() *TxFetcher { return NewTxFetcher( func(common.Hash) bool { return false }, - func(txs []*txpool.Transaction) []error { + func(txs []*types.Transaction) []error { return make([]error, len(txs)) }, func(string, []common.Hash) error { return nil }, + nil, ) }, steps: []interface{}{ @@ -591,6 +825,7 @@ return NewTxFetcher( func(common.Hash) bool { return false }, nil, func(string, []common.Hash) error { return nil }, + nil, ) }, steps: []interface{}{ @@ -644,10 +879,11 @@ testTransactionFetcherParallel(t, txFetcherTest{ init: func() *TxFetcher { return NewTxFetcher( func(common.Hash) bool { return false }, - func(txs []*txpool.Transaction) []error { + func(txs []*types.Transaction) []error { return make([]error, len(txs)) }, func(string, []common.Hash) error { return nil }, + nil, ) }, steps: []interface{}{ @@ -713,6 +949,7 @@ return NewTxFetcher( func(common.Hash) bool { return false }, nil, func(string, []common.Hash) error { return nil }, + nil, ) }, steps: []interface{}{ @@ -757,21 +994,21 @@ }, }) }   -// Tests that if thousands of transactions are announces, only a small +// Tests that if thousands of transactions are announced, only a small // number of them will be requested at a time. func TestTransactionFetcherRateLimiting(t *testing.T) { - // Create a slew of transactions and to announce them + // Create a slew of transactions and announce them var hashes []common.Hash for i := 0; i < maxTxAnnounces; i++ { hashes = append(hashes, common.Hash{byte(i / 256), byte(i % 256)}) } - testTransactionFetcherParallel(t, txFetcherTest{ init: func() *TxFetcher { return NewTxFetcher( func(common.Hash) bool { return false }, nil, func(string, []common.Hash) error { return nil }, + nil, ) }, steps: []interface{}{ @@ -792,6 +1029,68 @@ }, }) }   +// Tests that if huge transactions are announced, only a small number of them will +// be requested at a time, to keep the responses below a resonable level. +func TestTransactionFetcherBandwidthLimiting(t *testing.T) { + testTransactionFetcherParallel(t, txFetcherTest{ + init: func() *TxFetcher { + return NewTxFetcher( + func(common.Hash) bool { return false }, + nil, + func(string, []common.Hash) error { return nil }, + nil, + ) + }, + steps: []interface{}{ + // Announce mid size transactions from A to verify that multiple + // ones can be piled into a single request. + doTxNotify{peer: "A", + hashes: []common.Hash{{0x01}, {0x02}, {0x03}, {0x04}}, + types: []byte{types.LegacyTxType, types.LegacyTxType, types.LegacyTxType, types.LegacyTxType}, + sizes: []uint32{48 * 1024, 48 * 1024, 48 * 1024, 48 * 1024}, + }, + // Announce exactly on the limit transactions to see that only one + // gets requested + doTxNotify{peer: "B", + hashes: []common.Hash{{0x05}, {0x06}}, + types: []byte{types.LegacyTxType, types.LegacyTxType}, + sizes: []uint32{maxTxRetrievalSize, maxTxRetrievalSize}, + }, + // Announce oversized blob transactions to see that overflows are ok + doTxNotify{peer: "C", + hashes: []common.Hash{{0x07}, {0x08}}, + types: []byte{types.BlobTxType, types.BlobTxType}, + sizes: []uint32{params.MaxBlobGasPerBlock, params.MaxBlobGasPerBlock}, + }, + doWait{time: txArriveTimeout, step: true}, + isWaiting(nil), + isScheduledWithMeta{ + tracking: map[string][]announce{ + "A": { + {common.Hash{0x01}, typeptr(types.LegacyTxType), sizeptr(48 * 1024)}, + {common.Hash{0x02}, typeptr(types.LegacyTxType), sizeptr(48 * 1024)}, + {common.Hash{0x03}, typeptr(types.LegacyTxType), sizeptr(48 * 1024)}, + {common.Hash{0x04}, typeptr(types.LegacyTxType), sizeptr(48 * 1024)}, + }, + "B": { + {common.Hash{0x05}, typeptr(types.LegacyTxType), sizeptr(maxTxRetrievalSize)}, + {common.Hash{0x06}, typeptr(types.LegacyTxType), sizeptr(maxTxRetrievalSize)}, + }, + "C": { + {common.Hash{0x07}, typeptr(types.BlobTxType), sizeptr(params.MaxBlobGasPerBlock)}, + {common.Hash{0x08}, typeptr(types.BlobTxType), sizeptr(params.MaxBlobGasPerBlock)}, + }, + }, + fetching: map[string][]common.Hash{ + "A": {{0x02}, {0x03}, {0x04}}, + "B": {{0x06}}, + "C": {{0x08}}, + }, + }, + }, + }) +} + // Tests that then number of transactions a peer is allowed to announce and/or // request at the same time is hard capped. func TestTransactionFetcherDoSProtection(t *testing.T) { @@ -810,6 +1109,7 @@ return NewTxFetcher( func(common.Hash) bool { return false }, nil, func(string, []common.Hash) error { return nil }, + nil, ) }, steps: []interface{}{ @@ -865,7 +1165,7 @@ testTransactionFetcherParallel(t, txFetcherTest{ init: func() *TxFetcher { return NewTxFetcher( func(common.Hash) bool { return false }, - func(txs []*txpool.Transaction) []error { + func(txs []*types.Transaction) []error { errs := make([]error, len(txs)) for i := 0; i < len(errs); i++ { if i%2 == 0 { @@ -877,6 +1177,7 @@ } return errs }, func(string, []common.Hash) error { return nil }, + nil, ) }, steps: []interface{}{ @@ -938,7 +1239,7 @@ testTransactionFetcher(t, txFetcherTest{ init: func() *TxFetcher { return NewTxFetcher( func(common.Hash) bool { return false }, - func(txs []*txpool.Transaction) []error { + func(txs []*types.Transaction) []error { errs := make([]error, len(txs)) for i := 0; i < len(errs); i++ { errs[i] = txpool.ErrUnderpriced @@ -946,6 +1247,7 @@ } return errs }, func(string, []common.Hash) error { return nil }, + nil, ) }, steps: append(steps, []interface{}{ @@ -964,10 +1266,11 @@ testTransactionFetcherParallel(t, txFetcherTest{ init: func() *TxFetcher { return NewTxFetcher( func(common.Hash) bool { return false }, - func(txs []*txpool.Transaction) []error { + func(txs []*types.Transaction) []error { return make([]error, len(txs)) }, func(string, []common.Hash) error { return nil }, + nil, ) }, steps: []interface{}{ @@ -1017,10 +1320,11 @@ testTransactionFetcherParallel(t, txFetcherTest{ init: func() *TxFetcher { return NewTxFetcher( func(common.Hash) bool { return false }, - func(txs []*txpool.Transaction) []error { + func(txs []*types.Transaction) []error { return make([]error, len(txs)) }, func(string, []common.Hash) error { return nil }, + nil, ) }, steps: []interface{}{ @@ -1083,10 +1387,11 @@ testTransactionFetcherParallel(t, txFetcherTest{ init: func() *TxFetcher { return NewTxFetcher( func(common.Hash) bool { return false }, - func(txs []*txpool.Transaction) []error { + func(txs []*types.Transaction) []error { return make([]error, len(txs)) }, func(string, []common.Hash) error { return nil }, + nil, ) }, steps: []interface{}{ @@ -1120,6 +1425,74 @@ }, }) }   +// Tests that announced transactions with the wrong transaction type or size will +// result in a dropped peer. +func TestInvalidAnnounceMetadata(t *testing.T) { + drop := make(chan string, 2) + testTransactionFetcherParallel(t, txFetcherTest{ + init: func() *TxFetcher { + return NewTxFetcher( + func(common.Hash) bool { return false }, + func(txs []*types.Transaction) []error { + return make([]error, len(txs)) + }, + func(string, []common.Hash) error { return nil }, + func(peer string) { drop <- peer }, + ) + }, + steps: []interface{}{ + // Initial announcement to get something into the waitlist + doTxNotify{peer: "A", hashes: []common.Hash{testTxsHashes[0], testTxsHashes[1]}, types: []byte{testTxs[0].Type(), testTxs[1].Type()}, sizes: []uint32{uint32(testTxs[0].Size()), uint32(testTxs[1].Size())}}, + isWaitingWithMeta(map[string][]announce{ + "A": { + {testTxsHashes[0], typeptr(testTxs[0].Type()), sizeptr(uint32(testTxs[0].Size()))}, + {testTxsHashes[1], typeptr(testTxs[1].Type()), sizeptr(uint32(testTxs[1].Size()))}, + }, + }), + // Announce from new peers conflicting transactions + doTxNotify{peer: "B", hashes: []common.Hash{testTxsHashes[0]}, types: []byte{testTxs[0].Type()}, sizes: []uint32{1024 + uint32(testTxs[0].Size())}}, + doTxNotify{peer: "C", hashes: []common.Hash{testTxsHashes[1]}, types: []byte{1 + testTxs[1].Type()}, sizes: []uint32{uint32(testTxs[1].Size())}}, + isWaitingWithMeta(map[string][]announce{ + "A": { + {testTxsHashes[0], typeptr(testTxs[0].Type()), sizeptr(uint32(testTxs[0].Size()))}, + {testTxsHashes[1], typeptr(testTxs[1].Type()), sizeptr(uint32(testTxs[1].Size()))}, + }, + "B": { + {testTxsHashes[0], typeptr(testTxs[0].Type()), sizeptr(1024 + uint32(testTxs[0].Size()))}, + }, + "C": { + {testTxsHashes[1], typeptr(1 + testTxs[1].Type()), sizeptr(uint32(testTxs[1].Size()))}, + }, + }), + // Schedule all the transactions for retrieval + doWait{time: txArriveTimeout, step: true}, + isWaitingWithMeta(nil), + isScheduledWithMeta{ + tracking: map[string][]announce{ + "A": { + {testTxsHashes[0], typeptr(testTxs[0].Type()), sizeptr(uint32(testTxs[0].Size()))}, + {testTxsHashes[1], typeptr(testTxs[1].Type()), sizeptr(uint32(testTxs[1].Size()))}, + }, + "B": { + {testTxsHashes[0], typeptr(testTxs[0].Type()), sizeptr(1024 + uint32(testTxs[0].Size()))}, + }, + "C": { + {testTxsHashes[1], typeptr(1 + testTxs[1].Type()), sizeptr(uint32(testTxs[1].Size()))}, + }, + }, + fetching: map[string][]common.Hash{ + "A": {testTxsHashes[0]}, + "C": {testTxsHashes[1]}, + }, + }, + // Deliver the transactions and wait for B to be dropped + doTxEnqueue{peer: "A", txs: []*types.Transaction{testTxs[0], testTxs[1]}}, + doFunc(func() { <-drop }), + doFunc(func() { <-drop }), + }, + }) +} + // This test reproduces a crash caught by the fuzzer. The root cause was a // dangling transaction timing out and clashing on re-add with a concurrently // announced one. @@ -1128,10 +1501,11 @@ testTransactionFetcherParallel(t, txFetcherTest{ init: func() *TxFetcher { return NewTxFetcher( func(common.Hash) bool { return false }, - func(txs []*txpool.Transaction) []error { + func(txs []*types.Transaction) []error { return make([]error, len(txs)) }, func(string, []common.Hash) error { return nil }, + nil, ) }, steps: []interface{}{ @@ -1155,10 +1529,11 @@ testTransactionFetcherParallel(t, txFetcherTest{ init: func() *TxFetcher { return NewTxFetcher( func(common.Hash) bool { return false }, - func(txs []*txpool.Transaction) []error { + func(txs []*types.Transaction) []error { return make([]error, len(txs)) }, func(string, []common.Hash) error { return nil }, + nil, ) }, steps: []interface{}{ @@ -1184,10 +1559,11 @@ testTransactionFetcherParallel(t, txFetcherTest{ init: func() *TxFetcher { return NewTxFetcher( func(common.Hash) bool { return false }, - func(txs []*txpool.Transaction) []error { + func(txs []*types.Transaction) []error { return make([]error, len(txs)) }, func(string, []common.Hash) error { return nil }, + nil, ) }, steps: []interface{}{ @@ -1217,13 +1593,14 @@ testTransactionFetcherParallel(t, txFetcherTest{ init: func() *TxFetcher { return NewTxFetcher( func(common.Hash) bool { return false }, - func(txs []*txpool.Transaction) []error { + func(txs []*types.Transaction) []error { return make([]error, len(txs)) }, func(string, []common.Hash) error { <-proceed return errors.New("peer disconnected") }, + nil, ) }, steps: []interface{}{ @@ -1274,9 +1651,34 @@ }()   // Crunch through all the test steps and execute them for i, step := range tt.steps { + // Auto-expand certain steps to ones with metadata + switch old := step.(type) { + case isWaiting: + new := make(isWaitingWithMeta) + for peer, hashes := range old { + for _, hash := range hashes { + new[peer] = append(new[peer], announce{hash, nil, nil}) + } + } + step = new + + case isScheduled: + new := isScheduledWithMeta{ + tracking: make(map[string][]announce), + fetching: old.fetching, + dangling: old.dangling, + } + for peer, hashes := range old.tracking { + for _, hash := range hashes { + new.tracking[peer] = append(new.tracking[peer], announce{hash, nil, nil}) + } + } + step = new + } + // Process the original or expanded steps switch step := step.(type) { case doTxNotify: - if err := fetcher.Notify(step.peer, step.hashes); err != nil { + if err := fetcher.Notify(step.peer, step.types, step.sizes, step.hashes); err != nil { t.Errorf("step %d: %v", i, err) } <-wait // Fetcher needs to process this, wait until it's done @@ -1307,24 +1709,34 @@ case doFunc: step()   - case isWaiting: + case isWaitingWithMeta: // We need to check that the waiting list (stage 1) internals // match with the expected set. Check the peer->hash mappings // first. - for peer, hashes := range step { + for peer, announces := range step { waiting := fetcher.waitslots[peer] if waiting == nil { t.Errorf("step %d: peer %s missing from waitslots", i, peer) continue } - for _, hash := range hashes { - if _, ok := waiting[hash]; !ok { - t.Errorf("step %d, peer %s: hash %x missing from waitslots", i, peer, hash) + for _, ann := range announces { + if meta, ok := waiting[ann.hash]; !ok { + t.Errorf("step %d, peer %s: hash %x missing from waitslots", i, peer, ann.hash) + } else { + if (meta == nil && (ann.kind != nil || ann.size != nil)) || + (meta != nil && (ann.kind == nil || ann.size == nil)) || + (meta != nil && (meta.kind != *ann.kind || meta.size != *ann.size)) { + t.Errorf("step %d, peer %s, hash %x: waitslot metadata mismatch: want %v, have %v/%v", i, peer, ann.hash, meta, *ann.kind, *ann.size) + } } } - for hash := range waiting { - if !containsHash(hashes, hash) { - t.Errorf("step %d, peer %s: hash %x extra in waitslots", i, peer, hash) + for hash, meta := range waiting { + ann := announce{hash: hash} + if meta != nil { + ann.kind, ann.size = &meta.kind, &meta.size + } + if !containsAnnounce(announces, ann) { + t.Errorf("step %d, peer %s: announce %v extra in waitslots", i, peer, ann) } } } @@ -1334,13 +1746,13 @@ t.Errorf("step %d: peer %s extra in waitslots", i, peer) } } // Peer->hash sets correct, check the hash->peer and timeout sets - for peer, hashes := range step { - for _, hash := range hashes { - if _, ok := fetcher.waitlist[hash][peer]; !ok { - t.Errorf("step %d, hash %x: peer %s missing from waitlist", i, hash, peer) + for peer, announces := range step { + for _, ann := range announces { + if _, ok := fetcher.waitlist[ann.hash][peer]; !ok { + t.Errorf("step %d, hash %x: peer %s missing from waitlist", i, ann.hash, peer) } - if _, ok := fetcher.waittime[hash]; !ok { - t.Errorf("step %d: hash %x missing from waittime", i, hash) + if _, ok := fetcher.waittime[ann.hash]; !ok { + t.Errorf("step %d: hash %x missing from waittime", i, ann.hash) } } } @@ -1349,15 +1761,15 @@ if len(peers) == 0 { t.Errorf("step %d, hash %x: empty peerset in waitlist", i, hash) } for peer := range peers { - if !containsHash(step[peer], hash) { + if !containsHashInAnnounces(step[peer], hash) { t.Errorf("step %d, hash %x: peer %s extra in waitlist", i, hash, peer) } } } for hash := range fetcher.waittime { var found bool - for _, hashes := range step { - if containsHash(hashes, hash) { + for _, announces := range step { + if containsHashInAnnounces(announces, hash) { found = true break } @@ -1367,23 +1779,33 @@ t.Errorf("step %d,: hash %x extra in waittime", i, hash) } }   - case isScheduled: + case isScheduledWithMeta: // Check that all scheduled announces are accounted for and no // extra ones are present. - for peer, hashes := range step.tracking { + for peer, announces := range step.tracking { scheduled := fetcher.announces[peer] if scheduled == nil { t.Errorf("step %d: peer %s missing from announces", i, peer) continue } - for _, hash := range hashes { - if _, ok := scheduled[hash]; !ok { - t.Errorf("step %d, peer %s: hash %x missing from announces", i, peer, hash) + for _, ann := range announces { + if meta, ok := scheduled[ann.hash]; !ok { + t.Errorf("step %d, peer %s: hash %x missing from announces", i, peer, ann.hash) + } else { + if (meta == nil && (ann.kind != nil || ann.size != nil)) || + (meta != nil && (ann.kind == nil || ann.size == nil)) || + (meta != nil && (meta.kind != *ann.kind || meta.size != *ann.size)) { + t.Errorf("step %d, peer %s, hash %x: announce metadata mismatch: want %v, have %v/%v", i, peer, ann.hash, meta, *ann.kind, *ann.size) + } } } - for hash := range scheduled { - if !containsHash(hashes, hash) { - t.Errorf("step %d, peer %s: hash %x extra in announces", i, peer, hash) + for hash, meta := range scheduled { + ann := announce{hash: hash} + if meta != nil { + ann.kind, ann.size = &meta.kind, &meta.size + } + if !containsAnnounce(announces, ann) { + t.Errorf("step %d, peer %s: announce %x extra in announces", i, peer, hash) } } } @@ -1483,17 +1905,17 @@ // Check that all transaction announces that are scheduled for // retrieval but not actively being downloaded are tracked only // in the stage 2 `announced` map. var queued []common.Hash - for _, hashes := range step.tracking { - for _, hash := range hashes { + for _, announces := range step.tracking { + for _, ann := range announces { var found bool for _, hs := range step.fetching { - if containsHash(hs, hash) { + if containsHash(hs, ann.hash) { found = true break } } if !found { - queued = append(queued, hash) + queued = append(queued, ann.hash) } } } @@ -1509,8 +1931,8 @@ } }   case isUnderpriced: - if fetcher.underpriced.Cardinality() != int(step) { - t.Errorf("step %d: underpriced set size mismatch: have %d, want %d", i, fetcher.underpriced.Cardinality(), step) + if fetcher.underpriced.Len() != int(step) { + t.Errorf("step %d: underpriced set size mismatch: have %d, want %d", i, fetcher.underpriced.Len(), step) }   default: @@ -1526,6 +1948,42 @@ } } }   +// containsAnnounce returns whether an announcement is contained within a slice +// of announcements. +func containsAnnounce(slice []announce, ann announce) bool { + for _, have := range slice { + if have.hash == ann.hash { + if have.kind == nil || ann.kind == nil { + if have.kind != ann.kind { + return false + } + } else if *have.kind != *ann.kind { + return false + } + if have.size == nil || ann.size == nil { + if have.size != ann.size { + return false + } + } else if *have.size != *ann.size { + return false + } + return true + } + } + return false +} + +// containsHashInAnnounces returns whether a hash is contained within a slice +// of announcements. +func containsHashInAnnounces(slice []announce, hash common.Hash) bool { + for _, have := range slice { + if have.hash == hash { + return true + } + } + return false +} + // containsHash returns whether a hash is contained within a hash slice. func containsHash(slice []common.Hash, hash common.Hash) bool { for _, have := range slice { @@ -1535,3 +1993,38 @@ } } return false } + +// Tests that a transaction is forgotten after the timeout. +func TestTransactionForgotten(t *testing.T) { + fetcher := NewTxFetcher( + func(common.Hash) bool { return false }, + func(txs []*types.Transaction) []error { + errs := make([]error, len(txs)) + for i := 0; i < len(errs); i++ { + errs[i] = txpool.ErrUnderpriced + } + return errs + }, + func(string, []common.Hash) error { return nil }, + func(string) {}, + ) + fetcher.Start() + defer fetcher.Stop() + // Create one TX which is 5 minutes old, and one which is recent + tx1 := types.NewTx(&types.LegacyTx{Nonce: 0}) + tx1.SetTime(time.Now().Add(-maxTxUnderpricedTimeout - 1*time.Second)) + tx2 := types.NewTx(&types.LegacyTx{Nonce: 1}) + + // Enqueue both in the fetcher. They will be immediately tagged as underpriced + if err := fetcher.Enqueue("asdf", []*types.Transaction{tx1, tx2}, false); err != nil { + t.Fatal(err) + } + // isKnownUnderpriced should trigger removal of the first tx (no longer be known underpriced) + if fetcher.isKnownUnderpriced(tx1.Hash()) { + t.Fatal("transaction should be forgotten by now") + } + // isKnownUnderpriced should not trigger removal of the second + if !fetcher.isKnownUnderpriced(tx2.Hash()) { + t.Fatal("transaction should be known underpriced") + } +}
diff --git ethereum/go-ethereum/eth/catalyst/api.go taikoxyz/taiko-geth/eth/catalyst/api.go index 1a221941427a0c935fc8a69d1be6c7ab534ac75c..7fbd918e02a87fd384dcee3eb69987b9cc0e1056 100644 --- ethereum/go-ethereum/eth/catalyst/api.go +++ taikoxyz/taiko-geth/eth/catalyst/api.go @@ -78,6 +78,7 @@ // All methods provided over the engine endpoint. var caps = []string{ "engine_forkchoiceUpdatedV1", "engine_forkchoiceUpdatedV2", + "engine_forkchoiceUpdatedV3", "engine_exchangeTransitionConfigurationV1", "engine_getPayloadV1", "engine_getPayloadV2", @@ -135,6 +136,13 @@ // NewConsensusAPI creates a new consensus api for the given backend. // The underlying blockchain needs to have a valid terminal total difficulty set. func NewConsensusAPI(eth *eth.Ethereum) *ConsensusAPI { + api := newConsensusAPIWithoutHeartbeat(eth) + go api.heartbeat() + return api +} + +// newConsensusAPIWithoutHeartbeat creates a new consensus api for the SimulatedBeacon Node. +func newConsensusAPIWithoutHeartbeat(eth *eth.Ethereum) *ConsensusAPI { if eth.BlockChain().Config().TerminalTotalDifficulty == nil { log.Warn("Engine API started but chain not configured for merge yet") } @@ -146,8 +154,6 @@ invalidBlocksHits: make(map[common.Hash]int), invalidTipsets: make(map[common.Hash]*types.Header), } eth.Downloader().SetBadBlockCallback(api.setInvalidAncestor) - go api.heartbeat() - return api }   @@ -187,18 +193,37 @@ } return api.forkchoiceUpdated(update, payloadAttributes) }   -func (api *ConsensusAPI) verifyPayloadAttributes(attr *engine.PayloadAttributes) error { - if !api.eth.BlockChain().Config().IsShanghai(api.eth.BlockChain().Config().LondonBlock, attr.Timestamp) { - // Reject payload attributes with withdrawals before shanghai - if attr.Withdrawals != nil { - return errors.New("withdrawals before shanghai") - } - } else { - // Reject payload attributes with nil withdrawals after shanghai - if attr.Withdrawals == nil { - return errors.New("missing withdrawals list") +// ForkchoiceUpdatedV3 is equivalent to V2 with the addition of parent beacon block root in the payload attributes. +func (api *ConsensusAPI) ForkchoiceUpdatedV3(update engine.ForkchoiceStateV1, payloadAttributes *engine.PayloadAttributes) (engine.ForkChoiceResponse, error) { + if payloadAttributes != nil { + if err := api.verifyPayloadAttributes(payloadAttributes); err != nil { + return engine.STATUS_INVALID, engine.InvalidParams.With(err) } } + return api.forkchoiceUpdated(update, payloadAttributes) +} + +func (api *ConsensusAPI) verifyPayloadAttributes(attr *engine.PayloadAttributes) error { + c := api.eth.BlockChain().Config() + + // Verify withdrawals attribute for Shanghai. + if err := checkAttribute(c.IsShanghai, attr.Withdrawals != nil, c.LondonBlock, attr.Timestamp); err != nil { + return fmt.Errorf("invalid withdrawals: %w", err) + } + // Verify beacon root attribute for Cancun. + if err := checkAttribute(c.IsCancun, attr.BeaconRoot != nil, c.LondonBlock, attr.Timestamp); err != nil { + return fmt.Errorf("invalid parent beacon block root: %w", err) + } + return nil +} + +func checkAttribute(active func(*big.Int, uint64) bool, exists bool, block *big.Int, time uint64) error { + if active(block, time) && !exists { + return errors.New("fork active, missing expected attribute") + } + if !active(block, time) && exists { + return errors.New("fork inactive, unexpected attribute set") + } return nil }   @@ -286,6 +311,10 @@ PayloadStatus: engine.PayloadStatusV1{Status: engine.VALID, LatestValidHash: &update.HeadBlockHash}, PayloadID: id, } } + + // CHANGE(taiko): check whether --taiko flag is set. + isTaiko := api.eth.BlockChain().Config().Taiko + if rawdb.ReadCanonicalHash(api.eth.ChainDb(), block.NumberU64()) != update.HeadBlockHash { // Block is not canonical, set head. if latestValid, err := api.eth.BlockChain().SetCanonical(block); err != nil { @@ -295,6 +324,10 @@ } else if api.eth.BlockChain().CurrentBlock().Hash() == update.HeadBlockHash { // If the specified head matches with our local head, do nothing and keep // generating the payload. It's a special corner case that a few slots are // missing and we are requested to generate the payload in slot. + } else if isTaiko { // CHANGE(taiko): reorg is allowed in L2. + if latestValid, err := api.eth.BlockChain().SetCanonical(block); err != nil { + return engine.ForkChoiceResponse{PayloadStatus: engine.PayloadStatusV1{Status: engine.INVALID, LatestValidHash: &latestValid}}, err + } } else { // If the head block is already in our canonical chain, the beacon client is // probably resyncing. Ignore the update. @@ -339,12 +372,62 @@ // If payload generation was requested, create a new block to be potentially // sealed by the beacon client. The payload will be requested later, and we // will replace it arbitrarily many times in between. if payloadAttributes != nil { + // CHANGE(taiko): create a L2 block by Taiko protocol. + if isTaiko { + // No need to check payloadAttribute here, because all its fields are + // marked as required. + block, err := api.eth.Miner().SealBlockWith( + update.HeadBlockHash, + payloadAttributes.Timestamp, + payloadAttributes.BlockMetadata, + payloadAttributes.BaseFeePerGas, + payloadAttributes.Withdrawals, + ) + if err != nil { + log.Error("Failed to create sealing block", "err", err) + return valid(nil), engine.InvalidPayloadAttributes.With(err) + } + + // Cache the mined block for later use. + args := &miner.BuildPayloadArgs{ + Parent: block.ParentHash(), + Timestamp: block.Time(), + FeeRecipient: block.Coinbase(), + Random: block.MixDigest(), + Withdrawals: block.Withdrawals(), + } + id := args.Id() + payload, err := api.eth.Miner().BuildPayload(args) + if err != nil { + log.Error("Failed to build payload", "err", err) + return valid(nil), engine.InvalidPayloadAttributes.With(err) + } + + payload.SetFullBlock(block, common.Big0) + + api.localBlocks.put(id, payload) + + // L1Origin **MUST NOT** be nil, it's a required field in PayloadAttributesV1. + l1Origin := payloadAttributes.L1Origin + + // Set the block hash before inserting the L1Origin into database. + l1Origin.L2BlockHash = block.Hash() + + // Write L1Origin. + rawdb.WriteL1Origin(api.eth.ChainDb(), l1Origin.BlockID, l1Origin) + // Write the head L1Origin. + rawdb.WriteHeadL1Origin(api.eth.ChainDb(), l1Origin.BlockID) + + return valid(&id), nil + } + args := &miner.BuildPayloadArgs{ Parent: update.HeadBlockHash, Timestamp: payloadAttributes.Timestamp, FeeRecipient: payloadAttributes.SuggestedFeeRecipient, Random: payloadAttributes.Random, Withdrawals: payloadAttributes.Withdrawals, + BeaconRoot: payloadAttributes.BeaconRoot, } id := args.Id() // If we already are busy generating this work, then we do not need @@ -395,7 +478,7 @@ }   // GetPayloadV1 returns a cached payload by id. func (api *ConsensusAPI) GetPayloadV1(payloadID engine.PayloadID) (*engine.ExecutableData, error) { - data, err := api.getPayload(payloadID) + data, err := api.getPayload(payloadID, false) if err != nil { return nil, err } @@ -404,17 +487,17 @@ }   // GetPayloadV2 returns a cached payload by id. func (api *ConsensusAPI) GetPayloadV2(payloadID engine.PayloadID) (*engine.ExecutionPayloadEnvelope, error) { - return api.getPayload(payloadID) + return api.getPayload(payloadID, false) }   // GetPayloadV3 returns a cached payload by id. func (api *ConsensusAPI) GetPayloadV3(payloadID engine.PayloadID) (*engine.ExecutionPayloadEnvelope, error) { - return api.getPayload(payloadID) + return api.getPayload(payloadID, false) }   -func (api *ConsensusAPI) getPayload(payloadID engine.PayloadID) (*engine.ExecutionPayloadEnvelope, error) { +func (api *ConsensusAPI) getPayload(payloadID engine.PayloadID, full bool) (*engine.ExecutionPayloadEnvelope, error) { log.Trace("Engine API request received", "method", "GetPayload", "id", payloadID) - data := api.localBlocks.get(payloadID, true) + data := api.localBlocks.get(payloadID, full) if data == nil { return nil, engine.UnknownPayload } @@ -426,13 +509,14 @@ func (api *ConsensusAPI) NewPayloadV1(params engine.ExecutableData) (engine.PayloadStatusV1, error) { if params.Withdrawals != nil { return engine.PayloadStatusV1{Status: engine.INVALID}, engine.InvalidParams.With(errors.New("withdrawals not supported in V1")) } - return api.newPayload(params, nil) + return api.newPayload(params, nil, nil) }   // NewPayloadV2 creates an Eth1 block, inserts it in the chain, and returns the status of the chain. func (api *ConsensusAPI) NewPayloadV2(params engine.ExecutableData) (engine.PayloadStatusV1, error) { if api.eth.BlockChain().Config().IsShanghai(new(big.Int).SetUint64(params.Number), params.Timestamp) { - if params.Withdrawals == nil { + if params.Withdrawals == nil && + (api.eth.BlockChain().Config().Taiko && params.WithdrawalsHash == (common.Hash{})) { // CHANGE(taiko): allow only passing `WithdrawalsHash` return engine.PayloadStatusV1{Status: engine.INVALID}, engine.InvalidParams.With(errors.New("nil withdrawals post-shanghai")) } } else if params.Withdrawals != nil { @@ -441,26 +525,32 @@ } if api.eth.BlockChain().Config().IsCancun(new(big.Int).SetUint64(params.Number), params.Timestamp) { return engine.PayloadStatusV1{Status: engine.INVALID}, engine.InvalidParams.With(errors.New("newPayloadV2 called post-cancun")) } - return api.newPayload(params, nil) + return api.newPayload(params, nil, nil) }   // NewPayloadV3 creates an Eth1 block, inserts it in the chain, and returns the status of the chain. -func (api *ConsensusAPI) NewPayloadV3(params engine.ExecutableData, versionedHashes *[]common.Hash) (engine.PayloadStatusV1, error) { - if !api.eth.BlockChain().Config().IsCancun(new(big.Int).SetUint64(params.Number), params.Timestamp) { - return engine.PayloadStatusV1{Status: engine.INVALID}, engine.InvalidParams.With(errors.New("newPayloadV3 called pre-cancun")) - } - +func (api *ConsensusAPI) NewPayloadV3(params engine.ExecutableData, versionedHashes []common.Hash, beaconRoot *common.Hash) (engine.PayloadStatusV1, error) { if params.ExcessBlobGas == nil { return engine.PayloadStatusV1{Status: engine.INVALID}, engine.InvalidParams.With(errors.New("nil excessBlobGas post-cancun")) } - var hashes []common.Hash - if versionedHashes != nil { - hashes = *versionedHashes + if params.BlobGasUsed == nil { + return engine.PayloadStatusV1{Status: engine.INVALID}, engine.InvalidParams.With(errors.New("nil params.BlobGasUsed post-cancun")) + } + if versionedHashes == nil { + return engine.PayloadStatusV1{Status: engine.INVALID}, engine.InvalidParams.With(errors.New("nil versionedHashes post-cancun")) + } + if beaconRoot == nil { + return engine.PayloadStatusV1{Status: engine.INVALID}, engine.InvalidParams.With(errors.New("nil parentBeaconBlockRoot post-cancun")) + } + + if !api.eth.BlockChain().Config().IsCancun(new(big.Int).SetUint64(params.Number), params.Timestamp) { + return engine.PayloadStatusV1{Status: engine.INVALID}, engine.UnsupportedFork.With(errors.New("newPayloadV3 called pre-cancun")) } - return api.newPayload(params, hashes) + + return api.newPayload(params, versionedHashes, beaconRoot) }   -func (api *ConsensusAPI) newPayload(params engine.ExecutableData, versionedHashes []common.Hash) (engine.PayloadStatusV1, error) { +func (api *ConsensusAPI) newPayload(params engine.ExecutableData, versionedHashes []common.Hash, beaconRoot *common.Hash) (engine.PayloadStatusV1, error) { // The locking here is, strictly, not required. Without these locks, this can happen: // // 1. NewPayload( execdata-N ) is invoked from the CL. It goes all the way down to @@ -478,10 +568,37 @@ api.newPayloadLock.Lock() defer api.newPayloadLock.Unlock()   log.Trace("Engine API request received", "method", "NewPayload", "number", params.Number, "hash", params.BlockHash) - block, err := engine.ExecutableDataToBlock(params, versionedHashes) - if err != nil { - log.Warn("Invalid NewPayload params", "params", params, "error", err) - return engine.PayloadStatusV1{Status: engine.INVALID}, nil + // CHANGE(taiko): allow passing the executable data with txHash instead of all transactions. + var ( + block *types.Block + err error + ) + params.TaikoBlock = api.eth.BlockChain().Config().Taiko + if api.eth.BlockChain().Config().Taiko && params.Transactions == nil && params.Withdrawals == nil { + block = types.NewBlockWithHeader(&types.Header{ + ParentHash: params.ParentHash, + UncleHash: types.EmptyUncleHash, + Coinbase: params.FeeRecipient, + Root: params.StateRoot, + TxHash: params.TxHash, + ReceiptHash: params.ReceiptsRoot, + Bloom: types.BytesToBloom(params.LogsBloom), + Difficulty: common.Big0, + Number: new(big.Int).SetUint64(params.Number), + GasLimit: params.GasLimit, + GasUsed: params.GasUsed, + Time: params.Timestamp, + BaseFee: params.BaseFeePerGas, + Extra: params.ExtraData, + MixDigest: params.Random, + WithdrawalsHash: &params.WithdrawalsHash, + }) + } else { + block, err = engine.ExecutableDataToBlock(params, versionedHashes, beaconRoot) + if err != nil { + log.Debug("Invalid NewPayload params", "params", params, "error", err) + return engine.PayloadStatusV1{Status: engine.INVALID}, nil + } } // Stash away the last update to warn the user if the beacon client goes offline api.lastNewPayloadLock.Lock() @@ -524,11 +641,20 @@ if parent.Difficulty().BitLen() > 0 && gptd != nil && gptd.Cmp(ttd) >= 0 { log.Error("Ignoring pre-merge parent block", "number", params.Number, "hash", params.BlockHash, "td", ptd, "ttd", ttd) return engine.INVALID_TERMINAL_BLOCK, nil } - if block.Time() <= parent.Time() { - log.Warn("Invalid timestamp", "parent", block.Time(), "block", block.Time()) - return api.invalid(errors.New("invalid timestamp"), parent.Header()), nil + // CHANGE(taiko): a block that has the same timestamp as its parents is + // allowed in Taiko protocol. + if api.eth.BlockChain().Config().Taiko { + if block.Time() < parent.Time() { + log.Warn("Invalid timestamp", "parent", block.Time(), "block", block.Time()) + return api.invalid(errors.New("invalid timestamp"), parent.Header()), nil + } + } else { + if block.Time() <= parent.Time() { + log.Warn("Invalid timestamp", "parent", block.Time(), "block", block.Time()) + return api.invalid(errors.New("invalid timestamp"), parent.Header()), nil + } } - // Another cornercase: if the node is in snap sync mode, but the CL client + // Another corner case: if the node is in snap sync mode, but the CL client // tries to make it import a block. That should be denied as pushing something // into the database directly will conflict with the assumptions of snap sync // that it has an empty db that it can fill itself. @@ -662,20 +788,21 @@ ValidationError: &failure, } }   -// invalid returns a response "INVALID" with the latest valid hash supplied by latest or to the current head -// if no latestValid block was provided. +// invalid returns a response "INVALID" with the latest valid hash supplied by latest. func (api *ConsensusAPI) invalid(err error, latestValid *types.Header) engine.PayloadStatusV1 { - currentHash := api.eth.BlockChain().CurrentBlock().Hash() + var currentHash *common.Hash if latestValid != nil { - // Set latest valid hash to 0x0 if parent is PoW block - currentHash = common.Hash{} - if latestValid.Difficulty.BitLen() == 0 { + if latestValid.Difficulty.BitLen() != 0 { + // Set latest valid hash to 0x0 if parent is PoW block + currentHash = &common.Hash{} + } else { // Otherwise set latest valid hash to parent hash - currentHash = latestValid.Hash() + h := latestValid.Hash() + currentHash = &h } } errorMsg := err.Error() - return engine.PayloadStatusV1{Status: engine.INVALID, LatestValidHash: &currentHash, ValidationError: &errorMsg} + return engine.PayloadStatusV1{Status: engine.INVALID, LatestValidHash: currentHash, ValidationError: &errorMsg} }   // heartbeat loops indefinitely, and checks if there have been beacon client updates @@ -744,7 +871,7 @@ // GetPayloadBodiesByHashV1 implements engine_getPayloadBodiesByHashV1 which allows for retrieval of a list // of block bodies by the engine api. func (api *ConsensusAPI) GetPayloadBodiesByHashV1(hashes []common.Hash) []*engine.ExecutionPayloadBodyV1 { - var bodies = make([]*engine.ExecutionPayloadBodyV1, len(hashes)) + bodies := make([]*engine.ExecutionPayloadBodyV1, len(hashes)) for i, hash := range hashes { block := api.eth.BlockChain().GetBlockByHash(hash) bodies[i] = getBody(block)
diff --git ethereum/go-ethereum/eth/downloader/skeleton.go taikoxyz/taiko-geth/eth/downloader/skeleton.go index 79f4e37dc70a0bdd9a916af63a901c64fc45f2ac..4f1f4620481dd1f9da07a4eaa17a99ca98bbe7c3 100644 --- ethereum/go-ethereum/eth/downloader/skeleton.go +++ taikoxyz/taiko-geth/eth/downloader/skeleton.go @@ -423,7 +423,7 @@ s.idles = make(map[string]*peerConnection) for _, peer := range s.peers.AllPeers() { s.idles[peer.id] = peer } - // Nofity any tester listening for startup events + // Notify any tester listening for startup events if s.syncStarting != nil { s.syncStarting() } @@ -648,7 +648,7 @@ return true } if parent := rawdb.ReadSkeletonHeader(s.db, number-1); parent.Hash() != head.ParentHash { if force { - log.Warn("Beacon chain forked", "ancestor", parent.Number, "hash", parent.Hash(), "want", head.ParentHash) + log.Warn("Beacon chain forked", "ancestor", number-1, "hash", parent.Hash(), "want", head.ParentHash) } return true } @@ -794,7 +794,7 @@ s.drop(peer.id)   case res := <-resCh: // Headers successfully retrieved, update the metrics - headers := *res.Res.(*eth.BlockHeadersPacket) + headers := *res.Res.(*eth.BlockHeadersRequest)   headerReqTimer.Update(time.Since(start)) s.peers.rates.Update(peer.id, eth.BlockHeadersMsg, res.Time, len(headers))
diff --git ethereum/go-ethereum/eth/downloader/queue.go taikoxyz/taiko-geth/eth/downloader/queue.go index c1df3b4e66b0b25aa4a7eb10a82bdf7723c67245..e55715879772dcef0dd8ee94fce7d034508721a7 100644 --- ethereum/go-ethereum/eth/downloader/queue.go +++ taikoxyz/taiko-geth/eth/downloader/queue.go @@ -798,7 +798,7 @@ return errInvalidBody } } // Blocks must have a number of blobs corresponding to the header gas usage, - // and zero before the Cancun hardfork + // and zero before the Cancun hardfork. var blobs int for _, tx := range txLists[index] { // Count the number of blobs to validate against the header's blobGasUsed @@ -813,6 +813,9 @@ for _, hash := range tx.BlobHashes() { if hash[0] != params.BlobTxHashVersion { return errInvalidBody } + } + if tx.BlobTxSidecar() != nil { + return errInvalidBody } } }
diff --git ethereum/go-ethereum/eth/filters/filter_system_test.go taikoxyz/taiko-geth/eth/filters/filter_system_test.go index 8f06dff1c59489bd4c635776e8ffffdcddc9f021..b5d716ae594b620efebe7fd825b9ec9b637a6f74 100644 --- ethereum/go-ethereum/eth/filters/filter_system_test.go +++ taikoxyz/taiko-geth/eth/filters/filter_system_test.go @@ -121,7 +121,7 @@ return nil, nil }   func (b *testBackend) GetLogs(ctx context.Context, hash common.Hash, number uint64) ([][]*types.Log, error) { - logs := rawdb.ReadLogs(b.db, hash, number, params.TestChainConfig) + logs := rawdb.ReadLogs(b.db, hash, number) return logs, nil }
diff --git ethereum/go-ethereum/eth/filters/filter_test.go taikoxyz/taiko-geth/eth/filters/filter_test.go index 8eea0a267892a863fd50c6ccc29e60d6e2457fd3..a076fb7377787e7135d61dfc711faea9b7ea3ede 100644 --- ethereum/go-ethereum/eth/filters/filter_test.go +++ taikoxyz/taiko-geth/eth/filters/filter_test.go @@ -86,7 +86,7 @@ }) // The test txs are not properly signed, can't simply create a chain // and then import blocks. TODO(rjl493456442) try to get rid of the // manual database writes. - gspec.MustCommit(db) + gspec.MustCommit(db, trie.NewDatabase(db, trie.HashDefaults))   for i, block := range chain { rawdb.WriteBlock(db, block) @@ -180,7 +180,7 @@ }   // Hack: GenerateChainWithGenesis creates a new db. // Commit the genesis manually and use GenerateChain. - _, err = gspec.Commit(db, trie.NewDatabase(db)) + _, err = gspec.Commit(db, trie.NewDatabase(db, nil)) if err != nil { t.Fatal(err) }
diff --git ethereum/go-ethereum/eth/downloader/fetchers.go taikoxyz/taiko-geth/eth/downloader/fetchers.go index 021e8c4f9bf334898ca60ef587f13bdabed34adb..cc4279b0da7a1d24b6a9f84d94864984fefc400a 100644 --- ethereum/go-ethereum/eth/downloader/fetchers.go +++ taikoxyz/taiko-geth/eth/downloader/fetchers.go @@ -58,14 +58,14 @@ case res := <-resCh: // Headers successfully retrieved, update the metrics headerReqTimer.Update(time.Since(start)) - headerInMeter.Mark(int64(len(*res.Res.(*eth.BlockHeadersPacket)))) + headerInMeter.Mark(int64(len(*res.Res.(*eth.BlockHeadersRequest))))   // Don't reject the packet even if it turns out to be bad, downloader will // disconnect the peer on its own terms. Simply delivery the headers to // be processed by the caller res.Done <- nil   - return *res.Res.(*eth.BlockHeadersPacket), res.Meta.([]common.Hash), nil + return *res.Res.(*eth.BlockHeadersRequest), res.Meta.([]common.Hash), nil } }   @@ -103,13 +103,13 @@ case res := <-resCh: // Headers successfully retrieved, update the metrics headerReqTimer.Update(time.Since(start)) - headerInMeter.Mark(int64(len(*res.Res.(*eth.BlockHeadersPacket)))) + headerInMeter.Mark(int64(len(*res.Res.(*eth.BlockHeadersRequest))))   // Don't reject the packet even if it turns out to be bad, downloader will // disconnect the peer on its own terms. Simply delivery the headers to // be processed by the caller res.Done <- nil   - return *res.Res.(*eth.BlockHeadersPacket), res.Meta.([]common.Hash), nil + return *res.Res.(*eth.BlockHeadersRequest), res.Meta.([]common.Hash), nil } }
diff --git ethereum/go-ethereum/eth/ethconfig/config.go taikoxyz/taiko-geth/eth/ethconfig/config.go index 4bc8b8dc6c6e5c0ad63855d38290742f1b1f6b7f..ab59112b34f0a605c154027af700bcd2e13a1971 100644 --- ethereum/go-ethereum/eth/ethconfig/config.go +++ taikoxyz/taiko-geth/eth/ethconfig/config.go @@ -26,6 +26,7 @@ "github.com/ethereum/go-ethereum/consensus" "github.com/ethereum/go-ethereum/consensus/beacon" "github.com/ethereum/go-ethereum/consensus/clique" "github.com/ethereum/go-ethereum/consensus/ethash" + "github.com/ethereum/go-ethereum/consensus/taiko" "github.com/ethereum/go-ethereum/core" "github.com/ethereum/go-ethereum/core/txpool/blobpool" "github.com/ethereum/go-ethereum/core/txpool/legacypool" @@ -61,6 +62,8 @@ var Defaults = Config{ SyncMode: downloader.SnapSync, NetworkId: 1, TxLookupLimit: 2350000, + TransactionHistory: 2350000, + StateHistory: params.FullImmutabilityThreshold, LightPeers: 100, DatabaseCache: 512, TrieCleanCache: 154, @@ -79,7 +82,7 @@ }   //go:generate go run github.com/fjl/gencodec -type Config -formats toml -out gen_config.go   -// Config contains configuration options for of the ETH and LES protocols. +// Config contains configuration options for ETH and LES protocols. type Config struct { // The genesis block, which is inserted if the database is empty. // If nil, the Ethereum main net block is used. @@ -97,7 +100,15 @@ NoPruning bool // Whether to disable pruning and flush everything to disk NoPrefetch bool // Whether to disable prefetching and only load state on demand   - TxLookupLimit uint64 `toml:",omitempty"` // The maximum number of blocks from head whose tx indices are reserved. + // Deprecated, use 'TransactionHistory' instead. + TxLookupLimit uint64 `toml:",omitempty"` // The maximum number of blocks from head whose tx indices are reserved. + TransactionHistory uint64 `toml:",omitempty"` // The maximum number of blocks from head whose tx indices are reserved. + StateHistory uint64 `toml:",omitempty"` // The maximum number of blocks from head whose state histories are reserved. + + // State scheme represents the scheme used to store ethereum states and trie + // nodes on top. It can be 'hash', 'path', or none which means use the scheme + // consistent with persistent state. + StateScheme string `toml:",omitempty"`   // RequiredBlocks is a set of block number -> hash mappings which must be in the // canonical chain of all remote peers. Setting the option makes geth verify the @@ -164,12 +175,16 @@ // CreateConsensusEngine creates a consensus engine for the given chain config. // Clique is allowed for now to live standalone, but ethash is forbidden and can // only exist on already merged networks. func CreateConsensusEngine(config *params.ChainConfig, db ethdb.Database) (consensus.Engine, error) { + // CHANGE(taiko): use Taiko consensus engine when the --taiko flag is set. + if config.Taiko { + return taiko.New(config), nil + } // If proof-of-authority is requested, set it up if config.Clique != nil { return beacon.New(clique.New(config.Clique, db)), nil } // If defaulting to proof-of-work, enforce an already merged network since - // we cannot run PoW algorithms and more, so we cannot even follow a chain + // we cannot run PoW algorithms anymore, so we cannot even follow a chain // not coordinated by a beacon node. if !config.TerminalTotalDifficultyPassed { return nil, errors.New("ethash is only supported as a historical component of already merged networks")
diff --git ethereum/go-ethereum/eth/catalyst/simulated_beacon.go taikoxyz/taiko-geth/eth/catalyst/simulated_beacon.go index d4b08b7ba8e1f0ab1253ec0fa73682d68b31e0c8..a9a2bb4a9a7b8c6be89efe077c68e11b15e916ab 100644 --- ethereum/go-ethereum/eth/catalyst/simulated_beacon.go +++ taikoxyz/taiko-geth/eth/catalyst/simulated_beacon.go @@ -17,8 +17,8 @@ package catalyst   import ( + "crypto/rand" "errors" - "fmt" "sync" "time"   @@ -31,6 +31,8 @@ "github.com/ethereum/go-ethereum/log" "github.com/ethereum/go-ethereum/node" "github.com/ethereum/go-ethereum/rpc" ) + +const devEpochLength = 32   // withdrawalQueue implements a FIFO queue which holds withdrawals that are // pending inclusion. @@ -90,7 +92,7 @@ HeadBlockHash: block.Hash(), SafeBlockHash: block.Hash(), FinalizedBlockHash: block.Hash(), } - engineAPI := NewConsensusAPI(eth) + engineAPI := newConsensusAPIWithoutHeartbeat(eth)   // if genesis block, send forkchoiceUpdated to trigger transition to PoS if block.Number.Sign() == 0 { @@ -142,33 +144,52 @@ c.feeRecipientLock.Lock() feeRecipient := c.feeRecipient c.feeRecipientLock.Unlock()   + // Reset to CurrentBlock in case of the chain was rewound + if header := c.eth.BlockChain().CurrentBlock(); c.curForkchoiceState.HeadBlockHash != header.Hash() { + finalizedHash := c.finalizedBlockHash(header.Number.Uint64()) + c.setCurrentState(header.Hash(), *finalizedHash) + } + + var random [32]byte + rand.Read(random[:]) fcResponse, err := c.engineAPI.ForkchoiceUpdatedV2(c.curForkchoiceState, &engine.PayloadAttributes{ Timestamp: tstamp, SuggestedFeeRecipient: feeRecipient, Withdrawals: withdrawals, + Random: random, }) if err != nil { - return fmt.Errorf("error calling forkchoice update: %v", err) + return err + } + if fcResponse == engine.STATUS_SYNCING { + return errors.New("chain rewind prevented invocation of payload creation") }   - envelope, err := c.engineAPI.getPayload(*fcResponse.PayloadID) + envelope, err := c.engineAPI.getPayload(*fcResponse.PayloadID, true) if err != nil { - return fmt.Errorf("error retrieving payload: %v", err) + return err } payload := envelope.ExecutionPayload   - // mark the payload as canon + var finalizedHash common.Hash + if payload.Number%devEpochLength == 0 { + finalizedHash = payload.BlockHash + } else { + if fh := c.finalizedBlockHash(payload.Number); fh == nil { + return errors.New("chain rewind interrupted calculation of finalized block hash") + } else { + finalizedHash = *fh + } + } + + // Mark the payload as canon if _, err = c.engineAPI.NewPayloadV2(*payload); err != nil { - return fmt.Errorf("failed to mark payload as canonical: %v", err) + return err } - c.curForkchoiceState = engine.ForkchoiceStateV1{ - HeadBlockHash: payload.BlockHash, - SafeBlockHash: payload.BlockHash, - FinalizedBlockHash: payload.BlockHash, - } - // mark the block containing the payload as canonical + c.setCurrentState(payload.BlockHash, finalizedHash) + // Mark the block containing the payload as canonical if _, err = c.engineAPI.ForkchoiceUpdatedV2(c.curForkchoiceState, nil); err != nil { - return fmt.Errorf("failed to mark block as canonical: %v", err) + return err } c.lastBlockTime = payload.Timestamp return nil @@ -178,7 +199,7 @@ // loopOnDemand runs the block production loop for "on-demand" configuration (period = 0) func (c *SimulatedBeacon) loopOnDemand() { var ( newTxs = make(chan core.NewTxsEvent) - sub = c.eth.TxPool().SubscribeNewTxsEvent(newTxs) + sub = c.eth.TxPool().SubscribeTransactions(newTxs, true) ) defer sub.Unsubscribe()   @@ -189,20 +210,18 @@ return case w := <-c.withdrawals.pending: withdrawals := append(c.withdrawals.gatherPending(9), w) if err := c.sealBlock(withdrawals); err != nil { - log.Error("Error performing sealing-work", "err", err) - return + log.Warn("Error performing sealing work", "err", err) } case <-newTxs: withdrawals := c.withdrawals.gatherPending(10) if err := c.sealBlock(withdrawals); err != nil { - log.Error("Error performing sealing-work", "err", err) - return + log.Warn("Error performing sealing work", "err", err) } } } }   -// loopOnDemand runs the block production loop for non-zero period configuration +// loop runs the block production loop for non-zero period configuration func (c *SimulatedBeacon) loop() { timer := time.NewTimer(0) for { @@ -212,11 +231,37 @@ return case <-timer.C: withdrawals := c.withdrawals.gatherPending(10) if err := c.sealBlock(withdrawals); err != nil { - log.Error("Error performing sealing-work", "err", err) - return + log.Warn("Error performing sealing work", "err", err) + } else { + timer.Reset(time.Second * time.Duration(c.period)) } - timer.Reset(time.Second * time.Duration(c.period)) } + } +} + +// finalizedBlockHash returns the block hash of the finalized block corresponding to the given number +// or nil if doesn't exist in the chain. +func (c *SimulatedBeacon) finalizedBlockHash(number uint64) *common.Hash { + var finalizedNumber uint64 + if number%devEpochLength == 0 { + finalizedNumber = number + } else { + finalizedNumber = (number - 1) / devEpochLength * devEpochLength + } + + if finalizedBlock := c.eth.BlockChain().GetBlockByNumber(finalizedNumber); finalizedBlock != nil { + fh := finalizedBlock.Hash() + return &fh + } + return nil +} + +// setCurrentState sets the current forkchoice state +func (c *SimulatedBeacon) setCurrentState(headHash, finalizedHash common.Hash) { + c.curForkchoiceState = engine.ForkchoiceStateV1{ + HeadBlockHash: headHash, + SafeBlockHash: headHash, + FinalizedBlockHash: finalizedHash, } }
diff --git ethereum/go-ethereum/eth/tracers/api.go taikoxyz/taiko-geth/eth/tracers/api.go index 740a38ab9fbfbda86f350519d2db321d7d17fe78..e8042bf04d14daca65494a75cf82a82673d348df 100644 --- ethereum/go-ethereum/eth/tracers/api.go +++ taikoxyz/taiko-geth/eth/tracers/api.go @@ -18,7 +18,6 @@ package tracers   import ( "bufio" - "bytes" "context" "encoding/json" "errors" @@ -270,6 +269,13 @@ blockCtx = core.NewEVMBlockContext(task.block.Header(), api.chainContext(ctx), nil) ) // Trace all the transactions contained within for i, tx := range task.block.Transactions() { + if i == 0 && api.backend.ChainConfig().Taiko { + if err := tx.MarkAsAnchor(); err != nil { + log.Warn("Mark anchor transaction error", "error", err) + task.results[i] = &txTraceResult{TxHash: tx.Hash(), Error: err.Error()} + break + } + } msg, _ := core.TransactionToMessage(tx, signer, task.block.BaseFee()) txctx := &Context{ BlockHash: task.block.Hash(), @@ -369,8 +375,8 @@ // limit, the trie database will be reconstructed from scratch only // if the relevant state is available in disk. var preferDisk bool if statedb != nil { - s1, s2 := statedb.Database().TrieDB().Size() - preferDisk = s1+s2 > defaultTracechainMemLimit + s1, s2, s3 := statedb.Database().TrieDB().Size() + preferDisk = s1+s2+s3 > defaultTracechainMemLimit } statedb, release, err = api.backend.StateAtBlock(ctx, block, reexec, statedb, false, preferDisk) if err != nil { @@ -453,7 +459,7 @@ // TraceBlock returns the structured logs created during the execution of EVM // and returns them as a JSON object. func (api *API) TraceBlock(ctx context.Context, blob hexutil.Bytes, config *TraceConfig) ([]*txTraceResult, error) { block := new(types.Block) - if err := rlp.Decode(bytes.NewReader(blob), block); err != nil { + if err := rlp.DecodeBytes(blob, block); err != nil { return nil, fmt.Errorf("could not decode block: %v", err) } return api.traceBlock(ctx, block, config) @@ -527,6 +533,11 @@ vmctx = core.NewEVMBlockContext(block.Header(), api.chainContext(ctx), nil) deleteEmptyObjects = chainConfig.IsEIP158(block.Number()) ) for i, tx := range block.Transactions() { + if i == 0 && chainConfig.Taiko { + if err := tx.MarkAsAnchor(); err != nil { + return nil, err + } + } if err := ctx.Err(); err != nil { return nil, err } @@ -604,6 +615,11 @@ signer = types.MakeSigner(api.backend.ChainConfig(), block.Number(), block.Time()) results = make([]*txTraceResult, len(txs)) ) for i, tx := range txs { + if i == 0 && api.backend.ChainConfig().Taiko { + if err := tx.MarkAsAnchor(); err != nil { + return nil, err + } + } // Generate the next state snapshot fast without tracing msg, _ := core.TransactionToMessage(tx, signer, block.BaseFee()) txctx := &Context{ @@ -757,6 +773,11 @@ // Note: This copies the config, to not screw up the main config chainConfig, canon = overrideConfig(chainConfig, config.Overrides) } for i, tx := range block.Transactions() { + if i == 0 && chainConfig.Taiko { + if err := tx.MarkAsAnchor(); err != nil { + return nil, err + } + } // Prepare the transaction for un-traced execution var ( msg, _ = core.TransactionToMessage(tx, signer, block.BaseFee())
diff --git ethereum/go-ethereum/eth/fetcher/block_fetcher.go taikoxyz/taiko-geth/eth/fetcher/block_fetcher.go index 35608031d97926f9131993461e1cf94ae51c8632..8751c4e3ea13c4af35219510eb05893e8ab26a95 100644 --- ethereum/go-ethereum/eth/fetcher/block_fetcher.go +++ taikoxyz/taiko-geth/eth/fetcher/block_fetcher.go @@ -483,7 +483,7 @@ select { case res := <-resCh: res.Done <- nil - f.FilterHeaders(peer, *res.Res.(*eth.BlockHeadersPacket), time.Now().Add(res.Time)) + f.FilterHeaders(peer, *res.Res.(*eth.BlockHeadersRequest), time.Now().Add(res.Time))   case <-timeout.C: // The peer didn't respond in time. The request @@ -541,7 +541,7 @@ select { case res := <-resCh: res.Done <- nil // Ignoring withdrawals here, since the block fetcher is not used post-merge. - txs, uncles, _ := res.Res.(*eth.BlockBodiesPacket).Unpack() + txs, uncles, _ := res.Res.(*eth.BlockBodiesResponse).Unpack() f.FilterBodies(peer, txs, uncles, time.Now())   case <-timeout.C:
diff --git ethereum/go-ethereum/eth/downloader/fetchers_concurrent_receipts.go taikoxyz/taiko-geth/eth/downloader/fetchers_concurrent_receipts.go index 1c853c21844325459d796342e5ee28b45ff2cace..3169f030ba1035a029911ed938cbbceb2fc015cd 100644 --- ethereum/go-ethereum/eth/downloader/fetchers_concurrent_receipts.go +++ taikoxyz/taiko-geth/eth/downloader/fetchers_concurrent_receipts.go @@ -88,7 +88,7 @@ // deliver is responsible for taking a generic response packet from the concurrent // fetcher, unpacking the receipt data and delivering it to the downloader's queue. func (q *receiptQueue) deliver(peer *peerConnection, packet *eth.Response) (int, error) { - receipts := *packet.Res.(*eth.ReceiptsPacket) + receipts := *packet.Res.(*eth.ReceiptsResponse) hashes := packet.Meta.([]common.Hash) // {receipt hashes}   accepted, err := q.queue.DeliverReceipts(peer.id, receipts, hashes)
diff --git ethereum/go-ethereum/eth/downloader/downloader.go taikoxyz/taiko-geth/eth/downloader/downloader.go index 9a805396c4d3bff3d1e8f52ff06676dee3c57cc6..2ca7e328c6c47646e752538551d61b62ed2cd8f0 100644 --- ethereum/go-ethereum/eth/downloader/downloader.go +++ taikoxyz/taiko-geth/eth/downloader/downloader.go @@ -286,11 +286,6 @@ HealingBytecode: pending.BytecodeHeal, } }   -// Synchronising returns whether the downloader is currently retrieving blocks. -func (d *Downloader) Synchronising() bool { - return d.synchronising.Load() -} - // RegisterPeer injects a new download peer into the set of block source to be // used for fetching hashes and blocks from. func (d *Downloader) RegisterPeer(id string, version uint, peer Peer) error { @@ -307,11 +302,6 @@ logger.Error("Failed to register sync peer", "err", err) return err } return nil -} - -// RegisterLightPeer injects a light client peer, wrapping it so it appears as a regular peer. -func (d *Downloader) RegisterLightPeer(id string, version uint, peer LightPeer) error { - return d.RegisterPeer(id, version, &lightPeerWrapper{peer}) }   // UnregisterPeer remove a peer from the known list, preventing any action from @@ -398,7 +388,16 @@ if d.notified.CompareAndSwap(false, true) { log.Info("Block synchronisation started") } if mode == SnapSync { - // Snap sync uses the snapshot namespace to store potentially flakey data until + // Snap sync will directly modify the persistent state, making the entire + // trie database unusable until the state is fully synced. To prevent any + // subsequent state reads, explicitly disable the trie database and state + // syncer is responsible to address and correct any state missing. + if d.blockchain.TrieDB().Scheme() == rawdb.PathScheme { + if err := d.blockchain.TrieDB().Disable(); err != nil { + return err + } + } + // Snap sync uses the snapshot namespace to store potentially flaky data until // sync completely heals and finishes. Pause snapshot maintenance in the mean- // time to prevent access. if snapshots := d.blockchain.Snapshots(); snapshots != nil { // Only nil in tests @@ -1273,41 +1272,13 @@ // processHeaders takes batches of retrieved headers from an input channel and // keeps processing and scheduling them into the header chain and downloader's // queue until the stream ends or a failure occurs. func (d *Downloader) processHeaders(origin uint64, td, ttd *big.Int, beaconMode bool) error { - // Keep a count of uncertain headers to roll back var ( - rollback uint64 // Zero means no rollback (fine as you can't unroll the genesis) - rollbackErr error - mode = d.getMode() + mode = d.getMode() + gotHeaders = false // Wait for batches of headers to process ) - defer func() { - if rollback > 0 { - lastHeader, lastFastBlock, lastBlock := d.lightchain.CurrentHeader().Number, common.Big0, common.Big0 - if mode != LightSync { - lastFastBlock = d.blockchain.CurrentSnapBlock().Number - lastBlock = d.blockchain.CurrentBlock().Number - } - if err := d.lightchain.SetHead(rollback - 1); err != nil { // -1 to target the parent of the first uncertain block - // We're already unwinding the stack, only print the error to make it more visible - log.Error("Failed to roll back chain segment", "head", rollback-1, "err", err) - } - curFastBlock, curBlock := common.Big0, common.Big0 - if mode != LightSync { - curFastBlock = d.blockchain.CurrentSnapBlock().Number - curBlock = d.blockchain.CurrentBlock().Number - } - log.Warn("Rolled back chain segment", - "header", fmt.Sprintf("%d->%d", lastHeader, d.lightchain.CurrentHeader().Number), - "snap", fmt.Sprintf("%d->%d", lastFastBlock, curFastBlock), - "block", fmt.Sprintf("%d->%d", lastBlock, curBlock), "reason", rollbackErr) - } - }() - // Wait for batches of headers to process - gotHeaders := false - for { select { case <-d.cancelCh: - rollbackErr = errCanceled return errCanceled   case task := <-d.headerProcCh: @@ -1356,8 +1327,6 @@ return errStallingPeer } } } - // Disable any rollback and return - rollback = 0 return nil } // Otherwise split the chunk of headers into batches and process them @@ -1368,7 +1337,6 @@ for len(headers) > 0 { // Terminate if something failed in between processing chunks select { case <-d.cancelCh: - rollbackErr = errCanceled return errCanceled default: } @@ -1415,29 +1383,11 @@ } } if len(chunkHeaders) > 0 { if n, err := d.lightchain.InsertHeaderChain(chunkHeaders); err != nil { - rollbackErr = err - - // If some headers were inserted, track them as uncertain - if mode == SnapSync && n > 0 && rollback == 0 { - rollback = chunkHeaders[0].Number.Uint64() - } log.Warn("Invalid header encountered", "number", chunkHeaders[n].Number, "hash", chunkHashes[n], "parent", chunkHeaders[n].ParentHash, "err", err) return fmt.Errorf("%w: %v", errInvalidChain, err) } - // All verifications passed, track all headers within the allowed limits - if mode == SnapSync { - head := chunkHeaders[len(chunkHeaders)-1].Number.Uint64() - if head-rollback > uint64(fsHeaderSafetyNet) { - rollback = head - uint64(fsHeaderSafetyNet) - } else { - rollback = 1 - } - } } if len(rejected) != 0 { - // Merge threshold reached, stop importing, but don't roll back - rollback = 0 - log.Info("Legacy sync reached merge threshold", "number", rejected[0].Number, "hash", rejected[0].Hash(), "td", td, "ttd", ttd) return ErrMergeTransition } @@ -1448,7 +1398,6 @@ // If we've reached the allowed number of pending headers, stall a bit for d.queue.PendingBodies() >= maxQueuedHeaders || d.queue.PendingReceipts() >= maxQueuedHeaders { select { case <-d.cancelCh: - rollbackErr = errCanceled return errCanceled case <-time.After(time.Second): } @@ -1456,7 +1405,6 @@ } // Otherwise insert the headers for content retrieval inserts := d.queue.Schedule(chunkHeaders, chunkHashes, origin) if len(inserts) != len(chunkHeaders) { - rollbackErr = fmt.Errorf("stale headers: len inserts %v len(chunk) %v", len(inserts), len(chunkHeaders)) return fmt.Errorf("%w: stale headers", errBadPeer) } } @@ -1606,17 +1554,30 @@ go closeOnErr(sync)   // To cater for moving pivot points, track the pivot block and subsequently // accumulated download results separately. + // + // These will be nil up to the point where we reach the pivot, and will only + // be set temporarily if the synced blocks are piling up, but the pivot is + // still busy downloading. In that case, we need to occasionally check for + // pivot moves, so need to unblock the loop. These fields will accumulate + // the results in the meantime. + // + // Note, there's no issue with memory piling up since after 64 blocks the + // pivot will forcefully move so these accumulators will be dropped. var ( oldPivot *fetchResult // Locked in pivot block, might change eventually oldTail []*fetchResult // Downloaded content after the pivot ) for { - // Wait for the next batch of downloaded data to be available, and if the pivot - // block became stale, move the goalpost - results := d.queue.Results(oldPivot == nil) // Block if we're not monitoring pivot staleness + // Wait for the next batch of downloaded data to be available. If we have + // not yet reached the pivot point, wait blockingly as there's no need to + // spin-loop check for pivot moves. If we reached the pivot but have not + // yet processed it, check for results async, so we might notice pivot + // moves while state syncing. If the pivot was passed fully, block again + // as there's no more reason to check for pivot moves at all. + results := d.queue.Results(oldPivot == nil) if len(results) == 0 { // If pivot sync is done, stop - if oldPivot == nil { + if d.committed.Load() { d.reportSnapSyncProgress(true) return sync.Cancel() } @@ -1639,21 +1600,23 @@ d.pivotLock.RLock() pivot := d.pivotHeader d.pivotLock.RUnlock()   - if oldPivot == nil { - if pivot.Root != sync.root { - sync.Cancel() - sync = d.syncState(pivot.Root) + if oldPivot == nil { // no results piling up, we can move the pivot + if !d.committed.Load() { // not yet passed the pivot, we can move the pivot + if pivot.Root != sync.root { // pivot position changed, we can move the pivot + sync.Cancel() + sync = d.syncState(pivot.Root)   - go closeOnErr(sync) + go closeOnErr(sync) + } } - } else { + } else { // results already piled up, consume before handling pivot move results = append(append([]*fetchResult{oldPivot}, oldTail...), results...) } // Split around the pivot block and process the two sides via snap/full sync if !d.committed.Load() { latest := results[len(results)-1].Header // If the height is above the pivot block by 2 sets, it means the pivot - // become stale in the network and it was garbage collected, move to a + // become stale in the network, and it was garbage collected, move to a // new pivot. // // Note, we have `reorgProtHeaderDelay` number of blocks withheld, Those
diff --git ethereum/go-ethereum/eth/catalyst/tester.go taikoxyz/taiko-geth/eth/catalyst/tester.go index c4eafd30d918f9ad69e32eaa2f8f5adddcec2bb8..0922ac0ba654541a62c3d2d4b13cb0fc3efb0b3f 100644 --- ethereum/go-ethereum/eth/catalyst/tester.go +++ taikoxyz/taiko-geth/eth/catalyst/tester.go @@ -20,7 +20,7 @@ import ( "sync" "time"   - "github.com/ethereum/go-ethereum/core/types" + "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/eth" "github.com/ethereum/go-ethereum/eth/downloader" "github.com/ethereum/go-ethereum/log" @@ -28,23 +28,27 @@ "github.com/ethereum/go-ethereum/node" )   // FullSyncTester is an auxiliary service that allows Geth to perform full sync -// alone without consensus-layer attached. Users must specify a valid block as -// the sync target. This tester can be applied to different networks, no matter -// it's pre-merge or post-merge, but only for full-sync. +// alone without consensus-layer attached. Users must specify a valid block hash +// as the sync target. +// +// This tester can be applied to different networks, no matter it's pre-merge or +// post-merge, but only for full-sync. type FullSyncTester struct { - api *ConsensusAPI - block *types.Block - closed chan struct{} - wg sync.WaitGroup + stack *node.Node + backend *eth.Ethereum + target common.Hash + closed chan struct{} + wg sync.WaitGroup }   // RegisterFullSyncTester registers the full-sync tester service into the node // stack for launching and stopping the service controlled by node. -func RegisterFullSyncTester(stack *node.Node, backend *eth.Ethereum, block *types.Block) (*FullSyncTester, error) { +func RegisterFullSyncTester(stack *node.Node, backend *eth.Ethereum, target common.Hash) (*FullSyncTester, error) { cl := &FullSyncTester{ - api: NewConsensusAPI(backend), - block: block, - closed: make(chan struct{}), + stack: stack, + backend: backend, + target: target, + closed: make(chan struct{}), } stack.RegisterLifecycle(cl) return cl, nil @@ -56,28 +60,24 @@ tester.wg.Add(1) go func() { defer tester.wg.Done()   + // Trigger beacon sync with the provided block hash as trusted + // chain head. + err := tester.backend.Downloader().BeaconDevSync(downloader.FullSync, tester.target, tester.closed) + if err != nil { + log.Info("Failed to trigger beacon sync", "err", err) + } + ticker := time.NewTicker(time.Second * 5) defer ticker.Stop()   for { select { case <-ticker.C: - // Don't bother downloader in case it's already syncing. - if tester.api.eth.Downloader().Synchronising() { - continue - } - // Short circuit in case the target block is already stored - // locally. TODO(somehow terminate the node stack if target - // is reached). - if tester.api.eth.BlockChain().HasBlock(tester.block.Hash(), tester.block.NumberU64()) { - log.Info("Full-sync target reached", "number", tester.block.NumberU64(), "hash", tester.block.Hash()) + // Stop in case the target block is already stored locally. + if block := tester.backend.BlockChain().GetBlockByHash(tester.target); block != nil { + log.Info("Full-sync target reached", "number", block.NumberU64(), "hash", block.Hash()) + go tester.stack.Close() // async since we need to close ourselves return - } - // Trigger beacon sync with the provided block header as - // trusted chain head. - err := tester.api.eth.Downloader().BeaconSync(downloader.FullSync, tester.block.Header(), nil) - if err != nil { - log.Info("Failed to beacon sync", "err", err) }   case <-tester.closed:
diff --git ethereum/go-ethereum/eth/downloader/downloader_test.go taikoxyz/taiko-geth/eth/downloader/downloader_test.go index 06c22afff092cd5148ea57d17df918fd6b9eba20..e4875b959a37707579f0cc78dbf62029e87ecbe0 100644 --- ethereum/go-ethereum/eth/downloader/downloader_test.go +++ taikoxyz/taiko-geth/eth/downloader/downloader_test.go @@ -177,7 +177,7 @@ // origin; associated with a particular peer in the download tester. The returned // function can be used to retrieve batches of headers from the particular peer. func (dlp *downloadTesterPeer) RequestHeadersByHash(origin common.Hash, amount int, skip int, reverse bool, sink chan *eth.Response) (*eth.Request, error) { // Service the header query via the live handler code - rlpHeaders := eth.ServiceGetBlockHeadersQuery(dlp.chain, &eth.GetBlockHeadersPacket{ + rlpHeaders := eth.ServiceGetBlockHeadersQuery(dlp.chain, &eth.GetBlockHeadersRequest{ Origin: eth.HashOrNumber{ Hash: origin, }, @@ -205,7 +205,7 @@ Peer: dlp.id, } res := &eth.Response{ Req: req, - Res: (*eth.BlockHeadersPacket)(&headers), + Res: (*eth.BlockHeadersRequest)(&headers), Meta: hashes, Time: 1, Done: make(chan error, 1), // Ignore the returned status @@ -221,7 +221,7 @@ // origin; associated with a particular peer in the download tester. The returned // function can be used to retrieve batches of headers from the particular peer. func (dlp *downloadTesterPeer) RequestHeadersByNumber(origin uint64, amount int, skip int, reverse bool, sink chan *eth.Response) (*eth.Request, error) { // Service the header query via the live handler code - rlpHeaders := eth.ServiceGetBlockHeadersQuery(dlp.chain, &eth.GetBlockHeadersPacket{ + rlpHeaders := eth.ServiceGetBlockHeadersQuery(dlp.chain, &eth.GetBlockHeadersRequest{ Origin: eth.HashOrNumber{ Number: origin, }, @@ -249,7 +249,7 @@ Peer: dlp.id, } res := &eth.Response{ Req: req, - Res: (*eth.BlockHeadersPacket)(&headers), + Res: (*eth.BlockHeadersRequest)(&headers), Meta: hashes, Time: 1, Done: make(chan error, 1), // Ignore the returned status @@ -286,7 +286,7 @@ Peer: dlp.id, } res := &eth.Response{ Req: req, - Res: (*eth.BlockBodiesPacket)(&bodies), + Res: (*eth.BlockBodiesResponse)(&bodies), Meta: [][]common.Hash{txsHashes, uncleHashes, withdrawalHashes}, Time: 1, Done: make(chan error, 1), // Ignore the returned status @@ -317,7 +317,7 @@ Peer: dlp.id, } res := &eth.Response{ Req: req, - Res: (*eth.ReceiptsPacket)(&receipts), + Res: (*eth.ReceiptsResponse)(&receipts), Meta: hashes, Time: 1, Done: make(chan error, 1), // Ignore the returned status @@ -437,9 +437,9 @@ t.Fatalf("synchronised receipts mismatch: have %v, want %v", rs, receipts) } }   -func TestCanonicalSynchronisation66Full(t *testing.T) { testCanonSync(t, eth.ETH66, FullSync) } -func TestCanonicalSynchronisation66Snap(t *testing.T) { testCanonSync(t, eth.ETH66, SnapSync) } -func TestCanonicalSynchronisation66Light(t *testing.T) { testCanonSync(t, eth.ETH66, LightSync) } +func TestCanonicalSynchronisation68Full(t *testing.T) { testCanonSync(t, eth.ETH68, FullSync) } +func TestCanonicalSynchronisation68Snap(t *testing.T) { testCanonSync(t, eth.ETH68, SnapSync) } +func TestCanonicalSynchronisation68Light(t *testing.T) { testCanonSync(t, eth.ETH68, LightSync) } func TestCanonicalSynchronisation67Full(t *testing.T) { testCanonSync(t, eth.ETH67, FullSync) } func TestCanonicalSynchronisation67Snap(t *testing.T) { testCanonSync(t, eth.ETH67, SnapSync) } func TestCanonicalSynchronisation67Light(t *testing.T) { testCanonSync(t, eth.ETH67, LightSync) } @@ -461,8 +461,8 @@ }   // Tests that if a large batch of blocks are being downloaded, it is throttled // until the cached blocks are retrieved. -func TestThrottling66Full(t *testing.T) { testThrottling(t, eth.ETH66, FullSync) } -func TestThrottling66Snap(t *testing.T) { testThrottling(t, eth.ETH66, SnapSync) } +func TestThrottling68Full(t *testing.T) { testThrottling(t, eth.ETH68, FullSync) } +func TestThrottling68Snap(t *testing.T) { testThrottling(t, eth.ETH68, SnapSync) } func TestThrottling67Full(t *testing.T) { testThrottling(t, eth.ETH67, FullSync) } func TestThrottling67Snap(t *testing.T) { testThrottling(t, eth.ETH67, SnapSync) }   @@ -543,9 +543,9 @@ // Tests that simple synchronization against a forked chain works correctly. In // this test common ancestor lookup should *not* be short circuited, and a full // binary search should be executed. -func TestForkedSync66Full(t *testing.T) { testForkedSync(t, eth.ETH66, FullSync) } -func TestForkedSync66Snap(t *testing.T) { testForkedSync(t, eth.ETH66, SnapSync) } -func TestForkedSync66Light(t *testing.T) { testForkedSync(t, eth.ETH66, LightSync) } +func TestForkedSync68Full(t *testing.T) { testForkedSync(t, eth.ETH68, FullSync) } +func TestForkedSync68Snap(t *testing.T) { testForkedSync(t, eth.ETH68, SnapSync) } +func TestForkedSync68Light(t *testing.T) { testForkedSync(t, eth.ETH68, LightSync) } func TestForkedSync67Full(t *testing.T) { testForkedSync(t, eth.ETH67, FullSync) } func TestForkedSync67Snap(t *testing.T) { testForkedSync(t, eth.ETH67, SnapSync) } func TestForkedSync67Light(t *testing.T) { testForkedSync(t, eth.ETH67, LightSync) } @@ -573,9 +573,9 @@ }   // Tests that synchronising against a much shorter but much heavier fork works // currently and is not dropped. -func TestHeavyForkedSync66Full(t *testing.T) { testHeavyForkedSync(t, eth.ETH66, FullSync) } -func TestHeavyForkedSync66Snap(t *testing.T) { testHeavyForkedSync(t, eth.ETH66, SnapSync) } -func TestHeavyForkedSync66Light(t *testing.T) { testHeavyForkedSync(t, eth.ETH66, LightSync) } +func TestHeavyForkedSync68Full(t *testing.T) { testHeavyForkedSync(t, eth.ETH68, FullSync) } +func TestHeavyForkedSync68Snap(t *testing.T) { testHeavyForkedSync(t, eth.ETH68, SnapSync) } +func TestHeavyForkedSync68Light(t *testing.T) { testHeavyForkedSync(t, eth.ETH68, LightSync) } func TestHeavyForkedSync67Full(t *testing.T) { testHeavyForkedSync(t, eth.ETH67, FullSync) } func TestHeavyForkedSync67Snap(t *testing.T) { testHeavyForkedSync(t, eth.ETH67, SnapSync) } func TestHeavyForkedSync67Light(t *testing.T) { testHeavyForkedSync(t, eth.ETH67, LightSync) } @@ -605,9 +605,9 @@ // Tests that chain forks are contained within a certain interval of the current // chain head, ensuring that malicious peers cannot waste resources by feeding // long dead chains. -func TestBoundedForkedSync66Full(t *testing.T) { testBoundedForkedSync(t, eth.ETH66, FullSync) } -func TestBoundedForkedSync66Snap(t *testing.T) { testBoundedForkedSync(t, eth.ETH66, SnapSync) } -func TestBoundedForkedSync66Light(t *testing.T) { testBoundedForkedSync(t, eth.ETH66, LightSync) } +func TestBoundedForkedSync68Full(t *testing.T) { testBoundedForkedSync(t, eth.ETH68, FullSync) } +func TestBoundedForkedSync68Snap(t *testing.T) { testBoundedForkedSync(t, eth.ETH68, SnapSync) } +func TestBoundedForkedSync68Light(t *testing.T) { testBoundedForkedSync(t, eth.ETH68, LightSync) } func TestBoundedForkedSync67Full(t *testing.T) { testBoundedForkedSync(t, eth.ETH67, FullSync) } func TestBoundedForkedSync67Snap(t *testing.T) { testBoundedForkedSync(t, eth.ETH67, SnapSync) } func TestBoundedForkedSync67Light(t *testing.T) { testBoundedForkedSync(t, eth.ETH67, LightSync) } @@ -636,14 +636,14 @@ // Tests that chain forks are contained within a certain interval of the current // chain head for short but heavy forks too. These are a bit special because they // take different ancestor lookup paths. -func TestBoundedHeavyForkedSync66Full(t *testing.T) { - testBoundedHeavyForkedSync(t, eth.ETH66, FullSync) +func TestBoundedHeavyForkedSync68Full(t *testing.T) { + testBoundedHeavyForkedSync(t, eth.ETH68, FullSync) } -func TestBoundedHeavyForkedSync66Snap(t *testing.T) { - testBoundedHeavyForkedSync(t, eth.ETH66, SnapSync) +func TestBoundedHeavyForkedSync68Snap(t *testing.T) { + testBoundedHeavyForkedSync(t, eth.ETH68, SnapSync) } -func TestBoundedHeavyForkedSync66Light(t *testing.T) { - testBoundedHeavyForkedSync(t, eth.ETH66, LightSync) +func TestBoundedHeavyForkedSync68Light(t *testing.T) { + testBoundedHeavyForkedSync(t, eth.ETH68, LightSync) } func TestBoundedHeavyForkedSync67Full(t *testing.T) { testBoundedHeavyForkedSync(t, eth.ETH67, FullSync) @@ -678,9 +678,9 @@ } }   // Tests that a canceled download wipes all previously accumulated state. -func TestCancel66Full(t *testing.T) { testCancel(t, eth.ETH66, FullSync) } -func TestCancel66Snap(t *testing.T) { testCancel(t, eth.ETH66, SnapSync) } -func TestCancel66Light(t *testing.T) { testCancel(t, eth.ETH66, LightSync) } +func TestCancel68Full(t *testing.T) { testCancel(t, eth.ETH68, FullSync) } +func TestCancel68Snap(t *testing.T) { testCancel(t, eth.ETH68, SnapSync) } +func TestCancel68Light(t *testing.T) { testCancel(t, eth.ETH68, LightSync) } func TestCancel67Full(t *testing.T) { testCancel(t, eth.ETH67, FullSync) } func TestCancel67Snap(t *testing.T) { testCancel(t, eth.ETH67, SnapSync) } func TestCancel67Light(t *testing.T) { testCancel(t, eth.ETH67, LightSync) } @@ -708,9 +708,9 @@ } }   // Tests that synchronisation from multiple peers works as intended (multi thread sanity test). -func TestMultiSynchronisation66Full(t *testing.T) { testMultiSynchronisation(t, eth.ETH66, FullSync) } -func TestMultiSynchronisation66Snap(t *testing.T) { testMultiSynchronisation(t, eth.ETH66, SnapSync) } -func TestMultiSynchronisation66Light(t *testing.T) { testMultiSynchronisation(t, eth.ETH66, LightSync) } +func TestMultiSynchronisation68Full(t *testing.T) { testMultiSynchronisation(t, eth.ETH68, FullSync) } +func TestMultiSynchronisation68Snap(t *testing.T) { testMultiSynchronisation(t, eth.ETH68, SnapSync) } +func TestMultiSynchronisation68Light(t *testing.T) { testMultiSynchronisation(t, eth.ETH68, LightSync) } func TestMultiSynchronisation67Full(t *testing.T) { testMultiSynchronisation(t, eth.ETH67, FullSync) } func TestMultiSynchronisation67Snap(t *testing.T) { testMultiSynchronisation(t, eth.ETH67, SnapSync) } func TestMultiSynchronisation67Light(t *testing.T) { testMultiSynchronisation(t, eth.ETH67, LightSync) } @@ -735,9 +735,9 @@ }   // Tests that synchronisations behave well in multi-version protocol environments // and not wreak havoc on other nodes in the network. -func TestMultiProtoSynchronisation66Full(t *testing.T) { testMultiProtoSync(t, eth.ETH66, FullSync) } -func TestMultiProtoSynchronisation66Snap(t *testing.T) { testMultiProtoSync(t, eth.ETH66, SnapSync) } -func TestMultiProtoSynchronisation66Light(t *testing.T) { testMultiProtoSync(t, eth.ETH66, LightSync) } +func TestMultiProtoSynchronisation68Full(t *testing.T) { testMultiProtoSync(t, eth.ETH68, FullSync) } +func TestMultiProtoSynchronisation68Snap(t *testing.T) { testMultiProtoSync(t, eth.ETH68, SnapSync) } +func TestMultiProtoSynchronisation68Light(t *testing.T) { testMultiProtoSync(t, eth.ETH68, LightSync) } func TestMultiProtoSynchronisation67Full(t *testing.T) { testMultiProtoSync(t, eth.ETH67, FullSync) } func TestMultiProtoSynchronisation67Snap(t *testing.T) { testMultiProtoSync(t, eth.ETH67, SnapSync) } func TestMultiProtoSynchronisation67Light(t *testing.T) { testMultiProtoSync(t, eth.ETH67, LightSync) } @@ -750,7 +750,7 @@ // Create a small enough block chain to download chain := testChainBase.shorten(blockCacheMaxItems - 15)   // Create peers of every type - tester.newPeer("peer 66", eth.ETH66, chain.blocks[1:]) + tester.newPeer("peer 68", eth.ETH68, chain.blocks[1:]) tester.newPeer("peer 67", eth.ETH67, chain.blocks[1:])   // Synchronise with the requested peer and make sure all blocks were retrieved @@ -760,7 +760,7 @@ } assertOwnChain(t, tester, len(chain.blocks))   // Check that no peers have been dropped off - for _, version := range []int{66, 67} { + for _, version := range []int{68, 67} { peer := fmt.Sprintf("peer %d", version) if _, ok := tester.peers[peer]; !ok { t.Errorf("%s dropped", peer) @@ -770,9 +770,9 @@ }   // Tests that if a block is empty (e.g. header only), no body request should be // made, and instead the header should be assembled into a whole block in itself. -func TestEmptyShortCircuit66Full(t *testing.T) { testEmptyShortCircuit(t, eth.ETH66, FullSync) } -func TestEmptyShortCircuit66Snap(t *testing.T) { testEmptyShortCircuit(t, eth.ETH66, SnapSync) } -func TestEmptyShortCircuit66Light(t *testing.T) { testEmptyShortCircuit(t, eth.ETH66, LightSync) } +func TestEmptyShortCircuit68Full(t *testing.T) { testEmptyShortCircuit(t, eth.ETH68, FullSync) } +func TestEmptyShortCircuit68Snap(t *testing.T) { testEmptyShortCircuit(t, eth.ETH68, SnapSync) } +func TestEmptyShortCircuit68Light(t *testing.T) { testEmptyShortCircuit(t, eth.ETH68, LightSync) } func TestEmptyShortCircuit67Full(t *testing.T) { testEmptyShortCircuit(t, eth.ETH67, FullSync) } func TestEmptyShortCircuit67Snap(t *testing.T) { testEmptyShortCircuit(t, eth.ETH67, SnapSync) } func TestEmptyShortCircuit67Light(t *testing.T) { testEmptyShortCircuit(t, eth.ETH67, LightSync) } @@ -821,9 +821,9 @@ }   // Tests that headers are enqueued continuously, preventing malicious nodes from // stalling the downloader by feeding gapped header chains. -func TestMissingHeaderAttack66Full(t *testing.T) { testMissingHeaderAttack(t, eth.ETH66, FullSync) } -func TestMissingHeaderAttack66Snap(t *testing.T) { testMissingHeaderAttack(t, eth.ETH66, SnapSync) } -func TestMissingHeaderAttack66Light(t *testing.T) { testMissingHeaderAttack(t, eth.ETH66, LightSync) } +func TestMissingHeaderAttack68Full(t *testing.T) { testMissingHeaderAttack(t, eth.ETH68, FullSync) } +func TestMissingHeaderAttack68Snap(t *testing.T) { testMissingHeaderAttack(t, eth.ETH68, SnapSync) } +func TestMissingHeaderAttack68Light(t *testing.T) { testMissingHeaderAttack(t, eth.ETH68, LightSync) } func TestMissingHeaderAttack67Full(t *testing.T) { testMissingHeaderAttack(t, eth.ETH67, FullSync) } func TestMissingHeaderAttack67Snap(t *testing.T) { testMissingHeaderAttack(t, eth.ETH67, SnapSync) } func TestMissingHeaderAttack67Light(t *testing.T) { testMissingHeaderAttack(t, eth.ETH67, LightSync) } @@ -850,9 +850,9 @@ }   // Tests that if requested headers are shifted (i.e. first is missing), the queue // detects the invalid numbering. -func TestShiftedHeaderAttack66Full(t *testing.T) { testShiftedHeaderAttack(t, eth.ETH66, FullSync) } -func TestShiftedHeaderAttack66Snap(t *testing.T) { testShiftedHeaderAttack(t, eth.ETH66, SnapSync) } -func TestShiftedHeaderAttack66Light(t *testing.T) { testShiftedHeaderAttack(t, eth.ETH66, LightSync) } +func TestShiftedHeaderAttack68Full(t *testing.T) { testShiftedHeaderAttack(t, eth.ETH68, FullSync) } +func TestShiftedHeaderAttack68Snap(t *testing.T) { testShiftedHeaderAttack(t, eth.ETH68, SnapSync) } +func TestShiftedHeaderAttack68Light(t *testing.T) { testShiftedHeaderAttack(t, eth.ETH68, LightSync) } func TestShiftedHeaderAttack67Full(t *testing.T) { testShiftedHeaderAttack(t, eth.ETH67, FullSync) } func TestShiftedHeaderAttack67Snap(t *testing.T) { testShiftedHeaderAttack(t, eth.ETH67, SnapSync) } func TestShiftedHeaderAttack67Light(t *testing.T) { testShiftedHeaderAttack(t, eth.ETH67, LightSync) } @@ -878,96 +878,16 @@ } assertOwnChain(t, tester, len(chain.blocks)) }   -// Tests that upon detecting an invalid header, the recent ones are rolled back -// for various failure scenarios. Afterwards a full sync is attempted to make -// sure no state was corrupted. -func TestInvalidHeaderRollback66Snap(t *testing.T) { testInvalidHeaderRollback(t, eth.ETH66, SnapSync) } -func TestInvalidHeaderRollback67Snap(t *testing.T) { testInvalidHeaderRollback(t, eth.ETH67, SnapSync) } - -func testInvalidHeaderRollback(t *testing.T, protocol uint, mode SyncMode) { - tester := newTester(t) - defer tester.terminate() - - // Create a small enough block chain to download - targetBlocks := 3*fsHeaderSafetyNet + 256 + fsMinFullBlocks - chain := testChainBase.shorten(targetBlocks) - - // Attempt to sync with an attacker that feeds junk during the fast sync phase. - // This should result in the last fsHeaderSafetyNet headers being rolled back. - missing := fsHeaderSafetyNet + MaxHeaderFetch + 1 - - fastAttacker := tester.newPeer("fast-attack", protocol, chain.blocks[1:]) - fastAttacker.withholdHeaders[chain.blocks[missing].Hash()] = struct{}{} - - if err := tester.sync("fast-attack", nil, mode); err == nil { - t.Fatalf("succeeded fast attacker synchronisation") - } - if head := tester.chain.CurrentHeader().Number.Int64(); int(head) > MaxHeaderFetch { - t.Errorf("rollback head mismatch: have %v, want at most %v", head, MaxHeaderFetch) - } - // Attempt to sync with an attacker that feeds junk during the block import phase. - // This should result in both the last fsHeaderSafetyNet number of headers being - // rolled back, and also the pivot point being reverted to a non-block status. - missing = 3*fsHeaderSafetyNet + MaxHeaderFetch + 1 - - blockAttacker := tester.newPeer("block-attack", protocol, chain.blocks[1:]) - fastAttacker.withholdHeaders[chain.blocks[missing].Hash()] = struct{}{} // Make sure the fast-attacker doesn't fill in - blockAttacker.withholdHeaders[chain.blocks[missing].Hash()] = struct{}{} - - if err := tester.sync("block-attack", nil, mode); err == nil { - t.Fatalf("succeeded block attacker synchronisation") - } - if head := tester.chain.CurrentHeader().Number.Int64(); int(head) > 2*fsHeaderSafetyNet+MaxHeaderFetch { - t.Errorf("rollback head mismatch: have %v, want at most %v", head, 2*fsHeaderSafetyNet+MaxHeaderFetch) - } - if mode == SnapSync { - if head := tester.chain.CurrentBlock().Number.Uint64(); head != 0 { - t.Errorf("fast sync pivot block #%d not rolled back", head) - } - } - // Attempt to sync with an attacker that withholds promised blocks after the - // fast sync pivot point. This could be a trial to leave the node with a bad - // but already imported pivot block. - withholdAttacker := tester.newPeer("withhold-attack", protocol, chain.blocks[1:]) - - tester.downloader.syncInitHook = func(uint64, uint64) { - for i := missing; i < len(chain.blocks); i++ { - withholdAttacker.withholdHeaders[chain.blocks[i].Hash()] = struct{}{} - } - tester.downloader.syncInitHook = nil - } - if err := tester.sync("withhold-attack", nil, mode); err == nil { - t.Fatalf("succeeded withholding attacker synchronisation") - } - if head := tester.chain.CurrentHeader().Number.Int64(); int(head) > 2*fsHeaderSafetyNet+MaxHeaderFetch { - t.Errorf("rollback head mismatch: have %v, want at most %v", head, 2*fsHeaderSafetyNet+MaxHeaderFetch) - } - if mode == SnapSync { - if head := tester.chain.CurrentBlock().Number.Uint64(); head != 0 { - t.Errorf("fast sync pivot block #%d not rolled back", head) - } - } - // Synchronise with the valid peer and make sure sync succeeds. Since the last rollback - // should also disable fast syncing for this process, verify that we did a fresh full - // sync. Note, we can't assert anything about the receipts since we won't purge the - // database of them, hence we can't use assertOwnChain. - tester.newPeer("valid", protocol, chain.blocks[1:]) - if err := tester.sync("valid", nil, mode); err != nil { - t.Fatalf("failed to synchronise blocks: %v", err) - } - assertOwnChain(t, tester, len(chain.blocks)) -} - // Tests that a peer advertising a high TD doesn't get to stall the downloader // afterwards by not sending any useful hashes. -func TestHighTDStarvationAttack66Full(t *testing.T) { - testHighTDStarvationAttack(t, eth.ETH66, FullSync) +func TestHighTDStarvationAttack68Full(t *testing.T) { + testHighTDStarvationAttack(t, eth.ETH68, FullSync) } -func TestHighTDStarvationAttack66Snap(t *testing.T) { - testHighTDStarvationAttack(t, eth.ETH66, SnapSync) +func TestHighTDStarvationAttack68Snap(t *testing.T) { + testHighTDStarvationAttack(t, eth.ETH68, SnapSync) } -func TestHighTDStarvationAttack66Light(t *testing.T) { - testHighTDStarvationAttack(t, eth.ETH66, LightSync) +func TestHighTDStarvationAttack68Light(t *testing.T) { + testHighTDStarvationAttack(t, eth.ETH68, LightSync) } func TestHighTDStarvationAttack67Full(t *testing.T) { testHighTDStarvationAttack(t, eth.ETH67, FullSync) @@ -991,7 +911,7 @@ } }   // Tests that misbehaving peers are disconnected, whilst behaving ones are not. -func TestBlockHeaderAttackerDropping66(t *testing.T) { testBlockHeaderAttackerDropping(t, eth.ETH66) } +func TestBlockHeaderAttackerDropping68(t *testing.T) { testBlockHeaderAttackerDropping(t, eth.ETH68) } func TestBlockHeaderAttackerDropping67(t *testing.T) { testBlockHeaderAttackerDropping(t, eth.ETH67) }   func testBlockHeaderAttackerDropping(t *testing.T, protocol uint) { @@ -1040,9 +960,9 @@ }   // Tests that synchronisation progress (origin block number, current block number // and highest block number) is tracked and updated correctly. -func TestSyncProgress66Full(t *testing.T) { testSyncProgress(t, eth.ETH66, FullSync) } -func TestSyncProgress66Snap(t *testing.T) { testSyncProgress(t, eth.ETH66, SnapSync) } -func TestSyncProgress66Light(t *testing.T) { testSyncProgress(t, eth.ETH66, LightSync) } +func TestSyncProgress68Full(t *testing.T) { testSyncProgress(t, eth.ETH68, FullSync) } +func TestSyncProgress68Snap(t *testing.T) { testSyncProgress(t, eth.ETH68, SnapSync) } +func TestSyncProgress68Light(t *testing.T) { testSyncProgress(t, eth.ETH68, LightSync) } func TestSyncProgress67Full(t *testing.T) { testSyncProgress(t, eth.ETH67, FullSync) } func TestSyncProgress67Snap(t *testing.T) { testSyncProgress(t, eth.ETH67, SnapSync) } func TestSyncProgress67Light(t *testing.T) { testSyncProgress(t, eth.ETH67, LightSync) } @@ -1120,9 +1040,9 @@ // Tests that synchronisation progress (origin block number and highest block // number) is tracked and updated correctly in case of a fork (or manual head // revertal). -func TestForkedSyncProgress66Full(t *testing.T) { testForkedSyncProgress(t, eth.ETH66, FullSync) } -func TestForkedSyncProgress66Snap(t *testing.T) { testForkedSyncProgress(t, eth.ETH66, SnapSync) } -func TestForkedSyncProgress66Light(t *testing.T) { testForkedSyncProgress(t, eth.ETH66, LightSync) } +func TestForkedSyncProgress68Full(t *testing.T) { testForkedSyncProgress(t, eth.ETH68, FullSync) } +func TestForkedSyncProgress68Snap(t *testing.T) { testForkedSyncProgress(t, eth.ETH68, SnapSync) } +func TestForkedSyncProgress68Light(t *testing.T) { testForkedSyncProgress(t, eth.ETH68, LightSync) } func TestForkedSyncProgress67Full(t *testing.T) { testForkedSyncProgress(t, eth.ETH67, FullSync) } func TestForkedSyncProgress67Snap(t *testing.T) { testForkedSyncProgress(t, eth.ETH67, SnapSync) } func TestForkedSyncProgress67Light(t *testing.T) { testForkedSyncProgress(t, eth.ETH67, LightSync) } @@ -1194,9 +1114,9 @@ // Tests that if synchronisation is aborted due to some failure, then the progress // origin is not updated in the next sync cycle, as it should be considered the // continuation of the previous sync and not a new instance. -func TestFailedSyncProgress66Full(t *testing.T) { testFailedSyncProgress(t, eth.ETH66, FullSync) } -func TestFailedSyncProgress66Snap(t *testing.T) { testFailedSyncProgress(t, eth.ETH66, SnapSync) } -func TestFailedSyncProgress66Light(t *testing.T) { testFailedSyncProgress(t, eth.ETH66, LightSync) } +func TestFailedSyncProgress68Full(t *testing.T) { testFailedSyncProgress(t, eth.ETH68, FullSync) } +func TestFailedSyncProgress68Snap(t *testing.T) { testFailedSyncProgress(t, eth.ETH68, SnapSync) } +func TestFailedSyncProgress68Light(t *testing.T) { testFailedSyncProgress(t, eth.ETH68, LightSync) } func TestFailedSyncProgress67Full(t *testing.T) { testFailedSyncProgress(t, eth.ETH67, FullSync) } func TestFailedSyncProgress67Snap(t *testing.T) { testFailedSyncProgress(t, eth.ETH67, SnapSync) } func TestFailedSyncProgress67Light(t *testing.T) { testFailedSyncProgress(t, eth.ETH67, LightSync) } @@ -1263,9 +1183,9 @@ }   // Tests that if an attacker fakes a chain height, after the attack is detected, // the progress height is successfully reduced at the next sync invocation. -func TestFakedSyncProgress66Full(t *testing.T) { testFakedSyncProgress(t, eth.ETH66, FullSync) } -func TestFakedSyncProgress66Snap(t *testing.T) { testFakedSyncProgress(t, eth.ETH66, SnapSync) } -func TestFakedSyncProgress66Light(t *testing.T) { testFakedSyncProgress(t, eth.ETH66, LightSync) } +func TestFakedSyncProgress68Full(t *testing.T) { testFakedSyncProgress(t, eth.ETH68, FullSync) } +func TestFakedSyncProgress68Snap(t *testing.T) { testFakedSyncProgress(t, eth.ETH68, SnapSync) } +func TestFakedSyncProgress68Light(t *testing.T) { testFakedSyncProgress(t, eth.ETH68, LightSync) } func TestFakedSyncProgress67Full(t *testing.T) { testFakedSyncProgress(t, eth.ETH67, FullSync) } func TestFakedSyncProgress67Snap(t *testing.T) { testFakedSyncProgress(t, eth.ETH67, SnapSync) } func TestFakedSyncProgress67Light(t *testing.T) { testFakedSyncProgress(t, eth.ETH67, LightSync) } @@ -1410,8 +1330,10 @@ }   // Tests that peers below a pre-configured checkpoint block are prevented from // being fast-synced from, avoiding potential cheap eclipse attacks. -func TestBeaconSync66Full(t *testing.T) { testBeaconSync(t, eth.ETH66, FullSync) } -func TestBeaconSync66Snap(t *testing.T) { testBeaconSync(t, eth.ETH66, SnapSync) } +func TestBeaconSync68Full(t *testing.T) { testBeaconSync(t, eth.ETH68, FullSync) } +func TestBeaconSync68Snap(t *testing.T) { testBeaconSync(t, eth.ETH68, SnapSync) } +func TestBeaconSync67Full(t *testing.T) { testBeaconSync(t, eth.ETH67, FullSync) } +func TestBeaconSync67Snap(t *testing.T) { testBeaconSync(t, eth.ETH67, SnapSync) }   func testBeaconSync(t *testing.T, protocol uint, mode SyncMode) { //log.Root().SetHandler(log.LvlFilterHandler(log.LvlInfo, log.StreamHandler(os.Stderr, log.TerminalFormat(true))))
diff --git ethereum/go-ethereum/eth/downloader/fetchers_concurrent_bodies.go taikoxyz/taiko-geth/eth/downloader/fetchers_concurrent_bodies.go index 9440972c6d70c9e9292615d38ec64936e63c3840..5105fda66b3a8752ed512532c8c8770956f1989d 100644 --- ethereum/go-ethereum/eth/downloader/fetchers_concurrent_bodies.go +++ taikoxyz/taiko-geth/eth/downloader/fetchers_concurrent_bodies.go @@ -89,7 +89,7 @@ // deliver is responsible for taking a generic response packet from the concurrent // fetcher, unpacking the body data and delivering it to the downloader's queue. func (q *bodyQueue) deliver(peer *peerConnection, packet *eth.Response) (int, error) { - txs, uncles, withdrawals := packet.Res.(*eth.BlockBodiesPacket).Unpack() + txs, uncles, withdrawals := packet.Res.(*eth.BlockBodiesResponse).Unpack() hashsets := packet.Meta.([][]common.Hash) // {txs hashes, uncle hashes, withdrawal hashes}   accepted, err := q.queue.DeliverBodies(peer.id, txs, hashsets[0], uncles, hashsets[1], withdrawals, hashsets[2])
diff --git ethereum/go-ethereum/eth/tracers/tracers_test.go taikoxyz/taiko-geth/eth/tracers/tracers_test.go index 759e3a4dd38ee9c59700adf327af4428b288b205..b4989ec98445053786b23ff5798db80be3b47d41 100644 --- ethereum/go-ethereum/eth/tracers/tracers_test.go +++ taikoxyz/taiko-geth/eth/tracers/tracers_test.go @@ -79,7 +79,9 @@ Nonce: 1, Code: []byte{}, Balance: big.NewInt(500000000000000), } - _, statedb := tests.MakePreState(rawdb.NewMemoryDatabase(), alloc, false) + triedb, _, statedb := tests.MakePreState(rawdb.NewMemoryDatabase(), alloc, false, rawdb.HashScheme) + defer triedb.Close() + // Create the tracer, the EVM environment and run it tracer := logger.NewStructLogger(&logger.Config{ Debug: false,
diff --git ethereum/go-ethereum/eth/fetcher/tx_fetcher.go taikoxyz/taiko-geth/eth/fetcher/tx_fetcher.go index 63872734035ca387e2bd55b27ec04c5909004977..60b07a2b4b0b458a5c7707bf396c665c1014dbd1 100644 --- ethereum/go-ethereum/eth/fetcher/tx_fetcher.go +++ taikoxyz/taiko-geth/eth/fetcher/tx_fetcher.go @@ -20,12 +20,13 @@ import ( "bytes" "errors" "fmt" + "math" mrand "math/rand" "sort" "time"   - mapset "github.com/deckarep/golang-set/v2" "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/common/lru" "github.com/ethereum/go-ethereum/common/mclock" "github.com/ethereum/go-ethereum/core/txpool" "github.com/ethereum/go-ethereum/core/types" @@ -38,20 +39,29 @@ // maxTxAnnounces is the maximum number of unique transaction a peer // can announce in a short time. maxTxAnnounces = 4096   - // maxTxRetrievals is the maximum transaction number can be fetched in one - // request. The rationale to pick 256 is: - // - In eth protocol, the softResponseLimit is 2MB. Nowadays according to - // Etherscan the average transaction size is around 200B, so in theory - // we can include lots of transaction in a single protocol packet. - // - However the maximum size of a single transaction is raised to 128KB, - // so pick a middle value here to ensure we can maximize the efficiency - // of the retrieval and response size overflow won't happen in most cases. + // maxTxRetrievals is the maximum number of transactions that can be fetched + // in one request. The rationale for picking 256 is to have a reasonabe lower + // bound for the transferred data (don't waste RTTs, transfer more meaningful + // batch sizes), but also have an upper bound on the sequentiality to allow + // using our entire peerset for deliveries. + // + // This number also acts as a failsafe against malicious announces which might + // cause us to request more data than we'd expect. maxTxRetrievals = 256   + // maxTxRetrievalSize is the max number of bytes that delivered transactions + // should weigh according to the announcements. The 128KB was chosen to limit + // retrieving a maximum of one blob transaction at a time to minimize hogging + // a connection between two peers. + maxTxRetrievalSize = 128 * 1024 + // maxTxUnderpricedSetSize is the size of the underpriced transaction set that // is used to track recent transactions that have been dropped so we don't // re-request them. maxTxUnderpricedSetSize = 32768 + + // maxTxUnderpricedTimeout is the max time a transaction should be stuck in the underpriced set. + maxTxUnderpricedTimeout = 5 * time.Minute   // txArriveTimeout is the time allowance before an announced transaction is // explicitly requested. @@ -102,6 +112,14 @@ // of new transactions in the network. type txAnnounce struct { origin string // Identifier of the peer originating the notification hashes []common.Hash // Batch of transaction hashes being announced + metas []*txMetadata // Batch of metadatas associated with the hashes (nil before eth/68) +} + +// txMetadata is a set of extra data transmitted along the announcement for better +// fetch scheduling. +type txMetadata struct { + kind byte // Transaction consensus type + size uint32 // Transaction size in bytes }   // txRequest represents an in-flight transaction retrieval request destined to @@ -117,6 +135,7 @@ // to the pool and should be untracked. type txDelivery struct { origin string // Identifier of the peer originating the notification hashes []common.Hash // Batch of transaction hashes having been delivered + metas []txMetadata // Batch of metadatas associated with the delivered hashes direct bool // Whether this is a direct reply or a broadcast }   @@ -148,18 +167,18 @@ cleanup chan *txDelivery drop chan *txDrop quit chan struct{}   - underpriced mapset.Set[common.Hash] // Transactions discarded as too cheap (don't re-fetch) + underpriced *lru.Cache[common.Hash, time.Time] // Transactions discarded as too cheap (don't re-fetch)   // Stage 1: Waiting lists for newly discovered transactions that might be // broadcast without needing explicit request/reply round trips. - waitlist map[common.Hash]map[string]struct{} // Transactions waiting for an potential broadcast - waittime map[common.Hash]mclock.AbsTime // Timestamps when transactions were added to the waitlist - waitslots map[string]map[common.Hash]struct{} // Waiting announcements grouped by peer (DoS protection) + waitlist map[common.Hash]map[string]struct{} // Transactions waiting for an potential broadcast + waittime map[common.Hash]mclock.AbsTime // Timestamps when transactions were added to the waitlist + waitslots map[string]map[common.Hash]*txMetadata // Waiting announcements grouped by peer (DoS protection)   // Stage 2: Queue of transactions that waiting to be allocated to some peer // to be retrieved directly. - announces map[string]map[common.Hash]struct{} // Set of announced transactions, grouped by origin peer - announced map[common.Hash]map[string]struct{} // Set of download locations, grouped by transaction hash + announces map[string]map[common.Hash]*txMetadata // Set of announced transactions, grouped by origin peer + announced map[common.Hash]map[string]struct{} // Set of download locations, grouped by transaction hash   // Stage 3: Set of transactions currently being retrieved, some which may be // fulfilled and some rescheduled. Note, this step shares 'announces' from the @@ -169,9 +188,10 @@ requests map[string]*txRequest // In-flight transaction retrievals alternates map[common.Hash]map[string]struct{} // In-flight transaction alternate origins if retrieval fails   // Callbacks - hasTx func(common.Hash) bool // Retrieves a tx from the local txpool - addTxs func([]*txpool.Transaction) []error // Insert a batch of transactions into local txpool - fetchTxs func(string, []common.Hash) error // Retrieves a set of txs from a remote peer + hasTx func(common.Hash) bool // Retrieves a tx from the local txpool + addTxs func([]*types.Transaction) []error // Insert a batch of transactions into local txpool + fetchTxs func(string, []common.Hash) error // Retrieves a set of txs from a remote peer + dropPeer func(string) // Drops a peer in case of announcement violation   step chan struct{} // Notification channel when the fetcher loop iterates clock mclock.Clock // Time wrapper to simulate in tests @@ -180,14 +200,14 @@ }   // NewTxFetcher creates a transaction fetcher to retrieve transaction // based on hash announcements. -func NewTxFetcher(hasTx func(common.Hash) bool, addTxs func([]*txpool.Transaction) []error, fetchTxs func(string, []common.Hash) error) *TxFetcher { - return NewTxFetcherForTests(hasTx, addTxs, fetchTxs, mclock.System{}, nil) +func NewTxFetcher(hasTx func(common.Hash) bool, addTxs func([]*types.Transaction) []error, fetchTxs func(string, []common.Hash) error, dropPeer func(string)) *TxFetcher { + return NewTxFetcherForTests(hasTx, addTxs, fetchTxs, dropPeer, mclock.System{}, nil) }   // NewTxFetcherForTests is a testing method to mock out the realtime clock with // a simulated version and the internal randomness with a deterministic one. func NewTxFetcherForTests( - hasTx func(common.Hash) bool, addTxs func([]*txpool.Transaction) []error, fetchTxs func(string, []common.Hash) error, + hasTx func(common.Hash) bool, addTxs func([]*types.Transaction) []error, fetchTxs func(string, []common.Hash) error, dropPeer func(string), clock mclock.Clock, rand *mrand.Rand) *TxFetcher { return &TxFetcher{ notify: make(chan *txAnnounce), @@ -196,16 +216,17 @@ drop: make(chan *txDrop), quit: make(chan struct{}), waitlist: make(map[common.Hash]map[string]struct{}), waittime: make(map[common.Hash]mclock.AbsTime), - waitslots: make(map[string]map[common.Hash]struct{}), - announces: make(map[string]map[common.Hash]struct{}), + waitslots: make(map[string]map[common.Hash]*txMetadata), + announces: make(map[string]map[common.Hash]*txMetadata), announced: make(map[common.Hash]map[string]struct{}), fetching: make(map[common.Hash]string), requests: make(map[string]*txRequest), alternates: make(map[common.Hash]map[string]struct{}), - underpriced: mapset.NewSet[common.Hash](), + underpriced: lru.NewCache[common.Hash, time.Time](maxTxUnderpricedSetSize), hasTx: hasTx, addTxs: addTxs, fetchTxs: fetchTxs, + dropPeer: dropPeer, clock: clock, rand: rand, } @@ -213,7 +234,7 @@ }   // Notify announces the fetcher of the potential availability of a new batch of // transactions in the network. -func (f *TxFetcher) Notify(peer string, hashes []common.Hash) error { +func (f *TxFetcher) Notify(peer string, types []byte, sizes []uint32, hashes []common.Hash) error { // Keep track of all the announced transactions txAnnounceInMeter.Mark(int64(len(hashes)))   @@ -223,32 +244,35 @@ // because multiple concurrent notifies will still manage to pass it, but it's // still valuable to check here because it runs concurrent to the internal // loop, so anything caught here is time saved internally. var ( - unknowns = make([]common.Hash, 0, len(hashes)) - duplicate, underpriced int64 + unknownHashes = make([]common.Hash, 0, len(hashes)) + unknownMetas = make([]*txMetadata, 0, len(hashes)) + + duplicate int64 + underpriced int64 ) - for _, hash := range hashes { + for i, hash := range hashes { switch { case f.hasTx(hash): duplicate++ - - case f.underpriced.Contains(hash): + case f.isKnownUnderpriced(hash): underpriced++ - default: - unknowns = append(unknowns, hash) + unknownHashes = append(unknownHashes, hash) + if types == nil { + unknownMetas = append(unknownMetas, nil) + } else { + unknownMetas = append(unknownMetas, &txMetadata{kind: types[i], size: sizes[i]}) + } } } txAnnounceKnownMeter.Mark(duplicate) txAnnounceUnderpricedMeter.Mark(underpriced)   // If anything's left to announce, push it into the internal loop - if len(unknowns) == 0 { + if len(unknownHashes) == 0 { return nil } - announce := &txAnnounce{ - origin: peer, - hashes: unknowns, - } + announce := &txAnnounce{origin: peer, hashes: unknownHashes, metas: unknownMetas} select { case f.notify <- announce: return nil @@ -257,6 +281,16 @@ return errTerminated } }   +// isKnownUnderpriced reports whether a transaction hash was recently found to be underpriced. +func (f *TxFetcher) isKnownUnderpriced(hash common.Hash) bool { + prevTime, ok := f.underpriced.Peek(hash) + if ok && prevTime.Before(time.Now().Add(-maxTxUnderpricedTimeout)) { + f.underpriced.Remove(hash) + return false + } + return ok +} + // Enqueue imports a batch of received transaction into the transaction pool // and the fetcher. This method may be called by both transaction broadcasts and // direct request replies. The differentiation is important so the fetcher can @@ -281,6 +315,7 @@ // Push all the transactions into the pool, tracking underpriced ones to avoid // re-requesting them and dropping the peer in case of malicious transfers. var ( added = make([]common.Hash, 0, len(txs)) + metas = make([]txMetadata, 0, len(txs)) ) // proceed in batches for i := 0; i < len(txs); i += 128 { @@ -295,19 +330,12 @@ otherreject int64 ) batch := txs[i:end]   - wrapped := make([]*txpool.Transaction, len(batch)) - for j, tx := range batch { - wrapped[j] = &txpool.Transaction{Tx: tx} - } - for j, err := range f.addTxs(wrapped) { + for j, err := range f.addTxs(batch) { // Track the transaction hash if the price is too low for us. // Avoid re-request this transaction when we receive another // announcement. if errors.Is(err, txpool.ErrUnderpriced) || errors.Is(err, txpool.ErrReplaceUnderpriced) { - for f.underpriced.Cardinality() >= maxTxUnderpricedSetSize { - f.underpriced.Pop() - } - f.underpriced.Add(batch[j].Hash()) + f.underpriced.Add(batch[j].Hash(), batch[j].Time()) } // Track a few interesting failure types switch { @@ -323,6 +351,10 @@ default: otherreject++ } added = append(added, batch[j].Hash()) + metas = append(metas, txMetadata{ + kind: batch[j].Type(), + size: uint32(batch[j].Size()), + }) } knownMeter.Mark(duplicate) underpricedMeter.Mark(underpriced) @@ -335,7 +367,7 @@ log.Warn("Peer delivering stale transactions", "peer", peer, "rejected", otherreject) } } select { - case f.cleanup <- &txDelivery{origin: peer, hashes: added, direct: direct}: + case f.cleanup <- &txDelivery{origin: peer, hashes: added, metas: metas, direct: direct}: return nil case <-f.quit: return errTerminated @@ -392,13 +424,15 @@ } want := used + len(ann.hashes) if want > maxTxAnnounces { txAnnounceDOSMeter.Mark(int64(want - maxTxAnnounces)) + ann.hashes = ann.hashes[:want-maxTxAnnounces] + ann.metas = ann.metas[:want-maxTxAnnounces] } // All is well, schedule the remainder of the transactions idleWait := len(f.waittime) == 0 _, oldPeer := f.announces[ann.origin]   - for _, hash := range ann.hashes { + for i, hash := range ann.hashes { // If the transaction is already downloading, add it to the list // of possible alternates (in case the current retrieval fails) and // also account it for the peer. @@ -407,9 +441,9 @@ f.alternates[hash][ann.origin] = struct{}{}   // Stage 2 and 3 share the set of origins per tx if announces := f.announces[ann.origin]; announces != nil { - announces[hash] = struct{}{} + announces[hash] = ann.metas[i] } else { - f.announces[ann.origin] = map[common.Hash]struct{}{hash: {}} + f.announces[ann.origin] = map[common.Hash]*txMetadata{hash: ann.metas[i]} } continue } @@ -420,9 +454,9 @@ f.announced[hash][ann.origin] = struct{}{}   // Stage 2 and 3 share the set of origins per tx if announces := f.announces[ann.origin]; announces != nil { - announces[hash] = struct{}{} + announces[hash] = ann.metas[i] } else { - f.announces[ann.origin] = map[common.Hash]struct{}{hash: {}} + f.announces[ann.origin] = map[common.Hash]*txMetadata{hash: ann.metas[i]} } continue } @@ -430,12 +464,18 @@ // If the transaction is already known to the fetcher, but not // yet downloading, add the peer as an alternate origin in the // waiting list. if f.waitlist[hash] != nil { + // Ignore double announcements from the same peer. This is + // especially important if metadata is also passed along to + // prevent malicious peers flip-flopping good/bad values. + if _, ok := f.waitlist[hash][ann.origin]; ok { + continue + } f.waitlist[hash][ann.origin] = struct{}{}   if waitslots := f.waitslots[ann.origin]; waitslots != nil { - waitslots[hash] = struct{}{} + waitslots[hash] = ann.metas[i] } else { - f.waitslots[ann.origin] = map[common.Hash]struct{}{hash: {}} + f.waitslots[ann.origin] = map[common.Hash]*txMetadata{hash: ann.metas[i]} } continue } @@ -444,9 +484,9 @@ f.waitlist[hash] = map[string]struct{}{ann.origin: {}} f.waittime[hash] = f.clock.Now()   if waitslots := f.waitslots[ann.origin]; waitslots != nil { - waitslots[hash] = struct{}{} + waitslots[hash] = ann.metas[i] } else { - f.waitslots[ann.origin] = map[common.Hash]struct{}{hash: {}} + f.waitslots[ann.origin] = map[common.Hash]*txMetadata{hash: ann.metas[i]} } } // If a new item was added to the waitlist, schedule it into the fetcher @@ -472,9 +512,9 @@ } f.announced[hash] = f.waitlist[hash] for peer := range f.waitlist[hash] { if announces := f.announces[peer]; announces != nil { - announces[hash] = struct{}{} + announces[hash] = f.waitslots[peer][hash] } else { - f.announces[peer] = map[common.Hash]struct{}{hash: {}} + f.announces[peer] = map[common.Hash]*txMetadata{hash: f.waitslots[peer][hash]} } delete(f.waitslots[peer], hash) if len(f.waitslots[peer]) == 0 { @@ -543,10 +583,28 @@ f.rescheduleTimeout(timeoutTimer, timeoutTrigger)   case delivery := <-f.cleanup: // Independent if the delivery was direct or broadcast, remove all - // traces of the hash from internal trackers - for _, hash := range delivery.hashes { + // traces of the hash from internal trackers. That said, compare any + // advertised metadata with the real ones and drop bad peers. + for i, hash := range delivery.hashes { if _, ok := f.waitlist[hash]; ok { for peer, txset := range f.waitslots { + if meta := txset[hash]; meta != nil { + if delivery.metas[i].kind != meta.kind { + log.Warn("Announced transaction type mismatch", "peer", peer, "tx", hash, "type", delivery.metas[i].kind, "ann", meta.kind) + f.dropPeer(peer) + } else if delivery.metas[i].size != meta.size { + if math.Abs(float64(delivery.metas[i].size)-float64(meta.size)) > 8 { + log.Warn("Announced transaction size mismatch", "peer", peer, "tx", hash, "size", delivery.metas[i].size, "ann", meta.size) + + // Normally we should drop a peer considering this is a protocol violation. + // However, due to the RLP vs consensus format messyness, allow a few bytes + // wiggle-room where we only warn, but don't drop. + // + // TODO(karalabe): Get rid of this relaxation when clients are proven stable. + f.dropPeer(peer) + } + } + } delete(txset, hash) if len(txset) == 0 { delete(f.waitslots, peer) @@ -556,6 +614,23 @@ delete(f.waitlist, hash) delete(f.waittime, hash) } else { for peer, txset := range f.announces { + if meta := txset[hash]; meta != nil { + if delivery.metas[i].kind != meta.kind { + log.Warn("Announced transaction type mismatch", "peer", peer, "tx", hash, "type", delivery.metas[i].kind, "ann", meta.kind) + f.dropPeer(peer) + } else if delivery.metas[i].size != meta.size { + if math.Abs(float64(delivery.metas[i].size)-float64(meta.size)) > 8 { + log.Warn("Announced transaction size mismatch", "peer", peer, "tx", hash, "size", delivery.metas[i].size, "ann", meta.size) + + // Normally we should drop a peer considering this is a protocol violation. + // However, due to the RLP vs consensus format messyness, allow a few bytes + // wiggle-room where we only warn, but don't drop. + // + // TODO(karalabe): Get rid of this relaxation when clients are proven stable. + f.dropPeer(peer) + } + } + } delete(txset, hash) if len(txset) == 0 { delete(f.announces, peer) @@ -792,25 +867,36 @@ } if len(f.announces[peer]) == 0 { return // continue in the for-each } - hashes := make([]common.Hash, 0, maxTxRetrievals) - f.forEachHash(f.announces[peer], func(hash common.Hash) bool { - if _, ok := f.fetching[hash]; !ok { - // Mark the hash as fetching and stash away possible alternates - f.fetching[hash] = peer + var ( + hashes = make([]common.Hash, 0, maxTxRetrievals) + bytes uint64 + ) + f.forEachAnnounce(f.announces[peer], func(hash common.Hash, meta *txMetadata) bool { + // If the transaction is already fetching, skip to the next one + if _, ok := f.fetching[hash]; ok { + return true + } + // Mark the hash as fetching and stash away possible alternates + f.fetching[hash] = peer   - if _, ok := f.alternates[hash]; ok { - panic(fmt.Sprintf("alternate tracker already contains fetching item: %v", f.alternates[hash])) - } - f.alternates[hash] = f.announced[hash] - delete(f.announced, hash) + if _, ok := f.alternates[hash]; ok { + panic(fmt.Sprintf("alternate tracker already contains fetching item: %v", f.alternates[hash])) + } + f.alternates[hash] = f.announced[hash] + delete(f.announced, hash)   - // Accumulate the hash and stop if the limit was reached - hashes = append(hashes, hash) - if len(hashes) >= maxTxRetrievals { - return false // break in the for-each + // Accumulate the hash and stop if the limit was reached + hashes = append(hashes, hash) + if len(hashes) >= maxTxRetrievals { + return false // break in the for-each + } + if meta != nil { // Only set eth/68 and upwards + bytes += uint64(meta.size) + if bytes >= maxTxRetrievalSize { + return false } } - return true // continue in the for-each + return true // scheduled, try to add more }) // If any hashes were allocated, request them from the peer if len(hashes) > 0 { @@ -855,27 +941,28 @@ do(peer) } }   -// forEachHash does a range loop over a map of hashes in production, but during -// testing it does a deterministic sorted random to allow reproducing issues. -func (f *TxFetcher) forEachHash(hashes map[common.Hash]struct{}, do func(hash common.Hash) bool) { +// forEachAnnounce does a range loop over a map of announcements in production, +// but during testing it does a deterministic sorted random to allow reproducing +// issues. +func (f *TxFetcher) forEachAnnounce(announces map[common.Hash]*txMetadata, do func(hash common.Hash, meta *txMetadata) bool) { // If we're running production, use whatever Go's map gives us if f.rand == nil { - for hash := range hashes { - if !do(hash) { + for hash, meta := range announces { + if !do(hash, meta) { return } } return } // We're running the test suite, make iteration deterministic - list := make([]common.Hash, 0, len(hashes)) - for hash := range hashes { + list := make([]common.Hash, 0, len(announces)) + for hash := range announces { list = append(list, hash) } sortHashes(list) rotateHashes(list, f.rand.Intn(len(list))) for _, hash := range list { - if !do(hash) { + if !do(hash, announces[hash]) { return } }
diff --git ethereum/go-ethereum/eth/downloader/peer.go taikoxyz/taiko-geth/eth/downloader/peer.go index 6b8269495948e8fdae2ccab5bdb3906d4cd593a2..4c43af5270ca88485a96962e7ce0d8b46665619b 100644 --- ethereum/go-ethereum/eth/downloader/peer.go +++ taikoxyz/taiko-geth/eth/downloader/peer.go @@ -55,37 +55,14 @@ log log.Logger // Contextual logger to add extra infos to peer logs lock sync.RWMutex }   -// LightPeer encapsulates the methods required to synchronise with a remote light peer. -type LightPeer interface { +// Peer encapsulates the methods required to synchronise with a remote full peer. +type Peer interface { Head() (common.Hash, *big.Int) RequestHeadersByHash(common.Hash, int, int, bool, chan *eth.Response) (*eth.Request, error) RequestHeadersByNumber(uint64, int, int, bool, chan *eth.Response) (*eth.Request, error) -}   -// Peer encapsulates the methods required to synchronise with a remote full peer. -type Peer interface { - LightPeer RequestBodies([]common.Hash, chan *eth.Response) (*eth.Request, error) RequestReceipts([]common.Hash, chan *eth.Response) (*eth.Request, error) -} - -// lightPeerWrapper wraps a LightPeer struct, stubbing out the Peer-only methods. -type lightPeerWrapper struct { - peer LightPeer -} - -func (w *lightPeerWrapper) Head() (common.Hash, *big.Int) { return w.peer.Head() } -func (w *lightPeerWrapper) RequestHeadersByHash(h common.Hash, amount int, skip int, reverse bool, sink chan *eth.Response) (*eth.Request, error) { - return w.peer.RequestHeadersByHash(h, amount, skip, reverse, sink) -} -func (w *lightPeerWrapper) RequestHeadersByNumber(i uint64, amount int, skip int, reverse bool, sink chan *eth.Response) (*eth.Request, error) { - return w.peer.RequestHeadersByNumber(i, amount, skip, reverse, sink) -} -func (w *lightPeerWrapper) RequestBodies([]common.Hash, chan *eth.Response) (*eth.Request, error) { - panic("RequestBodies not supported in light client mode sync") -} -func (w *lightPeerWrapper) RequestReceipts([]common.Hash, chan *eth.Response) (*eth.Request, error) { - panic("RequestReceipts not supported in light client mode sync") }   // newPeerConnection creates a new downloader peer.
diff --git ethereum/go-ethereum/eth/filters/filter.go taikoxyz/taiko-geth/eth/filters/filter.go index d65bbfacfc854d59ff6aa78df9373be7072685b1..a5750c1934829db053e49da46cf154cea30b5f7f 100644 --- ethereum/go-ethereum/eth/filters/filter.go +++ taikoxyz/taiko-geth/eth/filters/filter.go @@ -347,48 +347,47 @@ } return nil }   -func includes(addresses []common.Address, a common.Address) bool { - for _, addr := range addresses { - if addr == a { +// includes returns true if the element is present in the list. +func includes[T comparable](things []T, element T) bool { + for _, thing := range things { + if thing == element { return true } } - return false }   // filterLogs creates a slice of logs matching the given criteria. func filterLogs(logs []*types.Log, fromBlock, toBlock *big.Int, addresses []common.Address, topics [][]common.Hash) []*types.Log { - var ret []*types.Log -Logs: - for _, log := range logs { + var check = func(log *types.Log) bool { if fromBlock != nil && fromBlock.Int64() >= 0 && fromBlock.Uint64() > log.BlockNumber { - continue + return false } if toBlock != nil && toBlock.Int64() >= 0 && toBlock.Uint64() < log.BlockNumber { - continue + return false } - if len(addresses) > 0 && !includes(addresses, log.Address) { - continue + return false } // If the to filtered topics is greater than the amount of topics in logs, skip. if len(topics) > len(log.Topics) { - continue + return false } for i, sub := range topics { - match := len(sub) == 0 // empty rule set == wildcard - for _, topic := range sub { - if log.Topics[i] == topic { - match = true - break - } + if len(sub) == 0 { + continue // empty rule set == wildcard } - if !match { - continue Logs + if !includes(sub, log.Topics[i]) { + return false } } - ret = append(ret, log) + return true + } + var ret []*types.Log + for _, log := range logs { + if check(log) { + ret = append(ret, log) + } } return ret }
diff --git ethereum/go-ethereum/eth/downloader/testchain_test.go taikoxyz/taiko-geth/eth/downloader/testchain_test.go index d791723b05b660b0f57e87c3944490d5ee260b2f..1bf03411d1d0de116a624391fea52853257f06f4 100644 --- ethereum/go-ethereum/eth/downloader/testchain_test.go +++ taikoxyz/taiko-geth/eth/downloader/testchain_test.go @@ -30,6 +30,7 @@ "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/core/vm" "github.com/ethereum/go-ethereum/crypto" "github.com/ethereum/go-ethereum/params" + "github.com/ethereum/go-ethereum/trie" )   // Test chain parameters. @@ -43,7 +44,7 @@ Config: params.TestChainConfig, Alloc: core.GenesisAlloc{testAddress: {Balance: big.NewInt(1000000000000000)}}, BaseFee: big.NewInt(params.InitialBaseFee), } - testGenesis = testGspec.MustCommit(testDB) + testGenesis = testGspec.MustCommit(testDB, trie.NewDatabase(testDB, trie.HashDefaults)) )   // The common prefix of all test chains:
diff --git ethereum/go-ethereum/eth/downloader/beacondevsync.go taikoxyz/taiko-geth/eth/downloader/beacondevsync.go new file mode 100644 index 0000000000000000000000000000000000000000..9a38fedd463e0ea8f5505992ae547105aa3b11ef --- /dev/null +++ taikoxyz/taiko-geth/eth/downloader/beacondevsync.go @@ -0,0 +1,81 @@ +// Copyright 2023 The go-ethereum Authors +// This file is part of the go-ethereum library. +// +// The go-ethereum library is free software: you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// The go-ethereum library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>. + +package downloader + +import ( + "errors" + "time" + + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/log" +) + +// BeaconDevSync is a development helper to test synchronization by providing +// a block hash instead of header to run the beacon sync against. +// +// The method will reach out to the network to retrieve the header of the sync +// target instead of receiving it from the consensus node. +// +// Note, this must not be used in live code. If the forkchcoice endpoint where +// to use this instead of giving us the payload first, then essentially nobody +// in the network would have the block yet that we'd attempt to retrieve. +func (d *Downloader) BeaconDevSync(mode SyncMode, hash common.Hash, stop chan struct{}) error { + // Be very loud that this code should not be used in a live node + log.Warn("----------------------------------") + log.Warn("Beacon syncing with hash as target", "hash", hash) + log.Warn("This is unhealthy for a live node!") + log.Warn("----------------------------------") + + log.Info("Waiting for peers to retrieve sync target") + for { + // If the node is going down, unblock + select { + case <-stop: + return errors.New("stop requested") + default: + } + // Pick a random peer to sync from and keep retrying if none are yet + // available due to fresh startup + d.peers.lock.RLock() + var peer *peerConnection + for _, peer = range d.peers.peers { + break + } + d.peers.lock.RUnlock() + + if peer == nil { + time.Sleep(time.Second) + continue + } + // Found a peer, attempt to retrieve the header whilst blocking and + // retry if it fails for whatever reason + log.Info("Attempting to retrieve sync target", "peer", peer.id) + headers, metas, err := d.fetchHeadersByHash(peer, hash, 1, 0, false) + if err != nil || len(headers) != 1 { + log.Warn("Failed to fetch sync target", "headers", len(headers), "err", err) + time.Sleep(time.Second) + continue + } + // Head header retrieved, if the hash matches, start the actual sync + if metas[0] != hash { + log.Error("Received invalid sync target", "want", hash, "have", metas[0]) + time.Sleep(time.Second) + continue + } + return d.BeaconSync(mode, headers[0], headers[0]) + } +}
diff --git ethereum/go-ethereum/eth/downloader/skeleton_test.go taikoxyz/taiko-geth/eth/downloader/skeleton_test.go index 6a76d78ac817fe6a5f30b6e32ff93e5fe5f65fb8..c31007765a8b722761852a64fee246daf5f8a414 100644 --- ethereum/go-ethereum/eth/downloader/skeleton_test.go +++ taikoxyz/taiko-geth/eth/downloader/skeleton_test.go @@ -173,7 +173,7 @@ Peer: p.id, } res := &eth.Response{ Req: req, - Res: (*eth.BlockHeadersPacket)(&headers), + Res: (*eth.BlockHeadersRequest)(&headers), Meta: hashes, Time: 1, Done: make(chan error), @@ -811,7 +811,7 @@ // Create a peer set to feed headers through peerset := newPeerSet() for _, peer := range tt.peers { - peerset.Register(newPeerConnection(peer.id, eth.ETH66, peer, log.New("id", peer.id))) + peerset.Register(newPeerConnection(peer.id, eth.ETH67, peer, log.New("id", peer.id))) } // Create a peer dropper to track malicious peers dropped := make(map[string]int) @@ -913,7 +913,7 @@ if tt.newHead != nil { skeleton.Sync(tt.newHead, nil, true) } if tt.newPeer != nil { - if err := peerset.Register(newPeerConnection(tt.newPeer.id, eth.ETH66, tt.newPeer, log.New("id", tt.newPeer.id))); err != nil { + if err := peerset.Register(newPeerConnection(tt.newPeer.id, eth.ETH67, tt.newPeer, log.New("id", tt.newPeer.id))); err != nil { t.Errorf("test %d: failed to register new peer: %v", i, err) } }
diff --git ethereum/go-ethereum/eth/catalyst/api_test.go taikoxyz/taiko-geth/eth/catalyst/api_test.go index 05ad3def48aec33456b7d667604bcec1ff1be3dd..59f44fafea4e0273b5db5b81b1609526e77c9d05 100644 --- ethereum/go-ethereum/eth/catalyst/api_test.go +++ taikoxyz/taiko-geth/eth/catalyst/api_test.go @@ -35,19 +35,20 @@ "github.com/ethereum/go-ethereum/consensus" beaconConsensus "github.com/ethereum/go-ethereum/consensus/beacon" "github.com/ethereum/go-ethereum/consensus/ethash" "github.com/ethereum/go-ethereum/core" - "github.com/ethereum/go-ethereum/core/txpool" "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/crypto" "github.com/ethereum/go-ethereum/crypto/kzg4844" "github.com/ethereum/go-ethereum/eth" "github.com/ethereum/go-ethereum/eth/downloader" "github.com/ethereum/go-ethereum/eth/ethconfig" + "github.com/ethereum/go-ethereum/log" "github.com/ethereum/go-ethereum/miner" "github.com/ethereum/go-ethereum/node" "github.com/ethereum/go-ethereum/p2p" "github.com/ethereum/go-ethereum/params" "github.com/ethereum/go-ethereum/rpc" "github.com/ethereum/go-ethereum/trie" + "github.com/mattn/go-colorable" )   var ( @@ -69,8 +70,11 @@ config.TerminalTotalDifficultyPassed = true engine = beaconConsensus.NewFaker() } genesis := &core.Genesis{ - Config: &config, - Alloc: core.GenesisAlloc{testAddr: {Balance: testBalance}}, + Config: &config, + Alloc: core.GenesisAlloc{ + testAddr: {Balance: testBalance}, + params.BeaconRootsStorageAddress: {Balance: common.Big0, Code: common.Hex2Bytes("3373fffffffffffffffffffffffffffffffffffffffe14604457602036146024575f5ffd5b620180005f350680545f35146037575f5ffd5b6201800001545f5260205ff35b6201800042064281555f359062018000015500")}, + }, ExtraData: []byte("test genesis"), Timestamp: 9000, BaseFee: big.NewInt(params.InitialBaseFee), @@ -108,7 +112,7 @@ tx, err := types.SignTx(types.NewTransaction(uint64(10), blocks[9].Coinbase(), big.NewInt(1000), params.TxGas, big.NewInt(params.InitialBaseFee), nil), signer, testKey) if err != nil { t.Fatalf("error signing transaction, err=%v", err) } - ethservice.TxPool().Add([]*txpool.Transaction{{Tx: tx}}, true, false) + ethservice.TxPool().Add([]*types.Transaction{tx}, true, false) blockParams := engine.PayloadAttributes{ Timestamp: blocks[9].Time() + 5, } @@ -145,11 +149,7 @@ api := NewConsensusAPI(ethservice)   // Put the 10th block's tx in the pool and produce a new block txs := blocks[9].Transactions() - wrapped := make([]*txpool.Transaction, len(txs)) - for i, tx := range txs { - wrapped[i] = &txpool.Transaction{Tx: tx} - } - api.eth.TxPool().Add(wrapped, false, true) + api.eth.TxPool().Add(txs, false, true) blockParams := engine.PayloadAttributes{ Timestamp: blocks[8].Time() + 5, } @@ -189,11 +189,7 @@ api := NewConsensusAPI(ethservice)   // Put the 10th block's tx in the pool and produce a new block txs := blocks[9].Transactions() - wrapped := make([]*txpool.Transaction, len(txs)) - for i, tx := range txs { - wrapped[i] = &txpool.Transaction{Tx: tx} - } - ethservice.TxPool().Add(wrapped, true, false) + ethservice.TxPool().Add(txs, true, false) blockParams := engine.PayloadAttributes{ Timestamp: blocks[8].Time() + 5, } @@ -213,6 +209,7 @@ Parent: fcState.HeadBlockHash, Timestamp: blockParams.Timestamp, FeeRecipient: blockParams.SuggestedFeeRecipient, Random: blockParams.Random, + BeaconRoot: blockParams.BeaconRoot, }).Id() execData, err := api.GetPayloadV1(payloadID) if err != nil { @@ -315,7 +312,7 @@ for i := 0; i < 10; i++ { statedb, _ := ethservice.BlockChain().StateAt(parent.Root()) nonce := statedb.GetNonce(testAddr) tx, _ := types.SignTx(types.NewContractCreation(nonce, new(big.Int), 1000000, big.NewInt(2*params.InitialBaseFee), logCode), types.LatestSigner(ethservice.BlockChain().Config()), testKey) - ethservice.TxPool().Add([]*txpool.Transaction{{Tx: tx}}, true, false) + ethservice.TxPool().Add([]*types.Transaction{tx}, true, false)   execData, err := assembleWithTransactions(api, parent.Hash(), &engine.PayloadAttributes{ Timestamp: parent.Time() + 5, @@ -323,7 +320,7 @@ }, 1) if err != nil { t.Fatalf("Failed to create the executable data %v", err) } - block, err := engine.ExecutableDataToBlock(*execData, nil) + block, err := engine.ExecutableDataToBlock(*execData, nil, nil) if err != nil { t.Fatalf("Failed to convert executable data to block %v", err) } @@ -365,7 +362,7 @@ }) if err != nil { t.Fatalf("Failed to create the executable data %v", err) } - block, err := engine.ExecutableDataToBlock(*execData, nil) + block, err := engine.ExecutableDataToBlock(*execData, nil, nil) if err != nil { t.Fatalf("Failed to convert executable data to block %v", err) } @@ -484,7 +481,7 @@ callback := func(parent *types.Header) { statedb, _ := ethservice.BlockChain().StateAt(parent.Root) nonce := statedb.GetNonce(testAddr) tx, _ := types.SignTx(types.NewContractCreation(nonce, new(big.Int), 1000000, big.NewInt(2*params.InitialBaseFee), logCode), types.LatestSigner(ethservice.BlockChain().Config()), testKey) - ethservice.TxPool().Add([]*txpool.Transaction{{Tx: tx}}, true, false) + ethservice.TxPool().Add([]*types.Transaction{tx}, true, false) }   setupBlocks(t, ethservice, 10, parent, callback, nil) @@ -610,7 +607,7 @@ Gas: 1000000, GasPrice: big.NewInt(2 * params.InitialBaseFee), Data: logCode, }) - ethservice.TxPool().Add([]*txpool.Transaction{{Tx: tx}}, false, true) + ethservice.TxPool().Add([]*types.Transaction{tx}, false, true) var ( params = engine.PayloadAttributes{ Timestamp: parent.Time + 1, @@ -676,6 +673,7 @@ Timestamp: params.Timestamp, FeeRecipient: params.SuggestedFeeRecipient, Random: params.Random, Withdrawals: params.Withdrawals, + BeaconRoot: params.BeaconRoot, } payload, err := api.eth.Miner().BuildPayload(args) if err != nil { @@ -997,7 +995,7 @@ if testErr != nil { t.Fatal(testErr) } } - block, err := engine.ExecutableDataToBlock(*execData, nil) + block, err := engine.ExecutableDataToBlock(*execData, nil, nil) if err != nil { t.Fatalf("Failed to convert executable data to block %v", err) } @@ -1077,6 +1075,7 @@ Timestamp: blockParams.Timestamp, FeeRecipient: blockParams.SuggestedFeeRecipient, Random: blockParams.Random, Withdrawals: blockParams.Withdrawals, + BeaconRoot: blockParams.BeaconRoot, }).Id() execData, err := api.GetPayloadV2(payloadID) if err != nil { @@ -1124,6 +1123,7 @@ Timestamp: blockParams.Timestamp, FeeRecipient: blockParams.SuggestedFeeRecipient, Random: blockParams.Random, Withdrawals: blockParams.Withdrawals, + BeaconRoot: blockParams.BeaconRoot, }).Id() execData, err = api.GetPayloadV2(payloadID) if err != nil { @@ -1254,6 +1254,7 @@ Parent: fcState.HeadBlockHash, Timestamp: test.blockParams.Timestamp, FeeRecipient: test.blockParams.SuggestedFeeRecipient, Random: test.blockParams.Random, + BeaconRoot: test.blockParams.BeaconRoot, }).Id() execData, err := api.GetPayloadV2(payloadID) if err != nil { @@ -1284,7 +1285,7 @@ callback := func(parent *types.Header) { statedb, _ := ethservice.BlockChain().StateAt(parent.Root) nonce := statedb.GetNonce(testAddr) tx, _ := types.SignTx(types.NewContractCreation(nonce, new(big.Int), 1000000, big.NewInt(2*params.InitialBaseFee), logCode), types.LatestSigner(ethservice.BlockChain().Config()), testKey) - ethservice.TxPool().Add([]*txpool.Transaction{{Tx: tx}}, true, false) + ethservice.TxPool().Add([]*types.Transaction{tx}, false, false) }   withdrawals := make([][]*types.Withdrawal, 10) @@ -1530,13 +1531,16 @@ BlobHashes: make([]common.Hash, 1), }   txs = append(txs, types.NewTx(&inner)) - - blobs := make([]kzg4844.Blob, 1) - commitments := make([]kzg4844.Commitment, 1) - proofs := make([]kzg4844.Proof, 1) + sidecars := []*types.BlobTxSidecar{ + { + Blobs: make([]kzg4844.Blob, 1), + Commitments: make([]kzg4844.Commitment, 1), + Proofs: make([]kzg4844.Proof, 1), + }, + }   block := types.NewBlock(&header, txs, nil, nil, trie.NewStackTrie(nil)) - envelope := engine.BlockToExecutableData(block, nil, blobs, commitments, proofs) + envelope := engine.BlockToExecutableData(block, nil, sidecars) var want int for _, tx := range txs { want += len(tx.BlobHashes()) @@ -1550,8 +1554,91 @@ } if got := len(envelope.BlobsBundle.Blobs); got != want { t.Fatalf("invalid number of blobs: got %v, want %v", got, want) } - _, err := engine.ExecutableDataToBlock(*envelope.ExecutionPayload, make([]common.Hash, 1)) + _, err := engine.ExecutableDataToBlock(*envelope.ExecutionPayload, make([]common.Hash, 1), nil) if err != nil { t.Error(err) } } + +// This checks that beaconRoot is applied to the state from the engine API. +func TestParentBeaconBlockRoot(t *testing.T) { + log.Root().SetHandler(log.LvlFilterHandler(log.LvlTrace, log.StreamHandler(colorable.NewColorableStderr(), log.TerminalFormat(true)))) + + genesis, blocks := generateMergeChain(10, true) + + // Set cancun time to last block + 5 seconds + time := blocks[len(blocks)-1].Time() + 5 + genesis.Config.ShanghaiTime = &time + genesis.Config.CancunTime = &time + + n, ethservice := startEthService(t, genesis, blocks) + ethservice.Merger().ReachTTD() + defer n.Close() + + api := NewConsensusAPI(ethservice) + + // 11: Build Shanghai block with no withdrawals. + parent := ethservice.BlockChain().CurrentHeader() + blockParams := engine.PayloadAttributes{ + Timestamp: parent.Time + 5, + Withdrawals: make([]*types.Withdrawal, 0), + BeaconRoot: &common.Hash{42}, + } + fcState := engine.ForkchoiceStateV1{ + HeadBlockHash: parent.Hash(), + } + resp, err := api.ForkchoiceUpdatedV2(fcState, &blockParams) + if err != nil { + t.Fatalf("error preparing payload, err=%v", err.(*engine.EngineAPIError).ErrorData()) + } + if resp.PayloadStatus.Status != engine.VALID { + t.Fatalf("unexpected status (got: %s, want: %s)", resp.PayloadStatus.Status, engine.VALID) + } + + // 11: verify state root is the same as parent + payloadID := (&miner.BuildPayloadArgs{ + Parent: fcState.HeadBlockHash, + Timestamp: blockParams.Timestamp, + FeeRecipient: blockParams.SuggestedFeeRecipient, + Random: blockParams.Random, + Withdrawals: blockParams.Withdrawals, + BeaconRoot: blockParams.BeaconRoot, + }).Id() + execData, err := api.GetPayloadV3(payloadID) + if err != nil { + t.Fatalf("error getting payload, err=%v", err) + } + + // 11: verify locally built block + if status, err := api.NewPayloadV3(*execData.ExecutionPayload, []common.Hash{}, &common.Hash{42}); err != nil { + t.Fatalf("error validating payload: %v", err) + } else if status.Status != engine.VALID { + t.Fatalf("invalid payload") + } + + fcState.HeadBlockHash = execData.ExecutionPayload.BlockHash + resp, err = api.ForkchoiceUpdatedV3(fcState, nil) + if err != nil { + t.Fatalf("error preparing payload, err=%v", err.(*engine.EngineAPIError).ErrorData()) + } + if resp.PayloadStatus.Status != engine.VALID { + t.Fatalf("unexpected status (got: %s, want: %s)", resp.PayloadStatus.Status, engine.VALID) + } + + // 11: verify beacon root was processed. + db, _, err := ethservice.APIBackend.StateAndHeaderByNumber(context.Background(), rpc.BlockNumber(execData.ExecutionPayload.Number)) + if err != nil { + t.Fatalf("unable to load db: %v", err) + } + var ( + timeIdx = common.BigToHash(big.NewInt(int64(execData.ExecutionPayload.Timestamp % 98304))) + rootIdx = common.BigToHash(big.NewInt(int64((execData.ExecutionPayload.Timestamp % 98304) + 98304))) + ) + + if num := db.GetState(params.BeaconRootsStorageAddress, timeIdx); num != timeIdx { + t.Fatalf("incorrect number stored: want %s, got %s", timeIdx, num) + } + if root := db.GetState(params.BeaconRootsStorageAddress, rootIdx); root != *blockParams.BeaconRoot { + t.Fatalf("incorrect root stored: want %s, got %s", *blockParams.BeaconRoot, root) + } +}

This shows changes to ethclient files.

This provides API calls for L1 and L2 Origins, as well as Throwaway Block Receipts.

diff --git ethereum/go-ethereum/ethclient/ethclient.go taikoxyz/taiko-geth/ethclient/ethclient.go index 4508027fa47b0c642b1599eb707eafceb3e098b8..af373b99383d4589d3a451fed73d0eedd1c04568 100644 --- ethereum/go-ethereum/ethclient/ethclient.go +++ taikoxyz/taiko-geth/ethclient/ethclient.go @@ -108,6 +108,16 @@ err := ec.c.CallContext(ctx, &result, "net_peerCount") return uint64(result), err }   +// BlockReceipts returns the receipts of a given block number or hash. +func (ec *Client) BlockReceipts(ctx context.Context, blockNrOrHash rpc.BlockNumberOrHash) ([]*types.Receipt, error) { + var r []*types.Receipt + err := ec.c.CallContext(ctx, &r, "eth_getBlockReceipts", blockNrOrHash.String()) + if err == nil && r == nil { + return nil, ethereum.NotFound + } + return r, err +} + type rpcBlock struct { Hash common.Hash `json:"hash"` Transactions []rpcTransaction `json:"transactions"` @@ -609,7 +619,7 @@ "from": msg.From, "to": msg.To, } if len(msg.Data) > 0 { - arg["data"] = hexutil.Bytes(msg.Data) + arg["input"] = hexutil.Bytes(msg.Data) } if msg.Value != nil { arg["value"] = (*hexutil.Big)(msg.Value)
diff --git ethereum/go-ethereum/ethclient/taiko_api_test.go taikoxyz/taiko-geth/ethclient/taiko_api_test.go new file mode 100644 index 0000000000000000000000000000000000000000..7a7cfc7dcd4c61b12dda671fe45d2a078e290b70 --- /dev/null +++ taikoxyz/taiko-geth/ethclient/taiko_api_test.go @@ -0,0 +1,124 @@ +package ethclient + +import ( + "context" + "crypto/rand" + "math/big" + "testing" + + "github.com/ethereum/go-ethereum" + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/core/rawdb" + "github.com/ethereum/go-ethereum/core/types" + "github.com/ethereum/go-ethereum/eth" + "github.com/ethereum/go-ethereum/eth/ethconfig" + "github.com/ethereum/go-ethereum/ethdb" + "github.com/ethereum/go-ethereum/log" + "github.com/ethereum/go-ethereum/node" + "github.com/ethereum/go-ethereum/params" + "github.com/ethereum/go-ethereum/rpc" + "github.com/stretchr/testify/require" +) + +func newTaikoAPITestClient(t *testing.T) (*Client, []*types.Block, ethdb.Database) { + // Generate test chain. + blocks := generateTestChain() + + // Create node + n, err := node.New(&node.Config{}) + + require.Nil(t, err) + + // Create Ethereum Service + config := &ethconfig.Config{Genesis: genesis} + ethservice, err := eth.New(n, config) + require.Nil(t, err) + + n.RegisterAPIs([]rpc.API{ + { + Namespace: "taiko", + Version: params.VersionWithMeta, + Service: eth.NewTaikoAPIBackend(ethservice), + Public: true, + }, + }) + + // Start node + require.Nil(t, n.Start()) + + // Insert test blocks + _, err = ethservice.BlockChain().InsertChain(blocks[1:]) + + require.Nil(t, err) + + return NewClient(n.Attach()), blocks, ethservice.ChainDb() +} + +func TestHeadL1Origin(t *testing.T) { + ec, blocks, db := newTaikoAPITestClient(t) + + headerHash := blocks[len(blocks)-1].Hash() + + l1OriginFound, err := ec.HeadL1Origin(context.Background()) + + require.Equal(t, ethereum.NotFound.Error(), err.Error()) + require.Nil(t, l1OriginFound) + + testL1Origin := &rawdb.L1Origin{ + BlockID: randomBigInt(), + L2BlockHash: headerHash, + L1BlockHeight: randomBigInt(), + L1BlockHash: randomHash(), + } + + rawdb.WriteL1Origin(db, testL1Origin.BlockID, testL1Origin) + rawdb.WriteHeadL1Origin(db, testL1Origin.BlockID) + + l1OriginFound, err = ec.HeadL1Origin(context.Background()) + + require.Nil(t, err) + require.Equal(t, testL1Origin, l1OriginFound) +} + +func TestL1OriginByID(t *testing.T) { + ec, blocks, db := newTaikoAPITestClient(t) + + headerHash := blocks[len(blocks)-1].Hash() + testL1Origin := &rawdb.L1Origin{ + BlockID: randomBigInt(), + L2BlockHash: headerHash, + L1BlockHeight: randomBigInt(), + L1BlockHash: randomHash(), + } + + l1OriginFound, err := ec.L1OriginByID(context.Background(), testL1Origin.BlockID) + require.Equal(t, ethereum.NotFound.Error(), err.Error()) + require.Nil(t, l1OriginFound) + + rawdb.WriteL1Origin(db, testL1Origin.BlockID, testL1Origin) + rawdb.WriteHeadL1Origin(db, testL1Origin.BlockID) + + l1OriginFound, err = ec.L1OriginByID(context.Background(), testL1Origin.BlockID) + + require.Nil(t, err) + require.Equal(t, testL1Origin, l1OriginFound) +} + +// randomHash generates a random blob of data and returns it as a hash. +func randomHash() common.Hash { + var hash common.Hash + if n, err := rand.Read(hash[:]); n != common.HashLength || err != nil { + panic(err) + } + return hash +} + +// randomBigInt generates a random big integer. +func randomBigInt() *big.Int { + randomBigInt, err := rand.Int(rand.Reader, common.Big256) + if err != nil { + log.Crit(err.Error()) + } + + return randomBigInt +}
diff --git ethereum/go-ethereum/ethclient/taiko_api.go taikoxyz/taiko-geth/ethclient/taiko_api.go new file mode 100644 index 0000000000000000000000000000000000000000..9637608d062f16bbc7e855d81647e8babe3c8ab9 --- /dev/null +++ taikoxyz/taiko-geth/ethclient/taiko_api.go @@ -0,0 +1,31 @@ +package ethclient + +import ( + "context" + "math/big" + + "github.com/ethereum/go-ethereum/common/hexutil" + "github.com/ethereum/go-ethereum/core/rawdb" +) + +// HeadL1Origin returns the latest L2 block's corresponding L1 origin. +func (ec *Client) HeadL1Origin(ctx context.Context) (*rawdb.L1Origin, error) { + var res *rawdb.L1Origin + + if err := ec.c.CallContext(ctx, &res, "taiko_headL1Origin"); err != nil { + return nil, err + } + + return res, nil +} + +// L1OriginByID returns the L2 block's corresponding L1 origin. +func (ec *Client) L1OriginByID(ctx context.Context, blockID *big.Int) (*rawdb.L1Origin, error) { + var res *rawdb.L1Origin + + if err := ec.c.CallContext(ctx, &res, "taiko_l1OriginByID", hexutil.EncodeBig(blockID)); err != nil { + return nil, err + } + + return res, nil +}

This shows changes to les files.

diff --git ethereum/go-ethereum/les/state_accessor.go taikoxyz/taiko-geth/les/state_accessor.go index 9a8214ac2f8f044493965fe989c54316a690a883..25c78f46ae85b6bd73e323beff1190192e37c054 100644 --- ethereum/go-ethereum/les/state_accessor.go +++ taikoxyz/taiko-geth/les/state_accessor.go @@ -59,6 +59,11 @@ } // Recompute transactions up to the target index. signer := types.MakeSigner(leth.blockchain.Config(), block.Number(), block.Time()) for idx, tx := range block.Transactions() { + if idx == 0 && leth.chainConfig.Taiko { + if err := tx.MarkAsAnchor(); err != nil { + return nil, vm.BlockContext{}, nil, nil, err + } + } // Assemble the transaction call message and return if the requested offset msg, _ := core.TransactionToMessage(tx, signer, block.BaseFee()) txContext := core.NewEVMTxContext(msg)
diff --git ethereum/go-ethereum/les/servingqueue.go taikoxyz/taiko-geth/les/servingqueue.go index 68cad9cb5a17b1b0830abdb4151444b68eff741e..b258fc3cafdc08243a08f6b81df96e39c23a559a 100644 --- ethereum/go-ethereum/les/servingqueue.go +++ taikoxyz/taiko-geth/les/servingqueue.go @@ -28,10 +28,11 @@ // servingQueue allows running tasks in a limited number of threads and puts the // waiting tasks in a priority queue type servingQueue struct { - recentTime, queuedTime, servingTimeDiff uint64 - burstLimit, burstDropLimit uint64 - burstDecRate float64 - lastUpdate mclock.AbsTime + recentTime, queuedTime uint64 + servingTimeDiff atomic.Uint64 + burstLimit, burstDropLimit uint64 + burstDecRate float64 + lastUpdate mclock.AbsTime   queueAddCh, queueBestCh chan *servingTask stopThreadCh, quit chan struct{} @@ -100,7 +101,7 @@ diff := t.servingTime - t.timeAdded t.timeAdded = t.servingTime if t.expTime > diff { t.expTime -= diff - atomic.AddUint64(&t.sq.servingTimeDiff, t.expTime) + t.sq.servingTimeDiff.Add(t.expTime) } else { t.expTime = 0 } @@ -249,7 +250,7 @@ }   // updateRecentTime recalculates the recent serving time value func (sq *servingQueue) updateRecentTime() { - subTime := atomic.SwapUint64(&sq.servingTimeDiff, 0) + subTime := sq.servingTimeDiff.Swap(0) now := mclock.Now() dt := now - sq.lastUpdate sq.lastUpdate = now
diff --git ethereum/go-ethereum/les/client_handler.go taikoxyz/taiko-geth/les/client_handler.go index 39965d4c968a77356dab0f42325a6d1b14c3f5b1..50f6dce879ffface3de8221662eb21e733fe9c7c 100644 --- ethereum/go-ethereum/les/client_handler.go +++ taikoxyz/taiko-geth/les/client_handler.go @@ -26,6 +26,7 @@ "github.com/ethereum/go-ethereum/core/forkid" "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/light" "github.com/ethereum/go-ethereum/p2p" + "github.com/ethereum/go-ethereum/trie/trienode" )   // clientHandler is responsible for receiving and processing all incoming server @@ -69,7 +70,7 @@ } p.Log().Debug("Light Ethereum peer connected", "name", p.Name())   // Execute the LES handshake - forkid := forkid.NewID(h.backend.blockchain.Config(), h.backend.genesis, h.backend.blockchain.CurrentHeader().Number.Uint64(), h.backend.blockchain.CurrentHeader().Time) + forkid := forkid.NewID(h.backend.blockchain.Config(), h.backend.BlockChain().Genesis(), h.backend.blockchain.CurrentHeader().Number.Uint64(), h.backend.blockchain.CurrentHeader().Time) if err := p.Handshake(h.backend.blockchain.Genesis().Hash(), forkid, h.forkFilter); err != nil { p.Log().Debug("Light Ethereum handshake failed", "err", err) return err @@ -236,7 +237,7 @@ case msg.Code == ProofsV2Msg: p.Log().Trace("Received les/2 proofs response") var resp struct { ReqID, BV uint64 - Data light.NodeList + Data trienode.ProofList } if err := msg.Decode(&resp); err != nil { return errResp(ErrDecode, "msg %v: %v", msg, err)
diff --git ethereum/go-ethereum/les/costtracker.go taikoxyz/taiko-geth/les/costtracker.go index 43e32a5b2d00322c69ac7b50ee2717b2851512e3..695d54e14147ffde5c935bdfffca137a2e0d556c 100644 --- ethereum/go-ethereum/les/costtracker.go +++ taikoxyz/taiko-geth/les/costtracker.go @@ -128,7 +128,7 @@ gfLock sync.RWMutex reqInfoCh chan reqInfo totalRechargeCh chan uint64   - stats map[uint64][]uint64 // Used for testing purpose. + stats map[uint64][]atomic.Uint64 // Used for testing purpose.   // TestHooks testing bool // Disable real cost evaluation for testing purpose. @@ -152,9 +152,9 @@ if config.LightEgress > 0 { ct.outSizeFactor = utilTarget / float64(config.LightEgress) } if makeCostStats { - ct.stats = make(map[uint64][]uint64) + ct.stats = make(map[uint64][]atomic.Uint64) for code := range reqAvgTimeCost { - ct.stats[code] = make([]uint64, 10) + ct.stats[code] = make([]atomic.Uint64, 10) } } ct.gfLoop() @@ -423,7 +423,7 @@ for l < 9 && realCost > avgTimeCost { l++ realCost >>= 1 } - atomic.AddUint64(&ct.stats[code][l], 1) + ct.stats[code][l].Add(1) } }   @@ -454,7 +454,7 @@ if ct.stats == nil { return } for code, arr := range ct.stats { - log.Info("Request cost statistics", "code", code, "1/16", arr[0], "1/8", arr[1], "1/4", arr[2], "1/2", arr[3], "1", arr[4], "2", arr[5], "4", arr[6], "8", arr[7], "16", arr[8], ">16", arr[9]) + log.Info("Request cost statistics", "code", code, "1/16", arr[0].Load(), "1/8", arr[1].Load(), "1/4", arr[2].Load(), "1/2", arr[3].Load(), "1", arr[4].Load(), "2", arr[5].Load(), "4", arr[6].Load(), "8", arr[7].Load(), "16", arr[8].Load(), ">16", arr[9].Load()) } }
diff --git ethereum/go-ethereum/les/server_requests.go taikoxyz/taiko-geth/les/server_requests.go index 30ff2cd05fb4220c764afa05349c5cda6a11c1f9..9a249f04c9242d3ed4dacb30236f624d58c458a3 100644 --- ethereum/go-ethereum/les/server_requests.go +++ taikoxyz/taiko-geth/les/server_requests.go @@ -30,6 +30,7 @@ "github.com/ethereum/go-ethereum/log" "github.com/ethereum/go-ethereum/metrics" "github.com/ethereum/go-ethereum/rlp" "github.com/ethereum/go-ethereum/trie" + "github.com/ethereum/go-ethereum/trie/trienode" )   // serverBackend defines the backend functions needed for serving LES requests @@ -303,9 +304,8 @@ p.Log().Debug("Reject stale code request", "number", header.Number.Uint64(), "head", local) p.bumpInvalid() continue } - triedb := bc.StateCache().TrieDB() address := common.BytesToAddress(request.AccountAddress) - account, err := getAccount(triedb, header.Root, address) + account, err := getAccount(bc.TrieDB(), header.Root, address) if err != nil { p.Log().Warn("Failed to retrieve account for code", "block", header.Number, "hash", header.Hash(), "account", address, "err", err) p.bumpInvalid() @@ -379,7 +379,7 @@ header *types.Header err error ) bc := backend.BlockChain() - nodes := light.NewNodeSet() + nodes := trienode.NewProofSet()   for i, request := range r.Reqs { if i != 0 && !waitOrStop() { @@ -424,7 +424,7 @@ } default: // Account key specified, open a storage trie address := common.BytesToAddress(request.AccountAddress) - account, err := getAccount(statedb.TrieDB(), root, address) + account, err := getAccount(bc.TrieDB(), root, address) if err != nil { p.Log().Warn("Failed to retrieve account for proof", "block", header.Number, "hash", header.Hash(), "account", address, "err", err) p.bumpInvalid() @@ -445,7 +445,7 @@ if nodes.DataSize() >= softResponseLimit { break } } - return p.replyProofsV2(r.ReqID, nodes.NodeList()) + return p.replyProofsV2(r.ReqID, nodes.List()) }, r.ReqID, uint64(len(r.Reqs)), nil }   @@ -464,7 +464,7 @@ auxBytes int auxData [][]byte ) bc := backend.BlockChain() - nodes := light.NewNodeSet() + nodes := trienode.NewProofSet() for i, request := range r.Reqs { if i != 0 && !waitOrStop() { return nil @@ -499,7 +499,7 @@ if nodes.DataSize()+auxBytes >= softResponseLimit { break } } - return p.replyHelperTrieProofs(r.ReqID, HelperTrieResps{Proofs: nodes.NodeList(), AuxData: auxData}) + return p.replyHelperTrieProofs(r.ReqID, HelperTrieResps{Proofs: nodes.List(), AuxData: auxData}) }, r.ReqID, uint64(len(r.Reqs)), nil }   @@ -519,7 +519,7 @@ } hash := tx.Hash() stats[i] = txStatus(backend, hash) if stats[i].Status == txpool.TxStatusUnknown { - if errs := backend.TxPool().Add([]*txpool.Transaction{{Tx: tx}}, false, backend.AddTxsSync()); errs[0] != nil { + if errs := backend.TxPool().Add([]*types.Transaction{tx}, false, backend.AddTxsSync()); errs[0] != nil { stats[i].Error = errs[0].Error() continue }
diff --git ethereum/go-ethereum/les/test_helper.go taikoxyz/taiko-geth/les/test_helper.go index b03bca14bf3959e187106798a29ee0f99bf84973..6be13eaecd5f9d27eebe9a3e3ee6e79a133b1e5a 100644 --- ethereum/go-ethereum/les/test_helper.go +++ taikoxyz/taiko-geth/les/test_helper.go @@ -49,6 +49,7 @@ "github.com/ethereum/go-ethereum/light" "github.com/ethereum/go-ethereum/p2p" "github.com/ethereum/go-ethereum/p2p/enode" "github.com/ethereum/go-ethereum/params" + "github.com/ethereum/go-ethereum/trie" )   var ( @@ -188,7 +189,7 @@ GasLimit: 100000000, BaseFee: big.NewInt(params.InitialBaseFee), } ) - genesis := gspec.MustCommit(db) + genesis := gspec.MustCommit(db, trie.NewDatabase(db, trie.HashDefaults)) chain, _ := light.NewLightChain(odr, gspec.Config, engine)   client := &LightEthereum{ @@ -226,7 +227,7 @@ GasLimit: 100000000, BaseFee: big.NewInt(params.InitialBaseFee), } ) - genesis := gspec.MustCommit(db) + genesis := gspec.MustCommit(db, trie.NewDatabase(db, trie.HashDefaults))   // create a simulation backend and pre-commit several customized block to the database. simulation := backends.NewSimulatedBackendWithDatabase(db, gspec.Alloc, 100000000) @@ -498,7 +499,7 @@ genesis = server.handler.blockchain.Genesis() head = server.handler.blockchain.CurrentHeader() td = server.handler.blockchain.GetTd(head.Hash(), head.Number.Uint64()) ) - forkID := forkid.NewID(server.handler.blockchain.Config(), genesis.Hash(), head.Number.Uint64(), head.Time) + forkID := forkid.NewID(server.handler.blockchain.Config(), genesis, head.Number.Uint64(), head.Time) tp.handshakeWithServer(t, td, head.Hash(), head.Number.Uint64(), genesis.Hash(), forkID)   // Ensure the connection is established or exits when any error occurs
diff --git ethereum/go-ethereum/les/server_handler.go taikoxyz/taiko-geth/les/server_handler.go index ad18d3f4e47ab50fa4baa93212ac79d7d349dde7..5b3505064b313c0e386926022ac27380e51e09c4 100644 --- ethereum/go-ethereum/les/server_handler.go +++ taikoxyz/taiko-geth/les/server_handler.go @@ -116,7 +116,7 @@ head = h.blockchain.CurrentHeader() hash = head.Hash() number = head.Number.Uint64() td = h.blockchain.GetTd(hash, number) - forkID = forkid.NewID(h.blockchain.Config(), h.blockchain.Genesis().Hash(), number, head.Time) + forkID = forkid.NewID(h.blockchain.Config(), h.blockchain.Genesis(), number, head.Time) ) if err := p.Handshake(td, hash, number, h.blockchain.Genesis().Hash(), forkID, h.forkFilter, h.server); err != nil { p.Log().Debug("Light Ethereum handshake failed", "err", err) @@ -390,7 +390,8 @@ } if root == (common.Hash{}) { return nil } - trie, _ := trie.New(trie.TrieID(root), trie.NewDatabase(rawdb.NewTable(h.chainDb, prefix))) + triedb := trie.NewDatabase(rawdb.NewTable(h.chainDb, prefix), trie.HashDefaults) + trie, _ := trie.New(trie.TrieID(root), triedb) return trie }
diff --git ethereum/go-ethereum/les/odr_test.go taikoxyz/taiko-geth/les/odr_test.go index 853b4ab5658a68c29a656e9891ff50c901524e23..69824a92dd083958d1d02f03ee956d9cddc35223 100644 --- ethereum/go-ethereum/les/odr_test.go +++ taikoxyz/taiko-geth/les/odr_test.go @@ -104,7 +104,7 @@ ) for _, addr := range acc { if bc != nil { header := bc.GetHeaderByHash(bhash) - st, err = state.New(header.Root, state.NewDatabase(db), nil) + st, err = state.New(header.Root, bc.StateCache(), nil) } else { header := lc.GetHeaderByHash(bhash) st = light.NewState(ctx, header, lc.Odr())
diff --git ethereum/go-ethereum/les/api_test.go taikoxyz/taiko-geth/les/api_test.go index 88a950afced8fa12e20e9001f8d753f2ada1d7f3..484c95504c0d76ab1c79881b3b6d0c163712da1a 100644 --- ethereum/go-ethereum/les/api_test.go +++ taikoxyz/taiko-geth/les/api_test.go @@ -147,7 +147,7 @@ var wg sync.WaitGroup stop := make(chan struct{})   - reqCount := make([]uint64, len(clientRpcClients)) + reqCount := make([]atomic.Uint64, len(clientRpcClients))   // Send light request like crazy. for i, c := range clientRpcClients { @@ -157,7 +157,7 @@ go func() { defer wg.Done()   queue := make(chan struct{}, 100) - reqCount[i] = 0 + reqCount[i].Store(0) for { select { case queue <- struct{}{}: @@ -173,8 +173,7 @@ ok := testRequest(ctx, t, c) wg.Done() <-queue if ok { - count := atomic.AddUint64(&reqCount[i], 1) - if count%10000 == 0 { + if reqCount[i].Add(1)%10000 == 0 { freezeClient(ctx, t, serverRpcClient, clients[i].ID()) } } @@ -192,7 +191,7 @@ processedSince := func(start []uint64) []uint64 { res := make([]uint64, len(reqCount)) for i := range reqCount { - res[i] = atomic.LoadUint64(&reqCount[i]) + res[i] = reqCount[i].Load() if start != nil { res[i] -= start[i] } @@ -292,8 +291,8 @@ close(stop) wg.Wait()   - for i, count := range reqCount { - t.Log("client", i, "processed", count) + for i := range reqCount { + t.Log("client", i, "processed", reqCount[i].Load()) } return true }) {
diff --git ethereum/go-ethereum/les/odr_requests.go taikoxyz/taiko-geth/les/odr_requests.go index 2b23e0540cc0e5ef17b9ea24f6ac105967159a73..c907018590fae1c263998f2f0691c36e37234479 100644 --- ethereum/go-ethereum/les/odr_requests.go +++ taikoxyz/taiko-geth/les/odr_requests.go @@ -30,6 +30,7 @@ "github.com/ethereum/go-ethereum/light" "github.com/ethereum/go-ethereum/log" "github.com/ethereum/go-ethereum/rlp" "github.com/ethereum/go-ethereum/trie" + "github.com/ethereum/go-ethereum/trie/trienode" )   var ( @@ -222,9 +223,9 @@ if msg.MsgType != MsgProofsV2 { return errInvalidMessageType } - proofs := msg.Obj.(light.NodeList) + proofs := msg.Obj.(trienode.ProofList) // Verify the proof and store if checks out - nodeSet := proofs.NodeSet() + nodeSet := proofs.Set() reads := &readTraceDB{db: nodeSet} if _, err := trie.VerifyProof(r.Id.Root, r.Key, reads); err != nil { return fmt.Errorf("merkle proof verification failed: %v", err) @@ -308,7 +309,7 @@ FromLevel, AuxReq uint }   type HelperTrieResps struct { // describes all responses, not just a single one - Proofs light.NodeList + Proofs trienode.ProofList AuxData [][]byte }   @@ -356,7 +357,7 @@ resp := msg.Obj.(HelperTrieResps) if len(resp.AuxData) != 1 { return errInvalidEntryCount } - nodeSet := resp.Proofs.NodeSet() + nodeSet := resp.Proofs.Set() headerEnc := resp.AuxData[0] if len(headerEnc) == 0 { return errHeaderUnavailable @@ -451,7 +452,7 @@ return errInvalidMessageType } resps := msg.Obj.(HelperTrieResps) proofs := resps.Proofs - nodeSet := proofs.NodeSet() + nodeSet := proofs.Set() reads := &readTraceDB{db: nodeSet}   r.BloomBits = make([][]byte, len(r.SectionIndexList))
diff --git ethereum/go-ethereum/les/handler_test.go taikoxyz/taiko-geth/les/handler_test.go index 81a34a25e8ccd092c8275b35b5df65ea29528366..c803a5ddb3f29f784f7fa64858f61aa7c5c6e030 100644 --- ethereum/go-ethereum/les/handler_test.go +++ taikoxyz/taiko-geth/les/handler_test.go @@ -37,6 +37,7 @@ "github.com/ethereum/go-ethereum/p2p" "github.com/ethereum/go-ethereum/params" "github.com/ethereum/go-ethereum/rlp" "github.com/ethereum/go-ethereum/trie" + "github.com/ethereum/go-ethereum/trie/trienode" )   func expectResponse(r p2p.MsgReader, msgcode, reqID, bv uint64, data interface{}) error { @@ -401,12 +402,12 @@ bc := server.handler.blockchain   var proofreqs []ProofReq - proofsV2 := light.NewNodeSet() + proofsV2 := trienode.NewProofSet()   accounts := []common.Address{bankAddr, userAddr1, userAddr2, signerAddr, {}} for i := uint64(0); i <= bc.CurrentBlock().Number.Uint64(); i++ { header := bc.GetHeaderByNumber(i) - trie, _ := trie.New(trie.StateTrieID(header.Root), trie.NewDatabase(server.db)) + trie, _ := trie.New(trie.StateTrieID(header.Root), server.backend.Blockchain().TrieDB())   for _, acc := range accounts { req := ProofReq{ @@ -419,7 +420,7 @@ } } // Send the proof request and verify the response sendRequest(rawPeer.app, GetProofsV2Msg, 42, proofreqs) - if err := expectResponse(rawPeer.app, ProofsV2Msg, 42, testBufLimit, proofsV2.NodeList()); err != nil { + if err := expectResponse(rawPeer.app, ProofsV2Msg, 42, testBufLimit, proofsV2.List()); err != nil { t.Errorf("proofs mismatch: %v", err) } } @@ -456,10 +457,10 @@ sendRequest(rawPeer.app, GetProofsV2Msg, 42, []*ProofReq{req})   var expected []rlp.RawValue if wantOK { - proofsV2 := light.NewNodeSet() - t, _ := trie.New(trie.StateTrieID(header.Root), trie.NewDatabase(server.db)) + proofsV2 := trienode.NewProofSet() + t, _ := trie.New(trie.StateTrieID(header.Root), server.backend.Blockchain().TrieDB()) t.Prove(account, proofsV2) - expected = proofsV2.NodeList() + expected = proofsV2.List() } if err := expectResponse(rawPeer.app, ProofsV2Msg, 42, testBufLimit, expected); err != nil { t.Errorf("codes mismatch: %v", err) @@ -513,7 +514,7 @@ proofsV2 := HelperTrieResps{ AuxData: [][]byte{rlp}, } root := light.GetChtRoot(server.db, 0, bc.GetHeaderByNumber(config.ChtSize-1).Hash()) - trie, _ := trie.New(trie.TrieID(root), trie.NewDatabase(rawdb.NewTable(server.db, string(rawdb.ChtTablePrefix)))) + trie, _ := trie.New(trie.TrieID(root), trie.NewDatabase(rawdb.NewTable(server.db, string(rawdb.ChtTablePrefix)), trie.HashDefaults)) trie.Prove(key, &proofsV2.Proofs) // Assemble the requests for the different protocols requestsV2 := []HelperTrieReq{{ @@ -578,7 +579,7 @@ }} var proofs HelperTrieResps   root := light.GetBloomTrieRoot(server.db, 0, bc.GetHeaderByNumber(config.BloomTrieSize-1).Hash()) - trie, _ := trie.New(trie.TrieID(root), trie.NewDatabase(rawdb.NewTable(server.db, string(rawdb.BloomTrieTablePrefix)))) + trie, _ := trie.New(trie.TrieID(root), trie.NewDatabase(rawdb.NewTable(server.db, string(rawdb.BloomTrieTablePrefix)), trie.HashDefaults)) trie.Prove(key, &proofs.Proofs)   // Send the proof request and verify the response
diff --git ethereum/go-ethereum/les/peer.go taikoxyz/taiko-geth/les/peer.go index 48381689ef7ad7e490ea4ef9d42038cfeb048acd..58cb9287003169ada48d9eb1fd1ec659950be4be 100644 --- ethereum/go-ethereum/les/peer.go +++ taikoxyz/taiko-geth/les/peer.go @@ -40,6 +40,7 @@ "github.com/ethereum/go-ethereum/light" "github.com/ethereum/go-ethereum/p2p" "github.com/ethereum/go-ethereum/p2p/enode" "github.com/ethereum/go-ethereum/rlp" + "github.com/ethereum/go-ethereum/trie/trienode" )   var ( @@ -899,7 +900,7 @@ return &reply{p.rw, ReceiptsMsg, reqID, data} }   // replyProofsV2 creates a reply with a batch of merkle proofs, corresponding to the ones requested. -func (p *clientPeer) replyProofsV2(reqID uint64, proofs light.NodeList) *reply { +func (p *clientPeer) replyProofsV2(reqID uint64, proofs trienode.ProofList) *reply { data, _ := rlp.EncodeToBytes(proofs) return &reply{p.rw, ProofsV2Msg, reqID, data} }
diff --git ethereum/go-ethereum/les/peer_test.go taikoxyz/taiko-geth/les/peer_test.go index 021d5cb594c4f489c6089ea01f1156e4b39bc078..0881dd292b15bb55ddfec494f8d2e659646877fc 100644 --- ethereum/go-ethereum/les/peer_test.go +++ taikoxyz/taiko-geth/les/peer_test.go @@ -124,8 +124,8 @@ headNum = uint64(10) genesis = common.HexToHash("cafebabe")   chain1, chain2 = &fakeChain{}, &fakeChain{} - forkID1 = forkid.NewID(chain1.Config(), chain1.Genesis().Hash(), chain1.CurrentHeader().Number.Uint64(), chain1.CurrentHeader().Time) - forkID2 = forkid.NewID(chain2.Config(), chain2.Genesis().Hash(), chain2.CurrentHeader().Number.Uint64(), chain2.CurrentHeader().Time) + forkID1 = forkid.NewID(chain1.Config(), chain1.Genesis(), chain1.CurrentHeader().Number.Uint64(), chain1.CurrentHeader().Time) + forkID2 = forkid.NewID(chain2.Config(), chain2.Genesis(), chain2.CurrentHeader().Number.Uint64(), chain2.CurrentHeader().Time) filter1, filter2 = forkid.NewFilter(chain1), forkid.NewFilter(chain2) )
diff --git ethereum/go-ethereum/les/client.go taikoxyz/taiko-geth/les/client.go index 132c857aa529ec59c004fb01a6b4f66c800e1486..be5e9fd5641dc23ce2f0268703607ac14a45bf0d 100644 --- ethereum/go-ethereum/les/client.go +++ taikoxyz/taiko-geth/les/client.go @@ -98,7 +98,8 @@ } if config.OverrideVerkle != nil { overrides.OverrideVerkle = config.OverrideVerkle } - chainConfig, genesisHash, genesisErr := core.SetupGenesisBlockWithOverride(chainDb, trie.NewDatabase(chainDb), config.Genesis, &overrides) + triedb := trie.NewDatabase(chainDb, trie.HashDefaults) + chainConfig, genesisHash, genesisErr := core.SetupGenesisBlockWithOverride(chainDb, triedb, config.Genesis, &overrides) if _, isCompat := genesisErr.(*params.ConfigCompatError); genesisErr != nil && !isCompat { return nil, genesisErr }

This shows changes to miner files.

This adds Taiko-specific miner changes.

diff --git ethereum/go-ethereum/miner/worker_test.go taikoxyz/taiko-geth/miner/worker_test.go index 80557d99bfcf10a90166cc24605bf59001cae1ff..9c4694c0e20deade0c1c929f61dab094205c8d1c 100644 --- ethereum/go-ethereum/miner/worker_test.go +++ taikoxyz/taiko-geth/miner/worker_test.go @@ -63,7 +63,7 @@ testUserKey, _ = crypto.GenerateKey() testUserAddress = crypto.PubkeyToAddress(testUserKey.PublicKey)   // Test transactions - pendingTxs []*txpool.Transaction + pendingTxs []*types.Transaction newTxs []*types.Transaction   testConfig = &Config{ @@ -93,7 +93,7 @@ Value: big.NewInt(1000), Gas: params.TxGas, GasPrice: big.NewInt(params.InitialBaseFee), }) - pendingTxs = append(pendingTxs, &txpool.Transaction{Tx: tx1}) + pendingTxs = append(pendingTxs, tx1)   tx2 := types.MustSignNewTx(testBankKey, signer, &types.LegacyTx{ Nonce: 1, @@ -194,8 +194,8 @@ // Start mining! w.start()   for i := 0; i < 5; i++ { - b.txPool.Add([]*txpool.Transaction{{Tx: b.newRandomTx(true)}}, true, false) - b.txPool.Add([]*txpool.Transaction{{Tx: b.newRandomTx(false)}}, true, false) + b.txPool.Add([]*types.Transaction{b.newRandomTx(true)}, true, false) + b.txPool.Add([]*types.Transaction{b.newRandomTx(false)}, true, false)   select { case ev := <-sub.Chan(): @@ -452,32 +452,50 @@ }   // This API should work even when the automatic sealing is not enabled for _, c := range cases { - block, _, err := w.getSealingBlock(c.parent, timestamp, c.coinbase, c.random, nil, false) + r := w.getSealingBlock(&generateParams{ + parentHash: c.parent, + timestamp: timestamp, + coinbase: c.coinbase, + random: c.random, + withdrawals: nil, + beaconRoot: nil, + noTxs: false, + forceTime: true, + }) if c.expectErr { - if err == nil { + if r.err == nil { t.Error("Expect error but get nil") } } else { - if err != nil { - t.Errorf("Unexpected error %v", err) + if r.err != nil { + t.Errorf("Unexpected error %v", r.err) } - assertBlock(block, c.expectNumber, c.coinbase, c.random) + assertBlock(r.block, c.expectNumber, c.coinbase, c.random) } }   // This API should work even when the automatic sealing is enabled w.start() for _, c := range cases { - block, _, err := w.getSealingBlock(c.parent, timestamp, c.coinbase, c.random, nil, false) + r := w.getSealingBlock(&generateParams{ + parentHash: c.parent, + timestamp: timestamp, + coinbase: c.coinbase, + random: c.random, + withdrawals: nil, + beaconRoot: nil, + noTxs: false, + forceTime: true, + }) if c.expectErr { - if err == nil { + if r.err == nil { t.Error("Expect error but get nil") } } else { - if err != nil { - t.Errorf("Unexpected error %v", err) + if r.err != nil { + t.Errorf("Unexpected error %v", r.err) } - assertBlock(block, c.expectNumber, c.coinbase, c.random) + assertBlock(r.block, c.expectNumber, c.coinbase, c.random) } } }
diff --git ethereum/go-ethereum/miner/worker.go taikoxyz/taiko-geth/miner/worker.go index 97967ea2f18bd787961c9d6cb9add18b77c7af06..d6f0ca68813ea31b41a3ba57f45529a03cee52e5 100644 --- ethereum/go-ethereum/miner/worker.go +++ taikoxyz/taiko-geth/miner/worker.go @@ -27,10 +27,12 @@ "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/consensus" "github.com/ethereum/go-ethereum/consensus/misc/eip1559" + "github.com/ethereum/go-ethereum/consensus/misc/eip4844" "github.com/ethereum/go-ethereum/core" "github.com/ethereum/go-ethereum/core/state" "github.com/ethereum/go-ethereum/core/txpool" "github.com/ethereum/go-ethereum/core/types" + "github.com/ethereum/go-ethereum/core/vm" "github.com/ethereum/go-ethereum/event" "github.com/ethereum/go-ethereum/log" "github.com/ethereum/go-ethereum/params" @@ -89,6 +91,8 @@ header *types.Header txs []*types.Transaction receipts []*types.Receipt + sidecars []*types.BlobTxSidecar + blobs int }   // copy creates a deep copy of environment. @@ -107,6 +111,10 @@ cpy.gasPool = &gasPool } cpy.txs = make([]*types.Transaction, len(env.txs)) copy(cpy.txs, env.txs) + + cpy.sidecars = make([]*types.BlobTxSidecar, len(env.sidecars)) + copy(cpy.sidecars, env.sidecars) + return cpy }   @@ -141,11 +149,12 @@ interrupt *atomic.Int32 timestamp int64 }   -// newPayloadResult represents a result struct corresponds to payload generation. +// newPayloadResult is the result of payload generation. type newPayloadResult struct { - err error - block *types.Block - fees *big.Int + err error + block *types.Block + fees *big.Int // total block fees + sidecars []*types.BlobTxSidecar // collected blobs of blob transactions }   // getWorkReq represents a request for getting a new sealing work with provided parameters. @@ -254,8 +263,8 @@ exitCh: make(chan struct{}), resubmitIntervalCh: make(chan time.Duration), resubmitAdjustCh: make(chan *intervalAdjust, resubmitAdjustChanSize), } - // Subscribe NewTxsEvent for tx pool - worker.txsSub = eth.TxPool().SubscribeNewTxsEvent(worker.txsCh) + // Subscribe for transaction insertion events (whether from network or resurrects) + worker.txsSub = eth.TxPool().SubscribeTransactions(worker.txsCh, true) // Subscribe events for blockchain worker.chainHeadSub = eth.BlockChain().SubscribeChainHeadEvent(worker.chainHeadCh)   @@ -516,12 +525,7 @@ case req := <-w.newWorkCh: w.commitWork(req.interrupt, req.timestamp)   case req := <-w.getWorkCh: - block, fees, err := w.generateWork(req.params) - req.result <- &newPayloadResult{ - err: err, - block: block, - fees: fees, - } + req.result <- w.generateWork(req.params)   case ev := <-w.txsCh: // Apply transactions to the pending state if we're not sealing @@ -538,11 +542,14 @@ txs := make(map[common.Address][]*txpool.LazyTransaction, len(ev.Txs)) for _, tx := range ev.Txs { acc, _ := types.Sender(w.current.signer, tx) txs[acc] = append(txs[acc], &txpool.LazyTransaction{ + Pool: w.eth.TxPool(), // We don't know where this came from, yolo resolve from everywhere Hash: tx.Hash(), - Tx: &txpool.Transaction{Tx: tx}, + Tx: nil, // Do *not* set this! We need to resolve it later to pull blobs in Time: tx.Time(), GasFeeCap: tx.GasFeeCap(), GasTipCap: tx.GasTipCap(), + Gas: tx.Gas(), + BlobGas: tx.BlobGas(), }) } txset := newTransactionsByPriceAndNonce(w.current.signer, txs, w.current.header.BaseFee) @@ -734,21 +741,55 @@ w.snapshotReceipts = copyReceipts(env.receipts) w.snapshotState = env.state.Copy() }   -func (w *worker) commitTransaction(env *environment, tx *txpool.Transaction) ([]*types.Log, error) { +func (w *worker) commitTransaction(env *environment, tx *types.Transaction) ([]*types.Log, error) { + if tx.Type() == types.BlobTxType { + return w.commitBlobTransaction(env, tx) + } + receipt, err := w.applyTransaction(env, tx) + if err != nil { + return nil, err + } + env.txs = append(env.txs, tx) + env.receipts = append(env.receipts, receipt) + return receipt.Logs, nil +} + +func (w *worker) commitBlobTransaction(env *environment, tx *types.Transaction) ([]*types.Log, error) { + sc := tx.BlobTxSidecar() + if sc == nil { + panic("blob transaction without blobs in miner") + } + // Checking against blob gas limit: It's kind of ugly to perform this check here, but there + // isn't really a better place right now. The blob gas limit is checked at block validation time + // and not during execution. This means core.ApplyTransaction will not return an error if the + // tx has too many blobs. So we have to explicitly check it here. + if (env.blobs+len(sc.Blobs))*params.BlobTxBlobGasPerBlob > params.MaxBlobGasPerBlock { + return nil, errors.New("max data blobs reached") + } + receipt, err := w.applyTransaction(env, tx) + if err != nil { + return nil, err + } + env.txs = append(env.txs, tx.WithoutBlobTxSidecar()) + env.receipts = append(env.receipts, receipt) + env.sidecars = append(env.sidecars, sc) + env.blobs += len(sc.Blobs) + *env.header.BlobGasUsed += receipt.BlobGasUsed + return receipt.Logs, nil +} + +// applyTransaction runs the transaction. If execution fails, state and gas pool are reverted. +func (w *worker) applyTransaction(env *environment, tx *types.Transaction) (*types.Receipt, error) { var ( snap = env.state.Snapshot() gp = env.gasPool.Gas() ) - receipt, err := core.ApplyTransaction(w.chainConfig, w.chain, &env.coinbase, env.gasPool, env.state, env.header, tx.Tx, &env.header.GasUsed, *w.chain.GetVMConfig()) + receipt, err := core.ApplyTransaction(w.chainConfig, w.chain, &env.coinbase, env.gasPool, env.state, env.header, tx, &env.header.GasUsed, *w.chain.GetVMConfig()) if err != nil { env.state.RevertToSnapshot(snap) env.gasPool.SetGas(gp) - return nil, err } - env.txs = append(env.txs, tx.Tx) - env.receipts = append(env.receipts, receipt) - - return receipt.Logs, nil + return receipt, err }   func (w *worker) commitTransactions(env *environment, txs *transactionsByPriceAndNonce, interrupt *atomic.Int32) error { @@ -775,33 +816,43 @@ ltx := txs.Peek() if ltx == nil { break } + // If we don't have enough space for the next transaction, skip the account. + if env.gasPool.Gas() < ltx.Gas { + log.Trace("Not enough gas left for transaction", "hash", ltx.Hash, "left", env.gasPool.Gas(), "needed", ltx.Gas) + txs.Pop() + continue + } + if left := uint64(params.MaxBlobGasPerBlock - env.blobs*params.BlobTxBlobGasPerBlob); left < ltx.BlobGas { + log.Trace("Not enough blob gas left for transaction", "hash", ltx.Hash, "left", left, "needed", ltx.BlobGas) + txs.Pop() + continue + } + // Transaction seems to fit, pull it up from the pool tx := ltx.Resolve() if tx == nil { - log.Warn("Ignoring evicted transaction") - + log.Trace("Ignoring evicted transaction", "hash", ltx.Hash) txs.Pop() continue } // Error may be ignored here. The error has already been checked // during transaction acceptance is the transaction pool. - from, _ := types.Sender(env.signer, tx.Tx) + from, _ := types.Sender(env.signer, tx)   // Check whether the tx is replay protected. If we're not in the EIP155 hf // phase, start ignoring the sender until we do. - if tx.Tx.Protected() && !w.chainConfig.IsEIP155(env.header.Number) { - log.Trace("Ignoring reply protected transaction", "hash", tx.Tx.Hash(), "eip155", w.chainConfig.EIP155Block) - + if tx.Protected() && !w.chainConfig.IsEIP155(env.header.Number) { + log.Trace("Ignoring replay protected transaction", "hash", ltx.Hash, "eip155", w.chainConfig.EIP155Block) txs.Pop() continue } // Start executing the transaction - env.state.SetTxContext(tx.Tx.Hash(), env.tcount) + env.state.SetTxContext(tx.Hash(), env.tcount)   logs, err := w.commitTransaction(env, tx) switch { case errors.Is(err, core.ErrNonceTooLow): // New head notification data race between the transaction pool and miner, shift - log.Trace("Skipping transaction with low nonce", "sender", from, "nonce", tx.Tx.Nonce()) + log.Trace("Skipping transaction with low nonce", "hash", ltx.Hash, "sender", from, "nonce", tx.Nonce()) txs.Shift()   case errors.Is(err, nil): @@ -813,7 +864,7 @@ default: // Transaction is regarded as invalid, drop all consecutive transactions from // the same sender because of `nonce-too-high` clause. - log.Debug("Transaction failed, account skipped", "hash", tx.Tx.Hash(), "err", err) + log.Debug("Transaction failed, account skipped", "hash", ltx.Hash, "err", err) txs.Pop() } } @@ -837,13 +888,15 @@ }   // generateParams wraps various of settings for generating sealing task. type generateParams struct { - timestamp uint64 // The timstamp for sealing task - forceTime bool // Flag whether the given timestamp is immutable or not - parentHash common.Hash // Parent block hash, empty means the latest chain head - coinbase common.Address // The fee recipient address for including transaction - random common.Hash // The randomness generated by beacon chain, empty before the merge - withdrawals types.Withdrawals // List of withdrawals to include in block. - noTxs bool // Flag whether an empty block without any transaction is expected + timestamp uint64 // The timstamp for sealing task + forceTime bool // Flag whether the given timestamp is immutable or not + parentHash common.Hash // Parent block hash, empty means the latest chain head + coinbase common.Address // The fee recipient address for including transaction + random common.Hash // The randomness generated by beacon chain, empty before the merge + withdrawals types.Withdrawals // List of withdrawals to include in block. + beaconRoot *common.Hash // The beacon root (cancun field). + noTxs bool // Flag whether an empty block without any transaction is expected + baseFeePerGas *big.Int // CHANGE(taiko): The base fee per gas for the next block }   // prepareWork constructs the sealing task according to the given parameters, @@ -866,10 +919,17 @@ // Sanity check the timestamp correctness, recap the timestamp // to parent+1 if the mutation is allowed. timestamp := genParams.timestamp if parent.Time >= timestamp { - if genParams.forceTime { - return nil, fmt.Errorf("invalid timestamp, parent %d given %d", parent.Time, timestamp) + // CHANGE(taiko): block.timestamp == parent.timestamp is allowed in Taiko protocol. + if !w.chainConfig.Taiko { + if genParams.forceTime { + return nil, fmt.Errorf("invalid timestamp, parent %d given %d", parent.Time, timestamp) + } + timestamp = parent.Time + 1 + } else { + if parent.Time > timestamp { + return nil, fmt.Errorf("invalid timestamp, parent %d given %d", parent.Time, timestamp) + } } - timestamp = parent.Time + 1 } // Construct the sealing block header. header := &types.Header{ @@ -889,12 +949,29 @@ header.MixDigest = genParams.random } // Set baseFee and GasLimit if we are on an EIP-1559 chain if w.chainConfig.IsLondon(header.Number) { - header.BaseFee = eip1559.CalcBaseFee(w.chainConfig, parent) - if !w.chainConfig.IsLondon(parent.Number) { - parentGasLimit := parent.GasLimit * w.chainConfig.ElasticityMultiplier() - header.GasLimit = core.CalcGasLimit(parentGasLimit, w.config.GasCeil) + if w.chainConfig.Taiko && genParams.baseFeePerGas != nil { + header.BaseFee = genParams.baseFeePerGas + } else { + header.BaseFee = eip1559.CalcBaseFee(w.chainConfig, parent) + if !w.chainConfig.IsLondon(parent.Number) { + parentGasLimit := parent.GasLimit * w.chainConfig.ElasticityMultiplier() + header.GasLimit = core.CalcGasLimit(parentGasLimit, w.config.GasCeil) + } } } + // Apply EIP-4844, EIP-4788. + if w.chainConfig.IsCancun(header.Number, header.Time) { + var excessBlobGas uint64 + if w.chainConfig.IsCancun(parent.Number, parent.Time) { + excessBlobGas = eip4844.CalcExcessBlobGas(*parent.ExcessBlobGas, *parent.BlobGasUsed) + } else { + // For the first post-fork block, both parent.data_gas_used and parent.excess_data_gas are evaluated as 0 + excessBlobGas = eip4844.CalcExcessBlobGas(0, 0) + } + header.BlobGasUsed = new(uint64) + header.ExcessBlobGas = &excessBlobGas + header.ParentBeaconRoot = genParams.beaconRoot + } // Run the consensus preparation with the default or customized consensus engine. if err := w.engine.Prepare(w.chain, header); err != nil { log.Error("Failed to prepare header for sealing", "err", err) @@ -908,6 +985,11 @@ if err != nil { log.Error("Failed to create sealing context", "err", err) return nil, err } + if header.ParentBeaconRoot != nil { + context := core.NewEVMBlockContext(header, w.chain, nil) + vmenv := vm.NewEVM(context, vm.TxContext{}, env.state, w.chainConfig, vm.Config{}) + core.ProcessBeaconBlockRoot(*header.ParentBeaconRoot, vmenv, env.state) + } return env, nil }   @@ -915,10 +997,9 @@ // fillTransactions retrieves the pending transactions from the txpool and fills them // into the given sealing block. The transaction selection and ordering strategy can // be customized with the plugin in the future. func (w *worker) fillTransactions(interrupt *atomic.Int32, env *environment) error { - // Split the pending transactions into locals and remotes - // Fill the block with all available pending transactions. pending := w.eth.TxPool().Pending(true)   + // Split the pending transactions into locals and remotes. localTxs, remoteTxs := make(map[common.Address][]*txpool.LazyTransaction), pending for _, account := range w.eth.TxPool().Locals() { if txs := remoteTxs[account]; len(txs) > 0 { @@ -926,6 +1007,8 @@ delete(remoteTxs, account) localTxs[account] = txs } } + + // Fill the block with all available pending transactions. if len(localTxs) > 0 { txs := newTransactionsByPriceAndNonce(env.signer, localTxs, env.header.BaseFee) if err := w.commitTransactions(env, txs, interrupt); err != nil { @@ -942,10 +1025,10 @@ return nil }   // generateWork generates a sealing block based on the given parameters. -func (w *worker) generateWork(params *generateParams) (*types.Block, *big.Int, error) { +func (w *worker) generateWork(params *generateParams) *newPayloadResult { work, err := w.prepareWork(params) if err != nil { - return nil, nil, err + return &newPayloadResult{err: err} } defer work.discard()   @@ -963,9 +1046,13 @@ } } block, err := w.engine.FinalizeAndAssemble(w.chain, work.header, work.state, work.txs, nil, work.receipts, params.withdrawals) if err != nil { - return nil, nil, err + return &newPayloadResult{err: err} + } + return &newPayloadResult{ + block: block, + fees: totalFees(block, work.receipts), + sidecars: work.sidecars, } - return block, totalFees(block, work.receipts), nil }   // commitWork generates several new sealing tasks based on the parent block @@ -1074,28 +1161,16 @@ // getSealingBlock generates the sealing block based on the given parameters. // The generation result will be passed back via the given channel no matter // the generation itself succeeds or not. -func (w *worker) getSealingBlock(parent common.Hash, timestamp uint64, coinbase common.Address, random common.Hash, withdrawals types.Withdrawals, noTxs bool) (*types.Block, *big.Int, error) { +func (w *worker) getSealingBlock(params *generateParams) *newPayloadResult { req := &getWorkReq{ - params: &generateParams{ - timestamp: timestamp, - forceTime: true, - parentHash: parent, - coinbase: coinbase, - random: random, - withdrawals: withdrawals, - noTxs: noTxs, - }, + params: params, result: make(chan *newPayloadResult, 1), } select { case w.getWorkCh <- req: - result := <-req.result - if result.err != nil { - return nil, nil, result.err - } - return result.block, result.fees, nil + return <-req.result case <-w.exitCh: - return nil, nil, errors.New("miner closed") + return &newPayloadResult{err: errors.New("miner closed")} } }
diff --git ethereum/go-ethereum/miner/ordering_test.go taikoxyz/taiko-geth/miner/ordering_test.go index 589633e0b8dd2a98a00680d2224e70d1e5632206..59d478274d7419e398737a62c9a06a7d4e68143d 100644 --- ethereum/go-ethereum/miner/ordering_test.go +++ taikoxyz/taiko-geth/miner/ordering_test.go @@ -88,10 +88,12 @@ t.Fatalf("failed to sign tx: %s", err) } groups[addr] = append(groups[addr], &txpool.LazyTransaction{ Hash: tx.Hash(), - Tx: &txpool.Transaction{Tx: tx}, + Tx: tx, Time: tx.Time(), GasFeeCap: tx.GasFeeCap(), GasTipCap: tx.GasTipCap(), + Gas: tx.Gas(), + BlobGas: tx.BlobGas(), }) } expectedCount += count @@ -101,7 +103,7 @@ txset := newTransactionsByPriceAndNonce(signer, groups, baseFee)   txs := types.Transactions{} for tx := txset.Peek(); tx != nil; tx = txset.Peek() { - txs = append(txs, tx.Tx.Tx) + txs = append(txs, tx.Tx) txset.Shift() } if len(txs) != expectedCount { @@ -153,10 +155,12 @@ tx.SetTime(time.Unix(0, int64(len(keys)-start)))   groups[addr] = append(groups[addr], &txpool.LazyTransaction{ Hash: tx.Hash(), - Tx: &txpool.Transaction{Tx: tx}, + Tx: tx, Time: tx.Time(), GasFeeCap: tx.GasFeeCap(), GasTipCap: tx.GasTipCap(), + Gas: tx.Gas(), + BlobGas: tx.BlobGas(), }) } // Sort the transactions and cross check the nonce ordering @@ -164,7 +168,7 @@ txset := newTransactionsByPriceAndNonce(signer, groups, nil)   txs := types.Transactions{} for tx := txset.Peek(); tx != nil; tx = txset.Peek() { - txs = append(txs, tx.Tx.Tx) + txs = append(txs, tx.Tx) txset.Shift() } if len(txs) != len(keys) {
diff --git ethereum/go-ethereum/miner/taiko_payload_building.go taikoxyz/taiko-geth/miner/taiko_payload_building.go new file mode 100644 index 0000000000000000000000000000000000000000..7458ee1ae2cba0b306fd5b570ed6706ffd9bd6bb --- /dev/null +++ taikoxyz/taiko-geth/miner/taiko_payload_building.go @@ -0,0 +1,44 @@ +package miner + +import ( + "math/big" + + "github.com/ethereum/go-ethereum/core/types" + "github.com/ethereum/go-ethereum/log" + "github.com/ethereum/go-ethereum/params" +) + +// SetFullBlock updates the full-block to the given block. +func (payload *Payload) SetFullBlock(block *types.Block, fees *big.Int) { + payload.lock.Lock() + defer payload.lock.Unlock() + + go payload.afterSetFullBlock() + + payload.full = block + payload.fullFees = fees + + feesInEther := new(big.Float).Quo(new(big.Float).SetInt(fees), big.NewFloat(params.Ether)) + log.Info("Updated payload", "id", payload.id, "number", block.NumberU64(), "hash", block.Hash(), + "txs", len(block.Transactions()), "gas", block.GasUsed(), "fees", feesInEther, + "root", block.Root()) + + payload.cond.Broadcast() // fire signal for notifying full block +} + +func (payload *Payload) afterSetFullBlock() { + payload.lock.Lock() + defer payload.lock.Unlock() + + select { + case <-payload.done: + log.Info("SetFullBlock payload done received", "id", payload.id) + return + default: + } + + select { + case payload.stop <- struct{}{}: + default: + } +}
diff --git ethereum/go-ethereum/miner/taiko_worker.go taikoxyz/taiko-geth/miner/taiko_worker.go new file mode 100644 index 0000000000000000000000000000000000000000..788cde176fc334b3b8460a53b8c8b1e7c42f6616 --- /dev/null +++ taikoxyz/taiko-geth/miner/taiko_worker.go @@ -0,0 +1,306 @@ +package miner + +import ( + "errors" + "fmt" + "math/big" + "time" + + "github.com/ethereum/go-ethereum/beacon/engine" + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/core" + "github.com/ethereum/go-ethereum/core/txpool" + "github.com/ethereum/go-ethereum/core/types" + "github.com/ethereum/go-ethereum/core/vm" + "github.com/ethereum/go-ethereum/log" + "github.com/ethereum/go-ethereum/params" + "github.com/ethereum/go-ethereum/rlp" +) + +// BuildTransactionsLists builds multiple transactions lists which satisfy all the given limits. +func (w *worker) BuildTransactionsLists( + beneficiary common.Address, + baseFee *big.Int, + maxTransactionsPerBlock uint64, + blockMaxGasLimit uint64, + maxBytesPerTxList uint64, + localAccounts []string, + maxTransactionsLists uint64, +) ([]types.Transactions, error) { + var ( + txsLists []types.Transactions + currentHead = w.chain.CurrentBlock() + ) + + if currentHead == nil { + return nil, fmt.Errorf("failed to find current head") + } + + // Check if tx pool is empty at first. + if len(w.eth.TxPool().Pending(false)) == 0 { + return txsLists, nil + } + + params := &generateParams{ + timestamp: uint64(time.Now().Unix()), + forceTime: true, + parentHash: currentHead.Hash(), + coinbase: beneficiary, + random: currentHead.MixDigest, + noTxs: false, + baseFeePerGas: baseFee, + } + + env, err := w.prepareWork(params) + if err != nil { + return nil, err + } + defer env.discard() + + var ( + signer = types.MakeSigner(w.chainConfig, new(big.Int).Add(currentHead.Number, common.Big1), currentHead.Time) + ) + + commitTxs := func() (types.Transactions, error) { + env.tcount = 0 + env.txs = []*types.Transaction{} + env.gasPool = new(core.GasPool).AddGas(blockMaxGasLimit) + env.header.GasLimit = blockMaxGasLimit + + // Split the pending transactions into locals and remotes, then + // fill the block with all available pending transactions. + localTxs, remoteTxs := w.getPendingTxs(localAccounts) + + w.commitL2Transactions( + env, + newTransactionsByPriceAndNonce(signer, localTxs, baseFee), + newTransactionsByPriceAndNonce(signer, remoteTxs, baseFee), + maxTransactionsPerBlock, + maxBytesPerTxList, + ) + + return env.txs, nil + } + + for i := 0; i < int(maxTransactionsLists); i++ { + txs, err := commitTxs() + if err != nil { + return nil, err + } + + if len(txs) == 0 { + break + } + + txsLists = append(txsLists, txs) + } + + return txsLists, nil +} + +// sealBlockWith mines and seals a block with the given block metadata. +func (w *worker) sealBlockWith( + parent common.Hash, + timestamp uint64, + blkMeta *engine.BlockMetadata, + baseFeePerGas *big.Int, + withdrawals types.Withdrawals, +) (*types.Block, error) { + // Decode transactions bytes. + var txs types.Transactions + if err := rlp.DecodeBytes(blkMeta.TxList, &txs); err != nil { + return nil, fmt.Errorf("failed to decode txList: %w", err) + } + + if len(txs) == 0 { + // A L2 block needs to have have at least one `V1TaikoL2.anchor` or + // `V1TaikoL2.invalidateBlock` transaction. + return nil, fmt.Errorf("too less transactions in the block") + } + + params := &generateParams{ + timestamp: timestamp, + forceTime: true, + parentHash: parent, + coinbase: blkMeta.Beneficiary, + random: blkMeta.MixHash, + withdrawals: withdrawals, + noTxs: false, + baseFeePerGas: baseFeePerGas, + } + + // Set extraData + w.extra = blkMeta.ExtraData + + env, err := w.prepareWork(params) + if err != nil { + return nil, err + } + defer env.discard() + + env.header.GasLimit = blkMeta.GasLimit + + // Commit transactions. + gasLimit := env.header.GasLimit + rules := w.chain.Config().Rules(env.header.Number, true, timestamp) + + env.gasPool = new(core.GasPool).AddGas(gasLimit) + + for i, tx := range txs { + if i == 0 { + if err := tx.MarkAsAnchor(); err != nil { + return nil, err + } + } + sender, err := types.LatestSignerForChainID(tx.ChainId()).Sender(tx) + if err != nil { + log.Info("Skip an invalid proposed transaction", "hash", tx.Hash(), "reason", err) + continue + } + + env.state.Prepare(rules, sender, blkMeta.Beneficiary, tx.To(), vm.ActivePrecompiles(rules), tx.AccessList()) + env.state.SetTxContext(tx.Hash(), env.tcount) + if _, err := w.commitTransaction(env, tx); err != nil { + log.Info("Skip an invalid proposed transaction", "hash", tx.Hash(), "reason", err) + continue + } + env.tcount++ + } + + block, err := w.engine.FinalizeAndAssemble(w.chain, env.header, env.state, env.txs, nil, env.receipts, withdrawals) + if err != nil { + return nil, err + } + + results := make(chan *types.Block, 1) + if err := w.engine.Seal(w.chain, block, results, nil); err != nil { + return nil, err + } + block = <-results + + return block, nil +} + +// getPendingTxs fetches the pending transactions from tx pool. +func (w *worker) getPendingTxs(localAccounts []string) ( + map[common.Address][]*txpool.LazyTransaction, + map[common.Address][]*txpool.LazyTransaction, +) { + pending := w.eth.TxPool().Pending(false) + localTxs, remoteTxs := make(map[common.Address][]*txpool.LazyTransaction), pending + + for _, local := range localAccounts { + account := common.HexToAddress(local) + if txs := remoteTxs[account]; len(txs) > 0 { + delete(remoteTxs, account) + localTxs[account] = txs + } + } + + return localTxs, remoteTxs +} + +// commitL2Transactions tries to commit the transactions into the given state. +func (w *worker) commitL2Transactions( + env *environment, + txsLocal *transactionsByPriceAndNonce, + txsRemote *transactionsByPriceAndNonce, + maxTransactionsPerBlock uint64, + maxBytesPerTxList uint64, +) { + var ( + txs = txsLocal + isLocal = true + accTxListBytes int + ) + +loop: + for { + // If we don't have enough gas for any further transactions then we're done. + if env.gasPool.Gas() < params.TxGas { + log.Trace("Not enough gas for further transactions", "have", env.gasPool, "want", params.TxGas) + break + } + + // Retrieve the next transaction and abort if all done. + ltx := txs.Peek() + if ltx == nil { + if isLocal { + txs = txsRemote + isLocal = false + continue + } + break + } + tx := ltx.Resolve() + if tx == nil { + log.Warn("Ignoring evicted transaction") + + txs.Pop() + continue + } + // Error may be ignored here. The error has already been checked + // during transaction acceptance is the transaction pool. + from, _ := types.Sender(env.signer, tx) + + b, err := rlp.EncodeToBytes(tx) + if err != nil { + log.Trace("Failed to rlp encode the pending transaction %s: %w", tx.Hash(), err) + txs.Pop() + continue + } + if accTxListBytes+len(b) >= int(maxBytesPerTxList) { + break + } + + // Check whether the tx is replay protected. If we're not in the EIP155 hf + // phase, start ignoring the sender until we do. + if tx.Protected() && !w.chainConfig.IsEIP155(env.header.Number) { + log.Trace("Ignoring reply protected transaction", "hash", tx.Hash(), "eip155", w.chainConfig.EIP155Block) + + txs.Pop() + continue + } + // Start executing the transaction + env.state.SetTxContext(tx.Hash(), env.tcount) + + _, err = w.commitTransaction(env, tx) + switch { + case errors.Is(err, core.ErrGasLimitReached): + // Pop the current out-of-gas transaction without shifting in the next from the account + log.Trace("Gas limit exceeded for current block", "sender", from) + txs.Pop() + + case errors.Is(err, core.ErrNonceTooLow): + // New head notification data race between the transaction pool and miner, shift + log.Trace("Skipping transaction with low nonce", "sender", from, "nonce", tx.Nonce()) + txs.Shift() + + case errors.Is(err, core.ErrNonceTooHigh): + // Reorg notification data race between the transaction pool and miner, skip account = + log.Trace("Skipping account with hight nonce", "sender", from, "nonce", tx.Nonce()) + txs.Pop() + + case errors.Is(err, nil): + // Everything ok, shift in the next transaction from the same account + env.tcount++ + txs.Shift() + + if env.tcount >= int(maxTransactionsPerBlock) { + break loop + } + accTxListBytes += len(b) + + case errors.Is(err, types.ErrTxTypeNotSupported): + // Pop the unsupported transaction without shifting in the next from the account + log.Trace("Skipping unsupported transaction type", "sender", from, "type", tx.Type()) + txs.Pop() + + default: + // Strange error, discard the transaction and get the next in line (note, the + // nonce-too-high clause will prevent us from executing in vain). + log.Debug("Transaction failed, account skipped", "hash", tx.Hash(), "err", err) + txs.Shift() + } + } +}
diff --git ethereum/go-ethereum/miner/taiko_miner.go taikoxyz/taiko-geth/miner/taiko_miner.go new file mode 100644 index 0000000000000000000000000000000000000000..a5374f6ee2a1f9967a7c05fb92ab46d29a869bb6 --- /dev/null +++ taikoxyz/taiko-geth/miner/taiko_miner.go @@ -0,0 +1,41 @@ +package miner + +import ( + "math/big" + + "github.com/ethereum/go-ethereum/beacon/engine" + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/core/types" +) + +// SealBlockWith mines and seals a block without changing the canonical chain. +func (miner *Miner) SealBlockWith( + parent common.Hash, + timestamp uint64, + blkMeta *engine.BlockMetadata, + baseFeePerGas *big.Int, + withdrawals types.Withdrawals, +) (*types.Block, error) { + return miner.worker.sealBlockWith(parent, timestamp, blkMeta, baseFeePerGas, withdrawals) +} + +// BuildTransactionsLists builds multiple transactions lists which satisfy all the given limits. +func (miner *Miner) BuildTransactionsLists( + beneficiary common.Address, + baseFee *big.Int, + maxTransactionsPerBlock uint64, + blockMaxGasLimit uint64, + maxBytesPerTxList uint64, + locals []string, + maxTransactionsLists uint64, +) ([]types.Transactions, error) { + return miner.worker.BuildTransactionsLists( + beneficiary, + baseFee, + maxTransactionsPerBlock, + blockMaxGasLimit, + maxBytesPerTxList, + locals, + maxTransactionsLists, + ) +}
diff --git ethereum/go-ethereum/miner/miner_test.go taikoxyz/taiko-geth/miner/miner_test.go index 21db1ce4a9e6d938f1044f0e0971a4383831d134..36d5166c6dbef7d97f559c252d0b937e98f6fac6 100644 --- ethereum/go-ethereum/miner/miner_test.go +++ taikoxyz/taiko-geth/miner/miner_test.go @@ -64,6 +64,7 @@ return nil, errors.New("not supported") }   type testBlockChain struct { + root common.Hash config *params.ChainConfig statedb *state.StateDB gasLimit uint64 @@ -87,6 +88,10 @@ }   func (bc *testBlockChain) StateAt(common.Hash) (*state.StateDB, error) { return bc.statedb, nil +} + +func (bc *testBlockChain) HasState(root common.Hash) bool { + return bc.root == root }   func (bc *testBlockChain) SubscribeChainHeadEvent(ch chan<- core.ChainHeadEvent) event.Subscription { @@ -288,8 +293,9 @@ Etherbase: common.HexToAddress("123456789"), } // Create chainConfig chainDB := rawdb.NewMemoryDatabase() + triedb := trie.NewDatabase(chainDB, nil) genesis := minerTestGenesisBlock(15, 11_500_000, common.HexToAddress("12345")) - chainConfig, _, err := core.SetupGenesisBlock(chainDB, trie.NewDatabase(chainDB), genesis) + chainConfig, _, err := core.SetupGenesisBlock(chainDB, triedb, genesis) if err != nil { t.Fatalf("can't create new chain config: %v", err) } @@ -300,8 +306,8 @@ bc, err := core.NewBlockChain(chainDB, nil, genesis, nil, engine, vm.Config{}, nil, nil) if err != nil { t.Fatalf("can't create new chain %v", err) } - statedb, _ := state.New(types.EmptyRootHash, state.NewDatabase(chainDB), nil) - blockchain := &testBlockChain{chainConfig, statedb, 10000000, new(event.Feed)} + statedb, _ := state.New(bc.Genesis().Root(), bc.StateCache(), nil) + blockchain := &testBlockChain{bc.Genesis().Root(), chainConfig, statedb, 10000000, new(event.Feed)}   pool := legacypool.New(testTxPoolConfig, blockchain) txpool, _ := txpool.New(new(big.Int).SetUint64(testTxPoolConfig.PriceLimit), blockchain, []txpool.SubPool{pool})
diff --git ethereum/go-ethereum/miner/payload_building.go taikoxyz/taiko-geth/miner/payload_building.go index 299196a3cdf3fcc872508859a7b0193ba47ded20..99f9c6b82033e0bf69620d0afc2614af3db61719 100644 --- ethereum/go-ethereum/miner/payload_building.go +++ taikoxyz/taiko-geth/miner/payload_building.go @@ -33,13 +33,14 @@ )   // BuildPayloadArgs contains the provided parameters for building payload. // Check engine-api specification for more details. -// https://github.com/ethereum/execution-apis/blob/main/src/engine/specification.md#payloadattributesv1 +// https://github.com/ethereum/execution-apis/blob/main/src/engine/cancun.md#payloadattributesv3 type BuildPayloadArgs struct { Parent common.Hash // The parent block to build payload on top Timestamp uint64 // The provided timestamp of generated payload FeeRecipient common.Address // The provided recipient address for collecting transaction fee Random common.Hash // The provided randomness value Withdrawals types.Withdrawals // The provided withdrawals + BeaconRoot *common.Hash // The provided beaconRoot (Cancun) }   // Id computes an 8-byte identifier by hashing the components of the payload arguments. @@ -51,6 +52,9 @@ binary.Write(hasher, binary.BigEndian, args.Timestamp) hasher.Write(args.Random[:]) hasher.Write(args.FeeRecipient[:]) rlp.Encode(hasher, args.Withdrawals) + if args.BeaconRoot != nil { + hasher.Write(args.BeaconRoot[:]) + } var out engine.PayloadID copy(out[:], hasher.Sum(nil)[:8]) return out @@ -65,10 +69,12 @@ type Payload struct { id engine.PayloadID empty *types.Block full *types.Block + sidecars []*types.BlobTxSidecar fullFees *big.Int stop chan struct{} lock sync.Mutex cond *sync.Cond + done chan struct{} // CHANGE(taiko): done channel to communicate we shouldnt write to `stop` channel. }   // newPayload initializes the payload object. @@ -77,6 +83,7 @@ payload := &Payload{ id: id, empty: empty, stop: make(chan struct{}), + done: make(chan struct{}, 1), // CHANGE(taiko): buffered channel to communicate done to taiko payload builder } log.Info("Starting work on payload", "id", payload.id) payload.cond = sync.NewCond(&payload.lock) @@ -84,7 +91,7 @@ return payload }   // update updates the full-block with latest built version. -func (payload *Payload) update(block *types.Block, fees *big.Int, elapsed time.Duration) { +func (payload *Payload) update(r *newPayloadResult, elapsed time.Duration) { payload.lock.Lock() defer payload.lock.Unlock()   @@ -96,14 +103,23 @@ } // Ensure the newly provided full block has a higher transaction fee. // In post-merge stage, there is no uncle reward anymore and transaction // fee(apart from the mev revenue) is the only indicator for comparison. - if payload.full == nil || fees.Cmp(payload.fullFees) > 0 { - payload.full = block - payload.fullFees = fees + if payload.full == nil || r.fees.Cmp(payload.fullFees) > 0 { + payload.full = r.block + payload.fullFees = r.fees + payload.sidecars = r.sidecars   - feesInEther := new(big.Float).Quo(new(big.Float).SetInt(fees), big.NewFloat(params.Ether)) - log.Info("Updated payload", "id", payload.id, "number", block.NumberU64(), "hash", block.Hash(), - "txs", len(block.Transactions()), "withdrawals", len(block.Withdrawals()), "gas", block.GasUsed(), - "fees", feesInEther, "root", block.Root(), "elapsed", common.PrettyDuration(elapsed)) + feesInEther := new(big.Float).Quo(new(big.Float).SetInt(r.fees), big.NewFloat(params.Ether)) + log.Info("Updated payload", + "id", payload.id, + "number", r.block.NumberU64(), + "hash", r.block.Hash(), + "txs", len(r.block.Transactions()), + "withdrawals", len(r.block.Withdrawals()), + "gas", r.block.GasUsed(), + "fees", feesInEther, + "root", r.block.Root(), + "elapsed", common.PrettyDuration(elapsed), + ) } payload.cond.Broadcast() // fire signal for notifying full block } @@ -120,9 +136,9 @@ default: close(payload.stop) } if payload.full != nil { - return engine.BlockToExecutableData(payload.full, payload.fullFees, nil, nil, nil) + return engine.BlockToExecutableData(payload.full, payload.fullFees, payload.sidecars) } - return engine.BlockToExecutableData(payload.empty, big.NewInt(0), nil, nil, nil) + return engine.BlockToExecutableData(payload.empty, big.NewInt(0), nil) }   // ResolveEmpty is basically identical to Resolve, but it expects empty block only. @@ -131,7 +147,7 @@ func (payload *Payload) ResolveEmpty() *engine.ExecutionPayloadEnvelope { payload.lock.Lock() defer payload.lock.Unlock()   - return engine.BlockToExecutableData(payload.empty, big.NewInt(0), nil, nil, nil) + return engine.BlockToExecutableData(payload.empty, big.NewInt(0), nil) }   // ResolveFull is basically identical to Resolve, but it expects full block only. @@ -155,9 +171,10 @@ // Terminate the background payload construction select { case <-payload.stop: default: + payload.done <- struct{}{} // CHANGE(taiko): signal to taiko payload builder to not write to `payload.stop` channel close(payload.stop) } - return engine.BlockToExecutableData(payload.full, payload.fullFees, nil, nil, nil) + return engine.BlockToExecutableData(payload.full, payload.fullFees, payload.sidecars) }   // buildPayload builds the payload according to the provided parameters. @@ -165,12 +182,23 @@ func (w *worker) buildPayload(args *BuildPayloadArgs) (*Payload, error) { // Build the initial version with no transaction included. It should be fast // enough to run. The empty payload can at least make sure there is something // to deliver for not missing slot. - empty, _, err := w.getSealingBlock(args.Parent, args.Timestamp, args.FeeRecipient, args.Random, args.Withdrawals, true) - if err != nil { - return nil, err + emptyParams := &generateParams{ + timestamp: args.Timestamp, + forceTime: true, + parentHash: args.Parent, + coinbase: args.FeeRecipient, + random: args.Random, + withdrawals: args.Withdrawals, + beaconRoot: args.BeaconRoot, + noTxs: true, + } + empty := w.getSealingBlock(emptyParams) + if empty.err != nil { + return nil, empty.err } + // Construct a payload object for return. - payload := newPayload(empty, args.Id()) + payload := newPayload(empty.block, args.Id())   // Spin up a routine for updating the payload in background. This strategy // can maximum the revenue for including transactions with highest fee. @@ -185,13 +213,28 @@ // the Mainnet configuration) have passed since the point in time identified // by the timestamp parameter. endTimer := time.NewTimer(time.Second * 12)   + fullParams := &generateParams{ + timestamp: args.Timestamp, + forceTime: true, + parentHash: args.Parent, + coinbase: args.FeeRecipient, + random: args.Random, + withdrawals: args.Withdrawals, + beaconRoot: args.BeaconRoot, + noTxs: false, + } + for { select { case <-timer.C: + // CHANGE(taiko): do not update payload. + if w.chainConfig.Taiko { + continue + } start := time.Now() - block, fees, err := w.getSealingBlock(args.Parent, args.Timestamp, args.FeeRecipient, args.Random, args.Withdrawals, false) - if err == nil { - payload.update(block, fees, time.Since(start)) + r := w.getSealingBlock(fullParams) + if r.err == nil { + payload.update(r, time.Since(start)) } timer.Reset(w.recommit) case <-payload.stop:
diff --git ethereum/go-ethereum/miner/taiko_payload_building_test.go taikoxyz/taiko-geth/miner/taiko_payload_building_test.go new file mode 100644 index 0000000000000000000000000000000000000000..6b7118c3a86045c2f5a089a0bd169642ce85d5d1 --- /dev/null +++ taikoxyz/taiko-geth/miner/taiko_payload_building_test.go @@ -0,0 +1,140 @@ +package miner + +import ( + "math/big" + "testing" + "time" + + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/consensus/ethash" + "github.com/ethereum/go-ethereum/core/rawdb" + "github.com/ethereum/go-ethereum/core/types" + "github.com/ethereum/go-ethereum/params" + "github.com/ethereum/go-ethereum/trie" + "github.com/stretchr/testify/assert" +) + +func newTestBlock() *types.Block { + tx1 := types.NewTransaction(1, common.BytesToAddress([]byte{0x11}), big.NewInt(111), 1111, big.NewInt(11111), []byte{0x11, 0x11, 0x11}) + txs := []*types.Transaction{tx1} + + block := types.NewBlock(&types.Header{Number: big.NewInt(314)}, txs, nil, nil, trie.NewStackTrie(nil)) + return block +} + +func TestSetFullBlock_AvoidPanic(t *testing.T) { + var ( + db = rawdb.NewMemoryDatabase() + recipient = common.HexToAddress("0xdeadbeef") + ) + w, b := newTestWorker(t, params.TestChainConfig, ethash.NewFaker(), db, 0) + defer w.close() + + timestamp := uint64(time.Now().Unix()) + args := &BuildPayloadArgs{ + Parent: b.chain.CurrentBlock().Hash(), + Timestamp: timestamp, + Random: common.Hash{}, + FeeRecipient: recipient, + } + payload, err := w.buildPayload(args) + if err != nil { + t.Fatalf("Failed to build payload %v", err) + } + + fees := big.NewInt(1) + + payload.done <- struct{}{} + close(payload.stop) + + block := newTestBlock() + // expect not to panic sending to payload.stop + // now that done is closed + payload.SetFullBlock(block, fees) +} + +func TestAfterSetFullBlock_Panic_DoneChannelNotSent(t *testing.T) { + var ( + db = rawdb.NewMemoryDatabase() + recipient = common.HexToAddress("0xdeadbeef") + ) + w, b := newTestWorker(t, params.TestChainConfig, ethash.NewFaker(), db, 0) + defer w.close() + + timestamp := uint64(time.Now().Unix()) + args := &BuildPayloadArgs{ + Parent: b.chain.CurrentBlock().Hash(), + Timestamp: timestamp, + Random: common.Hash{}, + FeeRecipient: recipient, + } + payload, err := w.buildPayload(args) + if err != nil { + t.Fatalf("Failed to build payload %v", err) + } + + // dont send on done channel, but close stop channel. + // should panic when sent on. + close(payload.stop) + + assert.Panics(t, func() { + payload.afterSetFullBlock() + }) +} + +func TestAfterSetFullBlock_AvoidPanic_DoneChannelSent(t *testing.T) { + var ( + db = rawdb.NewMemoryDatabase() + recipient = common.HexToAddress("0xdeadbeef") + ) + w, b := newTestWorker(t, params.TestChainConfig, ethash.NewFaker(), db, 0) + defer w.close() + + timestamp := uint64(time.Now().Unix()) + args := &BuildPayloadArgs{ + Parent: b.chain.CurrentBlock().Hash(), + Timestamp: timestamp, + Random: common.Hash{}, + FeeRecipient: recipient, + } + payload, err := w.buildPayload(args) + if err != nil { + t.Fatalf("Failed to build payload %v", err) + } + + payload.done <- struct{}{} + close(payload.stop) + + assert.NotPanics(t, func() { + payload.afterSetFullBlock() + }) +} + +func TestSetFullBlock(t *testing.T) { + var ( + db = rawdb.NewMemoryDatabase() + recipient = common.HexToAddress("0xdeadbeef") + ) + w, b := newTestWorker(t, params.TestChainConfig, ethash.NewFaker(), db, 0) + defer w.close() + + timestamp := uint64(time.Now().Unix()) + args := &BuildPayloadArgs{ + Parent: b.chain.CurrentBlock().Hash(), + Timestamp: timestamp, + Random: common.Hash{}, + FeeRecipient: recipient, + } + payload, err := w.buildPayload(args) + if err != nil { + t.Fatalf("Failed to build payload %v", err) + } + + fees := big.NewInt(1) + + block := newTestBlock() + payload.SetFullBlock(block, fees) + + assert.Equal(t, block, payload.full) + assert.Equal(t, fees, payload.fullFees) +}

This shows changes to params files.

This adds Taiko config values such as chainIds/Network Ids.

diff --git ethereum/go-ethereum/params/version.go taikoxyz/taiko-geth/params/version.go index 7417dc0be2f6c5bc281346d4b4a5896d1381f2fe..0736259b59049925daac911a994cbd649d0501e4 100644 --- ethereum/go-ethereum/params/version.go +++ taikoxyz/taiko-geth/params/version.go @@ -22,8 +22,8 @@ )   const ( VersionMajor = 1 // Major version component of the current release - VersionMinor = 12 // Minor version component of the current release - VersionPatch = 2 // Patch version component of the current release + VersionMinor = 13 // Minor version component of the current release + VersionPatch = 4 // Patch version component of the current release VersionMeta = "stable" // Version metadata to append to the version string )
diff --git ethereum/go-ethereum/params/bootnodes.go taikoxyz/taiko-geth/params/bootnodes.go index edc6e06cb3dcb016c61a3f372376cbec57c295f1..a843896914a64596381459ad1bbd854c57fcad16 100644 --- ethereum/go-ethereum/params/bootnodes.go +++ taikoxyz/taiko-geth/params/bootnodes.go @@ -28,6 +28,14 @@ "enode://2b252ab6a1d0f971d9722cb839a42cb81db019ba44c08754628ab4a823487071b5695317c8ccd085219c3a03af063495b2f1da8d18218da2d6a82981b45e6ffc@65.108.70.101:30303", // bootnode-hetzner-hel "enode://4aeb4ab6c14b23e2c4cfdce879c04b0748a20d8e9b59e25ded2a08143e265c6c25936e74cbc8e641e3312ca288673d91f2f93f8e277de3cfa444ecdaaf982052@157.90.35.166:30303", // bootnode-hetzner-fsn }   +// HoleskyBootnodes are the enode URLs of the P2P bootstrap nodes running on the +// Holesky test network. +var HoleskyBootnodes = []string{ + // EF DevOps + "enode://ac906289e4b7f12df423d654c5a962b6ebe5b3a74cc9e06292a85221f9a64a6f1cfdd6b714ed6dacef51578f92b34c60ee91e9ede9c7f8fadc4d347326d95e2b@146.190.13.128:30303", + "enode://a3435a0155a3e837c02f5e7f5662a2f1fbc25b48e4dc232016e1c51b544cb5b4510ef633ea3278c0e970fa8ad8141e2d4d0f9f95456c537ff05fdf9b31c15072@178.128.136.233:30303", +} + // SepoliaBootnodes are the enode URLs of the P2P bootstrap nodes running on the // Sepolia test network. var SepoliaBootnodes = []string{ @@ -88,6 +96,8 @@ case GoerliGenesisHash: net = "goerli" case SepoliaGenesisHash: net = "sepolia" + case HoleskyGenesisHash: + net = "holesky" default: return "" }
diff --git ethereum/go-ethereum/params/taiko_config_test.go taikoxyz/taiko-geth/params/taiko_config_test.go new file mode 100644 index 0000000000000000000000000000000000000000..80e1ec8d7e94674b22de62de0c1d7f7d366a5105 --- /dev/null +++ taikoxyz/taiko-geth/params/taiko_config_test.go @@ -0,0 +1,78 @@ +package params + +import ( + "math/big" + "testing" +) + +func TestNetworkIDToChainConfigOrDefault(t *testing.T) { + tests := []struct { + name string + networkID *big.Int + wantChainConfig *ChainConfig + }{ + { + "taikoInternal", + TaikoInternalNetworkID, + TaikoChainConfig, + }, + { + "taikoInternalL3NetworkId", + TaikoInternalL3NetworkID, + TaikoChainConfig, + }, + { + "snaefoll", + SnaefellsjokullNetworkID, + TaikoChainConfig, + }, + { + "askja", + AskjaNetworkID, + TaikoChainConfig, + }, + { + "grimsvotn", + GrimsvotnNetworkID, + TaikoChainConfig, + }, + { + "eldfellNetworkID", + EldfellNetworkID, + TaikoChainConfig, + }, + { + "jolnirNetworkID", + JolnirNetworkID, + TaikoChainConfig, + }, + { + "mainnet", + MainnetChainConfig.ChainID, + MainnetChainConfig, + }, + { + "sepolia", + SepoliaChainConfig.ChainID, + SepoliaChainConfig, + }, + { + "goerli", + GoerliChainConfig.ChainID, + GoerliChainConfig, + }, + { + "doesntExist", + big.NewInt(89390218390), + AllEthashProtocolChanges, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if config := NetworkIDToChainConfigOrDefault(tt.networkID); config != tt.wantChainConfig { + t.Fatalf("expected %v, got %v", config, tt.wantChainConfig) + } + }) + } +}
diff --git ethereum/go-ethereum/params/taiko_config.go taikoxyz/taiko-geth/params/taiko_config.go new file mode 100644 index 0000000000000000000000000000000000000000..638cbc692b3331fa9cc1db85c02b3ae3d1ef5e28 --- /dev/null +++ taikoxyz/taiko-geth/params/taiko_config.go @@ -0,0 +1,62 @@ +package params + +import ( + "math/big" + + "github.com/ethereum/go-ethereum/common" +) + +func u64(val uint64) *uint64 { return &val } + +// Network IDs +var ( + TaikoInternalNetworkID = big.NewInt(167001) + TaikoInternalL3NetworkID = big.NewInt(167002) + SnaefellsjokullNetworkID = big.NewInt(167003) + AskjaNetworkID = big.NewInt(167004) + GrimsvotnNetworkID = big.NewInt(167005) + EldfellNetworkID = big.NewInt(167006) + JolnirNetworkID = big.NewInt(167007) +) + +var networkIDToChainConfig = map[*big.Int]*ChainConfig{ + TaikoInternalNetworkID: TaikoChainConfig, + TaikoInternalL3NetworkID: TaikoChainConfig, + SnaefellsjokullNetworkID: TaikoChainConfig, + AskjaNetworkID: TaikoChainConfig, + GrimsvotnNetworkID: TaikoChainConfig, + EldfellNetworkID: TaikoChainConfig, + JolnirNetworkID: TaikoChainConfig, + MainnetChainConfig.ChainID: MainnetChainConfig, + SepoliaChainConfig.ChainID: SepoliaChainConfig, + GoerliChainConfig.ChainID: GoerliChainConfig, + TestChainConfig.ChainID: TestChainConfig, + NonActivatedConfig.ChainID: NonActivatedConfig, +} + +func NetworkIDToChainConfigOrDefault(networkID *big.Int) *ChainConfig { + if config, ok := networkIDToChainConfig[networkID]; ok { + return config + } + + return AllEthashProtocolChanges +} + +var TaikoChainConfig = &ChainConfig{ + ChainID: TaikoInternalNetworkID, // Use Internal Devnet network ID by default. + HomesteadBlock: common.Big0, + EIP150Block: common.Big0, + EIP155Block: common.Big0, + EIP158Block: common.Big0, + ByzantiumBlock: common.Big0, + ConstantinopleBlock: common.Big0, + PetersburgBlock: common.Big0, + IstanbulBlock: common.Big0, + BerlinBlock: common.Big0, + LondonBlock: common.Big0, + ShanghaiTime: u64(0), + MergeNetsplitBlock: nil, + TerminalTotalDifficulty: common.Big0, + TerminalTotalDifficultyPassed: true, + Taiko: true, +}
diff --git ethereum/go-ethereum/params/config.go taikoxyz/taiko-geth/params/config.go index 75c8fd89d09fa946dca42be0ca940233aea6d7b6..5b768fb5505df1e921e61f66d7e86b34ab70deca 100644 --- ethereum/go-ethereum/params/config.go +++ taikoxyz/taiko-geth/params/config.go @@ -26,6 +26,7 @@ // Genesis hashes to enforce below configs on. var ( MainnetGenesisHash = common.HexToHash("0xd4e56740f876aef8c010b86a40d5f56745a118d0906a34e69aec8c0db1cb8fa3") + HoleskyGenesisHash = common.HexToHash("0xb5f7f912443c940f21fd611f12828d75b534364ed9e95ca4e307729a4661bde4") SepoliaGenesisHash = common.HexToHash("0x25a5cc106eea7138acab33231d7160d69cb777ee0c2c553fcddf5138993e6dd9") GoerliGenesisHash = common.HexToHash("0xbf7e331f7f7c1dd2e05159666b3bf8bc7a8a3a9eb1d518969eab529dd9b88c1a") ) @@ -58,6 +59,30 @@ TerminalTotalDifficultyPassed: true, ShanghaiTime: newUint64(1681338455), Ethash: new(EthashConfig), } + // HoleskyChainConfig contains the chain parameters to run a node on the Holesky test network. + HoleskyChainConfig = &ChainConfig{ + ChainID: big.NewInt(17000), + HomesteadBlock: big.NewInt(0), + DAOForkBlock: nil, + DAOForkSupport: true, + EIP150Block: big.NewInt(0), + EIP155Block: big.NewInt(0), + EIP158Block: big.NewInt(0), + ByzantiumBlock: big.NewInt(0), + ConstantinopleBlock: big.NewInt(0), + PetersburgBlock: big.NewInt(0), + IstanbulBlock: big.NewInt(0), + MuirGlacierBlock: nil, + BerlinBlock: big.NewInt(0), + LondonBlock: big.NewInt(0), + ArrowGlacierBlock: nil, + GrayGlacierBlock: nil, + TerminalTotalDifficulty: big.NewInt(0), + TerminalTotalDifficultyPassed: true, + MergeNetsplitBlock: nil, + ShanghaiTime: newUint64(1696000704), + Ethash: new(EthashConfig), + } // SepoliaChainConfig contains the chain parameters to run a node on the Sepolia test network. SepoliaChainConfig = &ChainConfig{ ChainID: big.NewInt(11155111), @@ -74,6 +99,8 @@ IstanbulBlock: big.NewInt(0), MuirGlacierBlock: big.NewInt(0), BerlinBlock: big.NewInt(0), LondonBlock: big.NewInt(0), + ArrowGlacierBlock: nil, + GrayGlacierBlock: nil, TerminalTotalDifficulty: big.NewInt(17_000_000_000_000_000), TerminalTotalDifficultyPassed: true, MergeNetsplitBlock: big.NewInt(1735371), @@ -187,7 +214,7 @@ Clique: &CliqueConfig{Period: 0, Epoch: 30000}, }   // TestChainConfig contains every protocol change (EIPs) introduced - // and accepted by the Ethereum core developers for testing proposes. + // and accepted by the Ethereum core developers for testing purposes. TestChainConfig = &ChainConfig{ ChainID: big.NewInt(1), HomesteadBlock: big.NewInt(0), @@ -253,6 +280,14 @@ var NetworkNames = map[string]string{ MainnetChainConfig.ChainID.String(): "mainnet", GoerliChainConfig.ChainID.String(): "goerli", SepoliaChainConfig.ChainID.String(): "sepolia", + HoleskyChainConfig.ChainID.String(): "holesky", + // CHANGE(taiko): add Taiko network name. + TaikoInternalNetworkID.String(): "Taiko Internal Devnet", + SnaefellsjokullNetworkID.String(): "Taiko Alpha-1 (Snæfellsjökull)", + AskjaNetworkID.String(): "Taiko Alpha-2 (Askja)", + GrimsvotnNetworkID.String(): "Taiko Alpha-3 L2 (Grimsvotn)", + EldfellNetworkID.String(): "Taiko Alpha-4 L3 (Eldfell)", + JolnirNetworkID.String(): "Taiko Alpha-5 L2 (Jolnir)", }   // ChainConfig is the core config which determines the blockchain settings. @@ -304,6 +339,9 @@ // Various consensus engines Ethash *EthashConfig `json:"ethash,omitempty"` Clique *CliqueConfig `json:"clique,omitempty"` IsDevMode bool `json:"isDev,omitempty"` + + // CHANGE(taiko): Taiko network flag. + Taiko bool `json:"taiko"` }   // EthashConfig is the consensus engine configs for proof-of-work based sealing. @@ -329,13 +367,16 @@ // Description returns a human-readable description of ChainConfig. func (c *ChainConfig) Description() string { var banner string   - // Create some basinc network config output + // Create some basic network config output network := NetworkNames[c.ChainID.String()] if network == "" { network = "unknown" } banner += fmt.Sprintf("Chain ID: %v (%s)\n", c.ChainID, network) switch { + // CHANGE(taiko): print Taiko consensus engine in banner. + case c.Taiko: + banner += "Consensus: Taiko\n" case c.Ethash != nil: if c.TerminalTotalDifficulty == nil { banner += "Consensus: Ethash (proof-of-work)\n"
diff --git ethereum/go-ethereum/params/protocol_params.go taikoxyz/taiko-geth/params/protocol_params.go index a407ed1473296e7fdfc9ba9d622c2586a1a11321..8a5c01184941f9260fbbf561a4495667990cb8ce 100644 --- ethereum/go-ethereum/params/protocol_params.go +++ taikoxyz/taiko-geth/params/protocol_params.go @@ -16,7 +16,11 @@ // along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.   package params   -import "math/big" +import ( + "math/big" + + "github.com/ethereum/go-ethereum/common" +)   const ( GasLimitBoundDivisor uint64 = 1024 // The bound divisor of the gas limit, used in update calculations. @@ -163,12 +167,13 @@ BlobTxBytesPerFieldElement = 32 // Size in bytes of a field element BlobTxFieldElementsPerBlob = 4096 // Number of field elements stored in a single data blob BlobTxHashVersion = 0x01 // Version byte of the commitment hash - BlobTxMaxBlobGasPerBlock = 1 << 19 // Maximum consumable blob gas for data blobs per block - BlobTxTargetBlobGasPerBlock = 1 << 18 // Target consumable blob gas for data blobs per block (for 1559-like pricing) BlobTxBlobGasPerBlob = 1 << 17 // Gas consumption of a single data blob (== blob byte size) BlobTxMinBlobGasprice = 1 // Minimum gas price for data blobs - BlobTxBlobGaspriceUpdateFraction = 2225652 // Controls the maximum rate of change for blob gas price + BlobTxBlobGaspriceUpdateFraction = 3338477 // Controls the maximum rate of change for blob gas price BlobTxPointEvaluationPrecompileGas = 50000 // Gas price for the point evaluation precompile. + + BlobTxTargetBlobGasPerBlock = 3 * BlobTxBlobGasPerBlob // Target consumable blob gas for data blobs per block (for 1559-like pricing) + MaxBlobGasPerBlock = 6 * BlobTxBlobGasPerBlob // Maximum consumable blob gas for data blobs per block )   // Gas discount table for BLS12-381 G1 and G2 multi exponentiation operations @@ -179,4 +184,9 @@ DifficultyBoundDivisor = big.NewInt(2048) // The bound divisor of the difficulty, used in the update calculations. GenesisDifficulty = big.NewInt(131072) // Difficulty of the Genesis block. MinimumDifficulty = big.NewInt(131072) // The minimum that the difficulty may ever be. DurationLimit = big.NewInt(13) // The decision boundary on the blocktime duration used to determine whether difficulty should go up or not. + + // BeaconRootsStorageAddress is the address where historical beacon roots are stored as per EIP-4788 + BeaconRootsStorageAddress = common.HexToAddress("0x000F3df6D732807Ef1319fB7B8bB8522d0Beac02") + // SystemAddress is where the system-transaction is sent from as per EIP-4788 + SystemAddress common.Address = common.HexToAddress("0xfffffffffffffffffffffffffffffffffffffffe") )
diff --git ethereum/go-ethereum/accounts/abi/abi.go taikoxyz/taiko-geth/accounts/abi/abi.go index 55576070a4ae1028db82f2d64a5f8ae3d8fafb2c..6e1075c715fddd2e727ca0f20c6f4adb46fd4b6c 100644 --- ethereum/go-ethereum/accounts/abi/abi.go +++ taikoxyz/taiko-geth/accounts/abi/abi.go @@ -22,6 +22,7 @@ "encoding/json" "errors" "fmt" "io" + "math/big"   "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/crypto" @@ -246,24 +247,65 @@ // revertSelector is a special function selector for revert reason unpacking. var revertSelector = crypto.Keccak256([]byte("Error(string)"))[:4]   +// panicSelector is a special function selector for panic reason unpacking. +var panicSelector = crypto.Keccak256([]byte("Panic(uint256)"))[:4] + +// panicReasons map is for readable panic codes +// see this linkage for the deails +// https://docs.soliditylang.org/en/v0.8.21/control-structures.html#panic-via-assert-and-error-via-require +// the reason string list is copied from ether.js +// https://github.com/ethers-io/ethers.js/blob/fa3a883ff7c88611ce766f58bdd4b8ac90814470/src.ts/abi/interface.ts#L207-L218 +var panicReasons = map[uint64]string{ + 0x00: "generic panic", + 0x01: "assert(false)", + 0x11: "arithmetic underflow or overflow", + 0x12: "division or modulo by zero", + 0x21: "enum overflow", + 0x22: "invalid encoded storage byte array accessed", + 0x31: "out-of-bounds array access; popping on an empty array", + 0x32: "out-of-bounds access of an array or bytesN", + 0x41: "out of memory", + 0x51: "uninitialized function", +} + // UnpackRevert resolves the abi-encoded revert reason. According to the solidity // spec https://solidity.readthedocs.io/en/latest/control-structures.html#revert, -// the provided revert reason is abi-encoded as if it were a call to a function -// `Error(string)`. So it's a special tool for it. +// the provided revert reason is abi-encoded as if it were a call to function +// `Error(string)` or `Panic(uint256)`. So it's a special tool for it. func UnpackRevert(data []byte) (string, error) { if len(data) < 4 { return "", errors.New("invalid data for unpacking") } - if !bytes.Equal(data[:4], revertSelector) { + switch { + case bytes.Equal(data[:4], revertSelector): + typ, err := NewType("string", "", nil) + if err != nil { + return "", err + } + unpacked, err := (Arguments{{Type: typ}}).Unpack(data[4:]) + if err != nil { + return "", err + } + return unpacked[0].(string), nil + case bytes.Equal(data[:4], panicSelector): + typ, err := NewType("uint256", "", nil) + if err != nil { + return "", err + } + unpacked, err := (Arguments{{Type: typ}}).Unpack(data[4:]) + if err != nil { + return "", err + } + pCode := unpacked[0].(*big.Int) + // uint64 safety check for future + // but the code is not bigger than MAX(uint64) now + if pCode.IsUint64() { + if reason, ok := panicReasons[pCode.Uint64()]; ok { + return reason, nil + } + } + return fmt.Sprintf("unknown panic code: %#x", pCode), nil + default: return "", errors.New("invalid data for unpacking") } - typ, err := NewType("string", "", nil) - if err != nil { - return "", err - } - unpacked, err := (Arguments{{Type: typ}}).Unpack(data[4:]) - if err != nil { - return "", err - } - return unpacked[0].(string), nil }
diff --git ethereum/go-ethereum/accounts/abi/abi_test.go taikoxyz/taiko-geth/accounts/abi/abi_test.go index 3486ffd1a517b9772a1dba0f4e6a3689695f89dd..84175df4bb93e7d4ab532df545fbd02ddfd983fc 100644 --- ethereum/go-ethereum/accounts/abi/abi_test.go +++ taikoxyz/taiko-geth/accounts/abi/abi_test.go @@ -1173,6 +1173,8 @@ }{ {"", "", errors.New("invalid data for unpacking")}, {"08c379a1", "", errors.New("invalid data for unpacking")}, {"08c379a00000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000d72657665727420726561736f6e00000000000000000000000000000000000000", "revert reason", nil}, + {"4e487b710000000000000000000000000000000000000000000000000000000000000000", "generic panic", nil}, + {"4e487b7100000000000000000000000000000000000000000000000000000000000000ff", "unknown panic code: 0xff", nil}, } for index, c := range cases { t.Run(fmt.Sprintf("case %d", index), func(t *testing.T) {
diff --git ethereum/go-ethereum/accounts/abi/bind/backends/simulated.go taikoxyz/taiko-geth/accounts/abi/bind/backends/simulated.go index 83b91f7f8d59351f1056f3f35af6439ef71d9046..8549976480bc2096c29c42a347f0cfcbcd519093 100644 --- ethereum/go-ethereum/accounts/abi/bind/backends/simulated.go +++ taikoxyz/taiko-geth/accounts/abi/bind/backends/simulated.go @@ -199,7 +199,6 @@ stateDB, err := b.stateByBlockNumber(ctx, blockNumber) if err != nil { return nil, err } - return stateDB.GetCode(contract), nil }   @@ -212,7 +211,6 @@ stateDB, err := b.stateByBlockNumber(ctx, blockNumber) if err != nil { return nil, err } - return stateDB.GetBalance(contract), nil }   @@ -225,7 +223,6 @@ stateDB, err := b.stateByBlockNumber(ctx, blockNumber) if err != nil { return 0, err } - return stateDB.GetNonce(contract), nil }   @@ -238,7 +235,6 @@ stateDB, err := b.stateByBlockNumber(ctx, blockNumber) if err != nil { return nil, err } - val := stateDB.GetState(contract, key) return val[:], nil } @@ -610,8 +606,7 @@ // Gas prices post 1559 need to be initialized if call.GasPrice != nil && (call.GasFeeCap != nil || call.GasTipCap != nil) { return nil, errors.New("both gasPrice and (maxFeePerGas or maxPriorityFeePerGas) specified") } - head := b.blockchain.CurrentHeader() - if !b.blockchain.Config().IsLondon(head.Number) { + if !b.blockchain.Config().IsLondon(header.Number) { // If there's no basefee, then it must be a non-1559 execution if call.GasPrice == nil { call.GasPrice = new(big.Int) @@ -633,13 +628,13 @@ } // Backfill the legacy gasPrice for EVM execution, unless we're all zeroes call.GasPrice = new(big.Int) if call.GasFeeCap.BitLen() > 0 || call.GasTipCap.BitLen() > 0 { - call.GasPrice = math.BigMin(new(big.Int).Add(call.GasTipCap, head.BaseFee), call.GasFeeCap) + call.GasPrice = math.BigMin(new(big.Int).Add(call.GasTipCap, header.BaseFee), call.GasFeeCap) } } } // Ensure message is initialized properly. if call.Gas == 0 { - call.Gas = 50000000 + call.Gas = 10 * header.GasLimit } if call.Value == nil { call.Value = new(big.Int) @@ -700,8 +695,10 @@ block.AddTxWithChain(b.blockchain, tx) } block.AddTxWithChain(b.blockchain, tx) }) - stateDB, _ := b.blockchain.State() - + stateDB, err := b.blockchain.State() + if err != nil { + return err + } b.pendingBlock = blocks[0] b.pendingState, _ = state.New(b.pendingBlock.Root(), stateDB.Database(), nil) b.pendingReceipts = receipts[0] @@ -821,11 +818,12 @@ blocks, _ := core.GenerateChain(b.config, block, ethash.NewFaker(), b.database, 1, func(number int, block *core.BlockGen) { block.OffsetTime(int64(adjustment.Seconds())) }) - stateDB, _ := b.blockchain.State() - + stateDB, err := b.blockchain.State() + if err != nil { + return err + } b.pendingBlock = blocks[0] b.pendingState, _ = state.New(b.pendingBlock.Root(), stateDB.Database(), nil) - return nil }   @@ -892,7 +890,7 @@ return rawdb.ReadReceipts(fb.db, hash, *number, header.Time, fb.bc.Config()), nil }   func (fb *filterBackend) GetLogs(ctx context.Context, hash common.Hash, number uint64) ([][]*types.Log, error) { - logs := rawdb.ReadLogs(fb.db, hash, number, fb.bc.Config()) + logs := rawdb.ReadLogs(fb.db, hash, number) return logs, nil }
diff --git ethereum/go-ethereum/accounts/abi/method.go taikoxyz/taiko-geth/accounts/abi/method.go index f69e3ee9b562dd33959a03871bf6eae0e183fccc..b6e1eef3cf3f1730186b78f07ea5505e5da8792a 100644 --- ethereum/go-ethereum/accounts/abi/method.go +++ taikoxyz/taiko-geth/accounts/abi/method.go @@ -127,11 +127,12 @@ if state != "" { state = state + " " } identity := fmt.Sprintf("function %v", rawName) - if funType == Fallback { + switch funType { + case Fallback: identity = "fallback" - } else if funType == Receive { + case Receive: identity = "receive" - } else if funType == Constructor { + case Constructor: identity = "constructor" } str := fmt.Sprintf("%v(%v) %sreturns(%v)", identity, strings.Join(inputNames, ", "), state, strings.Join(outputNames, ", "))
diff --git ethereum/go-ethereum/accounts/abi/method_test.go taikoxyz/taiko-geth/accounts/abi/method_test.go index 395a5289654aee77c826e2200ca7cc1cb1a74a48..9230e307aa41b09ad4cad9f7c116adc2cf5ee26b 100644 --- ethereum/go-ethereum/accounts/abi/method_test.go +++ taikoxyz/taiko-geth/accounts/abi/method_test.go @@ -84,11 +84,12 @@ }   for _, test := range table { var got string - if test.method == "fallback" { + switch test.method { + case "fallback": got = abi.Fallback.String() - } else if test.method == "receive" { + case "receive": got = abi.Receive.String() - } else { + default: got = abi.Methods[test.method].String() } if got != test.expectation {
diff --git ethereum/go-ethereum/accounts/abi/unpack.go taikoxyz/taiko-geth/accounts/abi/unpack.go index 68451483cdaa234f0b39a8a3e182fd1b6c594962..905b5ce629db5684495aa87da39c9cfdee6bc69c 100644 --- ethereum/go-ethereum/accounts/abi/unpack.go +++ taikoxyz/taiko-geth/accounts/abi/unpack.go @@ -160,13 +160,14 @@ // this value will become our slice or our array, depending on the type var refSlice reflect.Value   - if t.T == SliceTy { + switch t.T { + case SliceTy: // declare our slice refSlice = reflect.MakeSlice(t.GetType(), size, size) - } else if t.T == ArrayTy { + case ArrayTy: // declare our array refSlice = reflect.New(t.GetType()).Elem() - } else { + default: return nil, errors.New("abi: invalid type in array/slice unpacking stage") }
diff --git ethereum/go-ethereum/accounts/keystore/watch.go taikoxyz/taiko-geth/accounts/keystore/watch.go index 3f64b89c585e57135b71d1f4cfaddb79124b8ad2..a9f87e7c323e11ed47b603776f737d756400aae2 100644 --- ethereum/go-ethereum/accounts/keystore/watch.go +++ taikoxyz/taiko-geth/accounts/keystore/watch.go @@ -20,6 +20,7 @@ package keystore   import ( + "os" "time"   "github.com/ethereum/go-ethereum/log" @@ -77,7 +78,9 @@ return } defer watcher.Close() if err := watcher.Add(w.ac.keydir); err != nil { - logger.Warn("Failed to watch keystore folder", "err", err) + if !os.IsNotExist(err) { + logger.Warn("Failed to watch keystore folder", "err", err) + } return }
diff --git ethereum/go-ethereum/accounts/scwallet/README.md taikoxyz/taiko-geth/accounts/scwallet/README.md index 4313d9c6b2f8ecacf53657409572f53e482bbbe4..28079c47435cffb174136638572c225c19a8d840 100644 --- ethereum/go-ethereum/accounts/scwallet/README.md +++ taikoxyz/taiko-geth/accounts/scwallet/README.md @@ -8,7 +8,7 @@ * PCSCD version 4.3 running on your system **Only version 4.3 is currently supported**   ## Preparing the smartcard   - **WARNING: FOILLOWING THESE INSTRUCTIONS WILL DESTROY THE MASTER KEY ON YOUR CARD. ONLY PROCEED IF NO FUNDS ARE ASSOCIATED WITH THESE ACCOUNTS** + **WARNING: FOLLOWING THESE INSTRUCTIONS WILL DESTROY THE MASTER KEY ON YOUR CARD. ONLY PROCEED IF NO FUNDS ARE ASSOCIATED WITH THESE ACCOUNTS**   You can use status' [keycard-cli](https://github.com/status-im/keycard-cli) and you should get _at least_ version 2.1.1 of their [smartcard application](https://github.com/status-im/status-keycard/releases/download/2.2.1/keycard_v2.2.1.cap)
diff --git ethereum/go-ethereum/build/checksums.txt taikoxyz/taiko-geth/build/checksums.txt index 6e33f456d142c22d436df62c20ad83ed9c31c16b..c752fb8ccd64593d5dfbb66d4a4ee912d281f6bb 100644 --- ethereum/go-ethereum/build/checksums.txt +++ taikoxyz/taiko-geth/build/checksums.txt @@ -1,20 +1,30 @@ # This file contains sha256 checksums of optional build dependencies.   -2c5ee9c9ec1e733b0dbbc2bdfed3f62306e51d8172bf38f4f4e542b27520f597 go1.20.7.src.tar.gz -785170eab380a8985d53896808b0a71336d0ea60e0a26099b4ccec77798b1cf4 go1.20.7.darwin-amd64.tar.gz -eea1e7e4c2f75c72629050e6a6c7c46c446d64056732a7787fb3ba16ace1982e go1.20.7.darwin-arm64.tar.gz -d8cff0357ac24eb06f3f280535397eeaacf95611d29f9b2abc3060f3d6dce3b4 go1.20.7.freebsd-386.tar.gz -26918dcebf474a9e81ccf9f648cdf36968dfb76b481518cf615d78455dda4416 go1.20.7.freebsd-amd64.tar.gz -ddb48145f05bda2f4617a22c979d4e94b22802cdb1a1fde1b1974e733b26f091 go1.20.7.linux-386.tar.gz -f0a87f1bcae91c4b69f8dc2bc6d7e6bfcd7524fceec130af525058c0c17b1b44 go1.20.7.linux-amd64.tar.gz -44781ae3b153c3b07651d93b6bc554e835a36e2d72a696281c1e4dad9efffe43 go1.20.7.linux-arm64.tar.gz -7cc231b415b94f2f7065870a73f67dd2b0ec12b5a98052b7ee0121c42bc04f8d go1.20.7.linux-armv6l.tar.gz -6318a1db307c12b8afe68808bd6fae4fba1e558a85b958216096869ed506dcb3 go1.20.7.linux-ppc64le.tar.gz -26aea2ede8722ceecbd9db883328a8d963136fd96c11dacc356c44c4c19c6515 go1.20.7.linux-s390x.tar.gz -5b0ef6f58d3e04d6cc003aa98e9172f41ba9e091b1c98e7339b41c4c87fb78a1 go1.20.7.windows-386.zip -736dc6c7fcab1c96b682c8c93e38d7e371e62a17d34cb2c37d451a1147f66af9 go1.20.7.windows-amd64.zip -fc6f79c1e1ed9e506c65f2112ac4e387479916f1accb0d046a6a19ff6938baa5 go1.20.7.windows-arm64.zip +# version:spec-tests 1.0.5 +# https://github.com/ethereum/execution-spec-tests/releases +# https://github.com/ethereum/execution-spec-tests/releases/download/v1.0.5/ +d4fd06a0e5f94beb970f3c68374b38ef9de82d4be77517d326bcf739c3cbf3a2 fixtures_develop.tar.gz   +# version:golang 1.21.3 +# https://go.dev/dl/ +186f2b6f8c8b704e696821b09ab2041a5c1ee13dcbc3156a13adcf75931ee488 go1.21.3.src.tar.gz +27014fc69e301d7588a169ca239b3cc609f0aa1abf38528bf0d20d3b259211eb go1.21.3.darwin-amd64.tar.gz +65302a7a9f7a4834932b3a7a14cb8be51beddda757b567a2f9e0cbd0d7b5a6ab go1.21.3.darwin-arm64.tar.gz +8e0cd2f66cf1bde9d07b4aee01e3d7c3cfdd14e20650488e1683da4b8492594a go1.21.3.freebsd-386.tar.gz +6e74f65f586e93d1f3947894766f69e9b2ebda488592a09df61f36f06bfe58a8 go1.21.3.freebsd-amd64.tar.gz +fb209fd070db500a84291c5a95251cceeb1723e8f6142de9baca5af70a927c0e go1.21.3.linux-386.tar.gz +1241381b2843fae5a9707eec1f8fb2ef94d827990582c7c7c32f5bdfbfd420c8 go1.21.3.linux-amd64.tar.gz +fc90fa48ae97ba6368eecb914343590bbb61b388089510d0c56c2dde52987ef3 go1.21.3.linux-arm64.tar.gz +a1ddcaaf0821a12a800884c14cb4268ce1c1f5a0301e9060646f1e15e611c6c7 go1.21.3.linux-armv6l.tar.gz +3b0e10a3704f164a6e85e0377728ec5fd21524fabe4c925610e34076586d5826 go1.21.3.linux-ppc64le.tar.gz +4c78e2e6f4c684a3d5a9bdc97202729053f44eb7be188206f0627ef3e18716b6 go1.21.3.linux-s390x.tar.gz +e36737f4f2fadb4d2f919ec4ce517133a56e06064cca6e82fc883bb000c4d56c go1.21.3.windows-386.zip +27c8daf157493f288d42a6f38debc6a2cb391f6543139eba9152fceca0be2a10 go1.21.3.windows-amd64.zip +bfb7a5c56f9ded07d8ae0e0b3702ac07b65e68fa8f33da24ed6df4ce01fe2c5c go1.21.3.windows-arm64.zip + +# version:golangci 1.51.1 +# https://github.com/golangci/golangci-lint/releases/ +# https://github.com/golangci/golangci-lint/releases/download/v1.51.1/ fba08acc4027f69f07cef48fbff70b8a7ecdfaa1c2aba9ad3fb31d60d9f5d4bc golangci-lint-1.51.1-darwin-amd64.tar.gz 75b8f0ff3a4e68147156be4161a49d4576f1be37a0b506473f8c482140c1e7f2 golangci-lint-1.51.1-darwin-arm64.tar.gz e06b3459aaed356e1667580be00b05f41f3b2e29685d12cdee571c23e1edb414 golangci-lint-1.51.1-freebsd-386.tar.gz @@ -43,4 +53,12 @@ bce02f7232723cb727755ee11f168a700a00896a25d37f87c4b173bce55596b4 golangci-lint-1.51.1-windows-armv6.zip cf6403f84707ce8c98664736772271bc8874f2e760c2fd0f00cf3e85963507e9 golangci-lint-1.51.1-windows-armv7.zip   # This is the builder on PPA that will build Go itself (inception-y), don't modify! +# +# This version is fine to be old and full of security holes, we just use it +# to build the latest Go. Don't change it. If it ever becomes insufficient, +# we need to switch over to a recursive builder to jump across supported +# versions. +# +# version:ppa-builder 1.19.6 +# https://go.dev/dl/ d7f0013f82e6d7f862cc6cb5c8cdb48eef5f2e239b35baa97e2f1a7466043767 go1.19.6.src.tar.gz
diff --git ethereum/go-ethereum/build/ci.go taikoxyz/taiko-geth/build/ci.go index 242f4d841e5fa57787b7af545e1b8eac14e17704..1ff3fb5bf8261ed961dba7ff2a90c02e28c7c468 100644 --- ethereum/go-ethereum/build/ci.go +++ taikoxyz/taiko-geth/build/ci.go @@ -120,15 +120,15 @@ // Distros for which packages are created. // Note: vivid is unsupported because there is no golang-1.6 package for it. // Note: the following Ubuntu releases have been officially deprecated on Launchpad: - // wily, yakkety, zesty, artful, cosmic, disco, eoan, groovy, hirsuite, impish + // wily, yakkety, zesty, artful, cosmic, disco, eoan, groovy, hirsuite, impish, + // kinetic debDistroGoBoots = map[string]string{ - "trusty": "golang-1.11", // EOL: 04/2024 - "xenial": "golang-go", // EOL: 04/2026 - "bionic": "golang-go", // EOL: 04/2028 - "focal": "golang-go", // EOL: 04/2030 - "jammy": "golang-go", // EOL: 04/2032 - "kinetic": "golang-go", // EOL: 07/2023 - "lunar": "golang-go", // EOL: 01/2024 + "trusty": "golang-1.11", // EOL: 04/2024 + "xenial": "golang-go", // EOL: 04/2026 + "bionic": "golang-go", // EOL: 04/2028 + "focal": "golang-go", // EOL: 04/2030 + "jammy": "golang-go", // EOL: 04/2032 + "lunar": "golang-go", // EOL: 01/2024 }   debGoBootPaths = map[string]string{ @@ -136,18 +136,8 @@ "golang-1.11": "/usr/lib/go-1.11", "golang-go": "/usr/lib/go", }   - // This is the version of Go that will be downloaded by - // - // go run ci.go install -dlgo - dlgoVersion = "1.20.7" - - // This is the version of Go that will be used to bootstrap the PPA builder. - // - // This version is fine to be old and full of security holes, we just use it - // to build the latest Go. Don't change it. If it ever becomes insufficient, - // we need to switch over to a recursive builder to jumpt across supported - // versions. - gobootVersion = "1.19.6" + // This is where the tests should be unpacked. + executionSpecTestsDir = "tests/spec-tests" )   var GOBIN, _ = filepath.Abs(filepath.Join("build", "bin")) @@ -185,6 +175,8 @@ case "nsis": doWindowsInstaller(os.Args[2:]) case "purge": doPurge(os.Args[2:]) + case "sanitycheck": + doSanityCheck() default: log.Fatal("unknown command ", os.Args[1]) } @@ -206,9 +198,8 @@ // Configure the toolchain. tc := build.GoToolchain{GOARCH: *arch, CC: *cc} if *dlgo { csdb := build.MustLoadChecksums("build/checksums.txt") - tc.Root = build.DownloadGo(csdb, dlgoVersion) + tc.Root = build.DownloadGo(csdb) } - // Disable CLI markdown doc generation in release builds. buildTags := []string{"urfave_cli_no_docs"}   @@ -294,14 +285,18 @@ cc = flag.String("cc", "", "Sets C compiler binary") coverage = flag.Bool("coverage", false, "Whether to record code coverage") verbose = flag.Bool("v", false, "Whether to log verbosely") race = flag.Bool("race", false, "Execute the race detector") + cachedir = flag.String("cachedir", "./build/cache", "directory for caching downloads") ) flag.CommandLine.Parse(cmdline) + + // Get test fixtures. + csdb := build.MustLoadChecksums("build/checksums.txt") + downloadSpecTestFixtures(csdb, *cachedir)   // Configure the toolchain. tc := build.GoToolchain{GOARCH: *arch, CC: *cc} if *dlgo { - csdb := build.MustLoadChecksums("build/checksums.txt") - tc.Root = build.DownloadGo(csdb, dlgoVersion) + tc.Root = build.DownloadGo(csdb) } gotest := tc.Go("test")   @@ -332,6 +327,25 @@ gotest.Args = append(gotest.Args, packages...) build.MustRun(gotest) }   +// downloadSpecTestFixtures downloads and extracts the execution-spec-tests fixtures. +func downloadSpecTestFixtures(csdb *build.ChecksumDB, cachedir string) string { + executionSpecTestsVersion, err := build.Version(csdb, "spec-tests") + if err != nil { + log.Fatal(err) + } + ext := ".tar.gz" + base := "fixtures_develop" // TODO(MariusVanDerWijden) rename once the version becomes part of the filename + url := fmt.Sprintf("https://github.com/ethereum/execution-spec-tests/releases/download/v%s/%s%s", executionSpecTestsVersion, base, ext) + archivePath := filepath.Join(cachedir, base+ext) + if err := csdb.DownloadFile(url, archivePath); err != nil { + log.Fatal(err) + } + if err := build.ExtractArchive(archivePath, executionSpecTestsDir); err != nil { + log.Fatal(err) + } + return filepath.Join(cachedir, base) +} + // doLint runs golangci-lint on requested packages. func doLint(cmdline []string) { var ( @@ -351,9 +365,11 @@ }   // downloadLinter downloads and unpacks golangci-lint. func downloadLinter(cachedir string) string { - const version = "1.51.1" - csdb := build.MustLoadChecksums("build/checksums.txt") + version, err := build.Version(csdb, "golangci") + if err != nil { + log.Fatal(err) + } arch := runtime.GOARCH ext := ".tar.gz"   @@ -735,6 +751,10 @@ // downloadGoBootstrapSources downloads the Go source tarball that will be used // to bootstrap the builder Go. func downloadGoBootstrapSources(cachedir string) string { csdb := build.MustLoadChecksums("build/checksums.txt") + gobootVersion, err := build.Version(csdb, "ppa-builder") + if err != nil { + log.Fatal(err) + } file := fmt.Sprintf("go%s.src.tar.gz", gobootVersion) url := "https://dl.google.com/go/" + file dst := filepath.Join(cachedir, file) @@ -747,6 +767,10 @@ // downloadGoSources downloads the Go source tarball. func downloadGoSources(cachedir string) string { csdb := build.MustLoadChecksums("build/checksums.txt") + dlgoVersion, err := build.Version(csdb, "golang") + if err != nil { + log.Fatal(err) + } file := fmt.Sprintf("go%s.src.tar.gz", dlgoVersion) url := "https://dl.google.com/go/" + file dst := filepath.Join(cachedir, file) @@ -1073,3 +1097,7 @@ if err := build.AzureBlobstoreDelete(auth, blobs); err != nil { log.Fatal(err) } } + +func doSanityCheck() { + build.DownloadAndVerifyChecksums(build.MustLoadChecksums("build/checksums.txt")) +}
diff --git ethereum/go-ethereum/cmd/devp2p/internal/ethtest/chain.go taikoxyz/taiko-geth/cmd/devp2p/internal/ethtest/chain.go index 5e3d9fe98daf50e0abdb1d34ffcdb08987813325..938159ec524d613a8e7f3ce4250bfe80246a2b5b 100644 --- ethereum/go-ethereum/cmd/devp2p/internal/ethtest/chain.go +++ taikoxyz/taiko-geth/cmd/devp2p/internal/ethtest/chain.go @@ -77,7 +77,7 @@ }   // ForkID gets the fork id of the chain. func (c *Chain) ForkID() forkid.ID { - return forkid.NewID(c.chainConfig, c.blocks[0].Hash(), uint64(c.Len()), c.blocks[0].Time()) + return forkid.NewID(c.chainConfig, c.blocks[0], uint64(c.Len()), c.blocks[0].Time()) }   // Shorten returns a copy chain of a desired height from the imported
diff --git ethereum/go-ethereum/cmd/devp2p/internal/ethtest/chain_test.go taikoxyz/taiko-geth/cmd/devp2p/internal/ethtest/chain_test.go index 67221923a684441973f2926301e570871136f542..de6acfdcda676c4b1d16b87d889cdfac3665b024 100644 --- ethereum/go-ethereum/cmd/devp2p/internal/ethtest/chain_test.go +++ taikoxyz/taiko-geth/cmd/devp2p/internal/ethtest/chain_test.go @@ -145,7 +145,7 @@ expected []*types.Header }{ { req: GetBlockHeaders{ - GetBlockHeadersPacket: &eth.GetBlockHeadersPacket{ + GetBlockHeadersRequest: &eth.GetBlockHeadersRequest{ Origin: eth.HashOrNumber{Number: uint64(2)}, Amount: uint64(5), Skip: 1, @@ -162,7 +162,7 @@ }, }, { req: GetBlockHeaders{ - GetBlockHeadersPacket: &eth.GetBlockHeadersPacket{ + GetBlockHeadersRequest: &eth.GetBlockHeadersRequest{ Origin: eth.HashOrNumber{Number: uint64(chain.Len() - 1)}, Amount: uint64(3), Skip: 0, @@ -177,7 +177,7 @@ }, }, { req: GetBlockHeaders{ - GetBlockHeadersPacket: &eth.GetBlockHeadersPacket{ + GetBlockHeadersRequest: &eth.GetBlockHeadersRequest{ Origin: eth.HashOrNumber{Hash: chain.Head().Hash()}, Amount: uint64(1), Skip: 0,
diff --git ethereum/go-ethereum/cmd/devp2p/internal/ethtest/helpers.go taikoxyz/taiko-geth/cmd/devp2p/internal/ethtest/helpers.go index bc901bdeb01392410dc99c824023f4be80318279..a0339b88cbe4ebcc161fc94b8e2bb889e2e80f19 100644 --- ethereum/go-ethereum/cmd/devp2p/internal/ethtest/helpers.go +++ taikoxyz/taiko-geth/cmd/devp2p/internal/ethtest/helpers.go @@ -62,7 +62,6 @@ return nil, err } // set default p2p capabilities conn.caps = []p2p.Cap{ - {Name: "eth", Version: 66}, {Name: "eth", Version: 67}, {Name: "eth", Version: 68}, } @@ -237,8 +236,8 @@ if err != nil { return errorf("could not get headers for inbound header request: %v", err) } resp := &BlockHeaders{ - RequestId: msg.ReqID(), - BlockHeadersPacket: eth.BlockHeadersPacket(headers), + RequestId: msg.ReqID(), + BlockHeadersRequest: eth.BlockHeadersRequest(headers), } if err := c.Write(resp); err != nil { return errorf("could not write to connection: %v", err) @@ -267,7 +266,7 @@ resp, ok := msg.(*BlockHeaders) if !ok { return nil, fmt.Errorf("unexpected message received: %s", pretty.Sdump(msg)) } - headers := []*types.Header(resp.BlockHeadersPacket) + headers := []*types.Header(resp.BlockHeadersRequest) return headers, nil }   @@ -379,7 +378,7 @@ defer conn.SetReadDeadline(time.Time{}) conn.SetReadDeadline(time.Now().Add(20 * time.Second)) // create request req := &GetBlockHeaders{ - GetBlockHeadersPacket: &eth.GetBlockHeadersPacket{ + GetBlockHeadersRequest: &eth.GetBlockHeadersRequest{ Origin: eth.HashOrNumber{Hash: block.Hash()}, Amount: 1, }, @@ -604,8 +603,8 @@ pretty.Sdump(announcement), pretty.Sdump(blockHeaderReq)) } err = sendConn.Write(&BlockHeaders{ - RequestId: blockHeaderReq.ReqID(), - BlockHeadersPacket: eth.BlockHeadersPacket{nextBlock.Header()}, + RequestId: blockHeaderReq.ReqID(), + BlockHeadersRequest: eth.BlockHeadersRequest{nextBlock.Header()}, }) if err != nil { return fmt.Errorf("failed to write to connection: %v", err)
diff --git ethereum/go-ethereum/cmd/devp2p/internal/ethtest/snap.go taikoxyz/taiko-geth/cmd/devp2p/internal/ethtest/snap.go index f947e4bc9bae791bc1a0058fcadf7fae094632b8..54eb63f3deb2f1dcb16f5b70582473c832852e8e 100644 --- ethereum/go-ethereum/cmd/devp2p/internal/ethtest/snap.go +++ taikoxyz/taiko-geth/cmd/devp2p/internal/ethtest/snap.go @@ -27,8 +27,8 @@ "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/crypto" "github.com/ethereum/go-ethereum/eth/protocols/snap" "github.com/ethereum/go-ethereum/internal/utesting" - "github.com/ethereum/go-ethereum/light" "github.com/ethereum/go-ethereum/trie" + "github.com/ethereum/go-ethereum/trie/trienode" "golang.org/x/crypto/sha3" )   @@ -58,7 +58,7 @@ // TestSnapGetAccountRange various forms of GetAccountRange requests. func (s *Suite) TestSnapGetAccountRange(t *utesting.T) { var ( root = s.chain.RootAt(999) - ffHash = common.HexToHash("0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff") + ffHash = common.MaxHash zero = common.Hash{} firstKeyMinus1 = common.HexToHash("0x00bf49f440a1cd0527e4d06e2765654c0f56452257516d793a9b8d604dcfdf29") firstKey = common.HexToHash("0x00bf49f440a1cd0527e4d06e2765654c0f56452257516d793a9b8d604dcfdf2a") @@ -125,7 +125,7 @@ // TestSnapGetStorageRanges various forms of GetStorageRanges requests. func (s *Suite) TestSnapGetStorageRanges(t *utesting.T) { var ( - ffHash = common.HexToHash("0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff") + ffHash = common.MaxHash zero = common.Hash{} firstKey = common.HexToHash("0x00bf49f440a1cd0527e4d06e2765654c0f56452257516d793a9b8d604dcfdf2a") secondKey = common.HexToHash("0x09e47cd5056a689e708f22fe1f932709a320518e444f5f7d8d46a3da523d6606") @@ -530,17 +530,13 @@ keys := make([][]byte, len(hashes)) for i, key := range hashes { keys[i] = common.CopyBytes(key[:]) } - nodes := make(light.NodeList, len(proof)) + nodes := make(trienode.ProofList, len(proof)) for i, node := range proof { nodes[i] = node } - proofdb := nodes.NodeSet() + proofdb := nodes.Set()   - var end []byte - if len(keys) > 0 { - end = keys[len(keys)-1] - } - _, err = trie.VerifyRangeProof(tc.root, tc.origin[:], end, keys, accounts, proofdb) + _, err = trie.VerifyRangeProof(tc.root, tc.origin[:], keys, accounts, proofdb) return err }
diff --git ethereum/go-ethereum/cmd/devp2p/internal/ethtest/suite.go taikoxyz/taiko-geth/cmd/devp2p/internal/ethtest/suite.go index 815353be72650c6aa871f80db76536eb60507ad6..0b56c8cf4b6f7be5fd6fec788c85705aefe04c8f 100644 --- ethereum/go-ethereum/cmd/devp2p/internal/ethtest/suite.go +++ taikoxyz/taiko-geth/cmd/devp2p/internal/ethtest/suite.go @@ -112,7 +112,7 @@ t.Fatalf("peering failed: %v", err) } // write request req := &GetBlockHeaders{ - GetBlockHeadersPacket: &eth.GetBlockHeadersPacket{ + GetBlockHeadersRequest: &eth.GetBlockHeadersRequest{ Origin: eth.HashOrNumber{Hash: s.chain.blocks[1].Hash()}, Amount: 2, Skip: 1, @@ -150,7 +150,7 @@ // create two requests req1 := &GetBlockHeaders{ RequestId: uint64(111), - GetBlockHeadersPacket: &eth.GetBlockHeadersPacket{ + GetBlockHeadersRequest: &eth.GetBlockHeadersRequest{ Origin: eth.HashOrNumber{ Hash: s.chain.blocks[1].Hash(), }, @@ -161,7 +161,7 @@ }, } req2 := &GetBlockHeaders{ RequestId: uint64(222), - GetBlockHeadersPacket: &eth.GetBlockHeadersPacket{ + GetBlockHeadersRequest: &eth.GetBlockHeadersRequest{ Origin: eth.HashOrNumber{ Hash: s.chain.blocks[1].Hash(), }, @@ -201,10 +201,10 @@ expected2, err := s.chain.GetHeaders(req2) if err != nil { t.Fatalf("failed to get expected headers for request 2: %v", err) } - if !headersMatch(expected1, headers1.BlockHeadersPacket) { + if !headersMatch(expected1, headers1.BlockHeadersRequest) { t.Fatalf("header mismatch: \nexpected %v \ngot %v", expected1, headers1) } - if !headersMatch(expected2, headers2.BlockHeadersPacket) { + if !headersMatch(expected2, headers2.BlockHeadersRequest) { t.Fatalf("header mismatch: \nexpected %v \ngot %v", expected2, headers2) } } @@ -224,7 +224,7 @@ // create requests reqID := uint64(1234) request1 := &GetBlockHeaders{ RequestId: reqID, - GetBlockHeadersPacket: &eth.GetBlockHeadersPacket{ + GetBlockHeadersRequest: &eth.GetBlockHeadersRequest{ Origin: eth.HashOrNumber{ Number: 1, }, @@ -233,7 +233,7 @@ }, } request2 := &GetBlockHeaders{ RequestId: reqID, - GetBlockHeadersPacket: &eth.GetBlockHeadersPacket{ + GetBlockHeadersRequest: &eth.GetBlockHeadersRequest{ Origin: eth.HashOrNumber{ Number: 33, }, @@ -270,10 +270,10 @@ expected2, err := s.chain.GetHeaders(request2) if err != nil { t.Fatalf("failed to get expected block headers: %v", err) } - if !headersMatch(expected1, headers1.BlockHeadersPacket) { + if !headersMatch(expected1, headers1.BlockHeadersRequest) { t.Fatalf("header mismatch: \nexpected %v \ngot %v", expected1, headers1) } - if !headersMatch(expected2, headers2.BlockHeadersPacket) { + if !headersMatch(expected2, headers2.BlockHeadersRequest) { t.Fatalf("header mismatch: \nexpected %v \ngot %v", expected2, headers2) } } @@ -290,7 +290,7 @@ if err := conn.peer(s.chain, nil); err != nil { t.Fatalf("peering failed: %v", err) } req := &GetBlockHeaders{ - GetBlockHeadersPacket: &eth.GetBlockHeadersPacket{ + GetBlockHeadersRequest: &eth.GetBlockHeadersRequest{ Origin: eth.HashOrNumber{Number: 0}, Amount: 2, }, @@ -322,7 +322,7 @@ } // create block bodies request req := &GetBlockBodies{ RequestId: uint64(55), - GetBlockBodiesPacket: eth.GetBlockBodiesPacket{ + GetBlockBodiesRequest: eth.GetBlockBodiesRequest{ s.chain.blocks[54].Hash(), s.chain.blocks[75].Hash(), }, @@ -336,11 +336,11 @@ resp, ok := msg.(*BlockBodies) if !ok { t.Fatalf("unexpected: %s", pretty.Sdump(msg)) } - bodies := resp.BlockBodiesPacket + bodies := resp.BlockBodiesResponse t.Logf("received %d block bodies", len(bodies)) - if len(bodies) != len(req.GetBlockBodiesPacket) { + if len(bodies) != len(req.GetBlockBodiesRequest) { t.Fatalf("wrong bodies in response: expected %d bodies, "+ - "got %d", len(req.GetBlockBodiesPacket), len(bodies)) + "got %d", len(req.GetBlockBodiesRequest), len(bodies)) } }   @@ -481,8 +481,8 @@ for _, hash := range hashMap { hashes = append(hashes, hash) } getTxReq := &GetPooledTransactions{ - RequestId: 1234, - GetPooledTransactionsPacket: hashes, + RequestId: 1234, + GetPooledTransactionsRequest: hashes, } if err = conn.Write(getTxReq); err != nil { t.Fatalf("could not write to conn: %v", err) @@ -490,7 +490,7 @@ } // check that all received transactions match those that were sent to node switch msg := conn.waitForResponse(s.chain, timeout, getTxReq.RequestId).(type) { case *PooledTransactions: - for _, gotTx := range msg.PooledTransactionsPacket { + for _, gotTx := range msg.PooledTransactionsResponse { if _, exists := hashMap[gotTx.Hash()]; !exists { t.Fatalf("unexpected tx received: %v", gotTx.Hash()) } @@ -547,8 +547,8 @@ for { msg := conn.readAndServe(s.chain, timeout) switch msg := msg.(type) { case *GetPooledTransactions: - if len(msg.GetPooledTransactionsPacket) != len(hashes) { - t.Fatalf("unexpected number of txs requested: wanted %d, got %d", len(hashes), len(msg.GetPooledTransactionsPacket)) + if len(msg.GetPooledTransactionsRequest) != len(hashes) { + t.Fatalf("unexpected number of txs requested: wanted %d, got %d", len(hashes), len(msg.GetPooledTransactionsRequest)) } return
diff --git ethereum/go-ethereum/cmd/devp2p/internal/ethtest/suite_test.go taikoxyz/taiko-geth/cmd/devp2p/internal/ethtest/suite_test.go index c5bcc3db1da494d03dc8ad458aa6afa88847fae4..7890c3134811accd6a78ec1554638e8a97e74780 100644 --- ethereum/go-ethereum/cmd/devp2p/internal/ethtest/suite_test.go +++ taikoxyz/taiko-geth/cmd/devp2p/internal/ethtest/suite_test.go @@ -120,6 +120,7 @@ }) if err != nil { return err } + backend.SetSynced()   _, err = backend.BlockChain().InsertChain(chain.blocks[1:]) return err
diff --git ethereum/go-ethereum/cmd/devp2p/internal/ethtest/types.go taikoxyz/taiko-geth/cmd/devp2p/internal/ethtest/types.go index afa9a9c8c68586bfc23685fa7b67bfc42b0578f6..805d7a81b99af47e7fdc8d2ad09c688fdac953da 100644 --- ethereum/go-ethereum/cmd/devp2p/internal/ethtest/types.go +++ taikoxyz/taiko-geth/cmd/devp2p/internal/ethtest/types.go @@ -99,24 +99,24 @@ func (msg Transactions) Code() int { return 18 } func (msg Transactions) ReqID() uint64 { return 18 }   // GetBlockHeaders represents a block header query. -type GetBlockHeaders eth.GetBlockHeadersPacket66 +type GetBlockHeaders eth.GetBlockHeadersPacket   func (msg GetBlockHeaders) Code() int { return 19 } func (msg GetBlockHeaders) ReqID() uint64 { return msg.RequestId }   -type BlockHeaders eth.BlockHeadersPacket66 +type BlockHeaders eth.BlockHeadersPacket   func (msg BlockHeaders) Code() int { return 20 } func (msg BlockHeaders) ReqID() uint64 { return msg.RequestId }   // GetBlockBodies represents a GetBlockBodies request -type GetBlockBodies eth.GetBlockBodiesPacket66 +type GetBlockBodies eth.GetBlockBodiesPacket   func (msg GetBlockBodies) Code() int { return 21 } func (msg GetBlockBodies) ReqID() uint64 { return msg.RequestId }   // BlockBodies is the network packet for block content distribution. -type BlockBodies eth.BlockBodiesPacket66 +type BlockBodies eth.BlockBodiesPacket   func (msg BlockBodies) Code() int { return 22 } func (msg BlockBodies) ReqID() uint64 { return msg.RequestId } @@ -128,7 +128,7 @@ func (msg NewBlock) Code() int { return 23 } func (msg NewBlock) ReqID() uint64 { return 0 }   // NewPooledTransactionHashes66 is the network packet for the tx hash propagation message. -type NewPooledTransactionHashes66 eth.NewPooledTransactionHashesPacket66 +type NewPooledTransactionHashes66 eth.NewPooledTransactionHashesPacket67   func (msg NewPooledTransactionHashes66) Code() int { return 24 } func (msg NewPooledTransactionHashes66) ReqID() uint64 { return 0 } @@ -139,12 +139,12 @@ func (msg NewPooledTransactionHashes) Code() int { return 24 } func (msg NewPooledTransactionHashes) ReqID() uint64 { return 0 }   -type GetPooledTransactions eth.GetPooledTransactionsPacket66 +type GetPooledTransactions eth.GetPooledTransactionsPacket   func (msg GetPooledTransactions) Code() int { return 25 } func (msg GetPooledTransactions) ReqID() uint64 { return msg.RequestId }   -type PooledTransactions eth.PooledTransactionsPacket66 +type PooledTransactions eth.PooledTransactionsPacket   func (msg PooledTransactions) Code() int { return 26 } func (msg PooledTransactions) ReqID() uint64 { return msg.RequestId } @@ -180,25 +180,25 @@ msg = new(Disconnect) case (Status{}).Code(): msg = new(Status) case (GetBlockHeaders{}).Code(): - ethMsg := new(eth.GetBlockHeadersPacket66) + ethMsg := new(eth.GetBlockHeadersPacket) if err := rlp.DecodeBytes(rawData, ethMsg); err != nil { return errorf("could not rlp decode message: %v", err) } return (*GetBlockHeaders)(ethMsg) case (BlockHeaders{}).Code(): - ethMsg := new(eth.BlockHeadersPacket66) + ethMsg := new(eth.BlockHeadersPacket) if err := rlp.DecodeBytes(rawData, ethMsg); err != nil { return errorf("could not rlp decode message: %v", err) } return (*BlockHeaders)(ethMsg) case (GetBlockBodies{}).Code(): - ethMsg := new(eth.GetBlockBodiesPacket66) + ethMsg := new(eth.GetBlockBodiesPacket) if err := rlp.DecodeBytes(rawData, ethMsg); err != nil { return errorf("could not rlp decode message: %v", err) } return (*GetBlockBodies)(ethMsg) case (BlockBodies{}).Code(): - ethMsg := new(eth.BlockBodiesPacket66) + ethMsg := new(eth.BlockBodiesPacket) if err := rlp.DecodeBytes(rawData, ethMsg); err != nil { return errorf("could not rlp decode message: %v", err) } @@ -217,13 +217,13 @@ return ethMsg } msg = new(NewPooledTransactionHashes66) case (GetPooledTransactions{}.Code()): - ethMsg := new(eth.GetPooledTransactionsPacket66) + ethMsg := new(eth.GetPooledTransactionsPacket) if err := rlp.DecodeBytes(rawData, ethMsg); err != nil { return errorf("could not rlp decode message: %v", err) } return (*GetPooledTransactions)(ethMsg) case (PooledTransactions{}.Code()): - ethMsg := new(eth.PooledTransactionsPacket66) + ethMsg := new(eth.PooledTransactionsPacket) if err := rlp.DecodeBytes(rawData, ethMsg); err != nil { return errorf("could not rlp decode message: %v", err) }
diff --git ethereum/go-ethereum/cmd/evm/internal/t8ntool/block.go taikoxyz/taiko-geth/cmd/evm/internal/t8ntool/block.go index 09dca8984e9c89c8132fd6e1b6caf00b3f7600d2..5c0e28e284c0c3090eb0f971310707456c1cf1b2 100644 --- ethereum/go-ethereum/cmd/evm/internal/t8ntool/block.go +++ taikoxyz/taiko-geth/cmd/evm/internal/t8ntool/block.go @@ -37,33 +37,38 @@ )   //go:generate go run github.com/fjl/gencodec -type header -field-override headerMarshaling -out gen_header.go type header struct { - ParentHash common.Hash `json:"parentHash"` - OmmerHash *common.Hash `json:"sha3Uncles"` - Coinbase *common.Address `json:"miner"` - Root common.Hash `json:"stateRoot" gencodec:"required"` - TxHash *common.Hash `json:"transactionsRoot"` - ReceiptHash *common.Hash `json:"receiptsRoot"` - Bloom types.Bloom `json:"logsBloom"` - Difficulty *big.Int `json:"difficulty"` - Number *big.Int `json:"number" gencodec:"required"` - GasLimit uint64 `json:"gasLimit" gencodec:"required"` - GasUsed uint64 `json:"gasUsed"` - Time uint64 `json:"timestamp" gencodec:"required"` - Extra []byte `json:"extraData"` - MixDigest common.Hash `json:"mixHash"` - Nonce *types.BlockNonce `json:"nonce"` - BaseFee *big.Int `json:"baseFeePerGas" rlp:"optional"` - WithdrawalsHash *common.Hash `json:"withdrawalsRoot" rlp:"optional"` + ParentHash common.Hash `json:"parentHash"` + OmmerHash *common.Hash `json:"sha3Uncles"` + Coinbase *common.Address `json:"miner"` + Root common.Hash `json:"stateRoot" gencodec:"required"` + TxHash *common.Hash `json:"transactionsRoot"` + ReceiptHash *common.Hash `json:"receiptsRoot"` + Bloom types.Bloom `json:"logsBloom"` + Difficulty *big.Int `json:"difficulty"` + Number *big.Int `json:"number" gencodec:"required"` + GasLimit uint64 `json:"gasLimit" gencodec:"required"` + GasUsed uint64 `json:"gasUsed"` + Time uint64 `json:"timestamp" gencodec:"required"` + Extra []byte `json:"extraData"` + MixDigest common.Hash `json:"mixHash"` + Nonce *types.BlockNonce `json:"nonce"` + BaseFee *big.Int `json:"baseFeePerGas" rlp:"optional"` + WithdrawalsHash *common.Hash `json:"withdrawalsRoot" rlp:"optional"` + BlobGasUsed *uint64 `json:"blobGasUsed" rlp:"optional"` + ExcessBlobGas *uint64 `json:"excessBlobGas" rlp:"optional"` + ParentBeaconBlockRoot *common.Hash `json:"parentBeaconBlockRoot" rlp:"optional"` }   type headerMarshaling struct { - Difficulty *math.HexOrDecimal256 - Number *math.HexOrDecimal256 - GasLimit math.HexOrDecimal64 - GasUsed math.HexOrDecimal64 - Time math.HexOrDecimal64 - Extra hexutil.Bytes - BaseFee *math.HexOrDecimal256 + Difficulty *math.HexOrDecimal256 + Number *math.HexOrDecimal256 + GasLimit math.HexOrDecimal64 + GasUsed math.HexOrDecimal64 + Time math.HexOrDecimal64 + Extra hexutil.Bytes + BaseFee *math.HexOrDecimal256 + BlobGasUsed *math.HexOrDecimal64 + ExcessBlobGas *math.HexOrDecimal64 }   type bbInput struct { @@ -113,22 +118,25 @@ // ToBlock converts i into a *types.Block func (i *bbInput) ToBlock() *types.Block { header := &types.Header{ - ParentHash: i.Header.ParentHash, - UncleHash: types.EmptyUncleHash, - Coinbase: common.Address{}, - Root: i.Header.Root, - TxHash: types.EmptyTxsHash, - ReceiptHash: types.EmptyReceiptsHash, - Bloom: i.Header.Bloom, - Difficulty: common.Big0, - Number: i.Header.Number, - GasLimit: i.Header.GasLimit, - GasUsed: i.Header.GasUsed, - Time: i.Header.Time, - Extra: i.Header.Extra, - MixDigest: i.Header.MixDigest, - BaseFee: i.Header.BaseFee, - WithdrawalsHash: i.Header.WithdrawalsHash, + ParentHash: i.Header.ParentHash, + UncleHash: types.EmptyUncleHash, + Coinbase: common.Address{}, + Root: i.Header.Root, + TxHash: types.EmptyTxsHash, + ReceiptHash: types.EmptyReceiptsHash, + Bloom: i.Header.Bloom, + Difficulty: common.Big0, + Number: i.Header.Number, + GasLimit: i.Header.GasLimit, + GasUsed: i.Header.GasUsed, + Time: i.Header.Time, + Extra: i.Header.Extra, + MixDigest: i.Header.MixDigest, + BaseFee: i.Header.BaseFee, + WithdrawalsHash: i.Header.WithdrawalsHash, + BlobGasUsed: i.Header.BlobGasUsed, + ExcessBlobGas: i.Header.ExcessBlobGas, + ParentBeaconRoot: i.Header.ParentBeaconBlockRoot, }   // Fill optional values. @@ -150,7 +158,7 @@ } if i.Header.Nonce != nil { header.Nonce = *i.Header.Nonce } - if header.Difficulty != nil { + if i.Header.Difficulty != nil { header.Difficulty = i.Header.Difficulty } return types.NewBlockWithHeader(header).WithBody(i.Txs, i.Ommers).WithWithdrawals(i.Withdrawals)
diff --git ethereum/go-ethereum/cmd/evm/internal/t8ntool/execution.go taikoxyz/taiko-geth/cmd/evm/internal/t8ntool/execution.go index c408623fe32f4c9b217cd4a9be29fa3955e3eaf8..312f427d4c6b98b4b86edef7ac23e4af2598be4b 100644 --- ethereum/go-ethereum/cmd/evm/internal/t8ntool/execution.go +++ taikoxyz/taiko-geth/cmd/evm/internal/t8ntool/execution.go @@ -59,7 +59,7 @@ GasUsed math.HexOrDecimal64 `json:"gasUsed"` BaseFee *math.HexOrDecimal256 `json:"currentBaseFee,omitempty"` WithdrawalsRoot *common.Hash `json:"withdrawalsRoot,omitempty"` CurrentExcessBlobGas *math.HexOrDecimal64 `json:"currentExcessBlobGas,omitempty"` - CurrentBlobGasUsed *math.HexOrDecimal64 `json:"currentBlobGasUsed,omitempty"` + CurrentBlobGasUsed *math.HexOrDecimal64 `json:"blobGasUsed,omitempty"` }   type ommer struct { @@ -69,25 +69,26 @@ }   //go:generate go run github.com/fjl/gencodec -type stEnv -field-override stEnvMarshaling -out gen_stenv.go type stEnv struct { - Coinbase common.Address `json:"currentCoinbase" gencodec:"required"` - Difficulty *big.Int `json:"currentDifficulty"` - Random *big.Int `json:"currentRandom"` - ParentDifficulty *big.Int `json:"parentDifficulty"` - ParentBaseFee *big.Int `json:"parentBaseFee,omitempty"` - ParentGasUsed uint64 `json:"parentGasUsed,omitempty"` - ParentGasLimit uint64 `json:"parentGasLimit,omitempty"` - GasLimit uint64 `json:"currentGasLimit" gencodec:"required"` - Number uint64 `json:"currentNumber" gencodec:"required"` - Timestamp uint64 `json:"currentTimestamp" gencodec:"required"` - ParentTimestamp uint64 `json:"parentTimestamp,omitempty"` - BlockHashes map[math.HexOrDecimal64]common.Hash `json:"blockHashes,omitempty"` - Ommers []ommer `json:"ommers,omitempty"` - Withdrawals []*types.Withdrawal `json:"withdrawals,omitempty"` - BaseFee *big.Int `json:"currentBaseFee,omitempty"` - ParentUncleHash common.Hash `json:"parentUncleHash"` - ExcessBlobGas *uint64 `json:"excessBlobGas,omitempty"` - ParentExcessBlobGas *uint64 `json:"parentExcessBlobGas,omitempty"` - ParentBlobGasUsed *uint64 `json:"parentBlobGasUsed,omitempty"` + Coinbase common.Address `json:"currentCoinbase" gencodec:"required"` + Difficulty *big.Int `json:"currentDifficulty"` + Random *big.Int `json:"currentRandom"` + ParentDifficulty *big.Int `json:"parentDifficulty"` + ParentBaseFee *big.Int `json:"parentBaseFee,omitempty"` + ParentGasUsed uint64 `json:"parentGasUsed,omitempty"` + ParentGasLimit uint64 `json:"parentGasLimit,omitempty"` + GasLimit uint64 `json:"currentGasLimit" gencodec:"required"` + Number uint64 `json:"currentNumber" gencodec:"required"` + Timestamp uint64 `json:"currentTimestamp" gencodec:"required"` + ParentTimestamp uint64 `json:"parentTimestamp,omitempty"` + BlockHashes map[math.HexOrDecimal64]common.Hash `json:"blockHashes,omitempty"` + Ommers []ommer `json:"ommers,omitempty"` + Withdrawals []*types.Withdrawal `json:"withdrawals,omitempty"` + BaseFee *big.Int `json:"currentBaseFee,omitempty"` + ParentUncleHash common.Hash `json:"parentUncleHash"` + ExcessBlobGas *uint64 `json:"currentExcessBlobGas,omitempty"` + ParentExcessBlobGas *uint64 `json:"parentExcessBlobGas,omitempty"` + ParentBlobGasUsed *uint64 `json:"parentBlobGasUsed,omitempty"` + ParentBeaconBlockRoot *common.Hash `json:"parentBeaconBlockRoot"` }   type stEnvMarshaling struct { @@ -162,17 +163,19 @@ if pre.Env.Random != nil { rnd := common.BigToHash(pre.Env.Random) vmContext.Random = &rnd } - // If excessBlobGas is defined, add it to the vmContext. + // Calculate the BlobBaseFee + var excessBlobGas uint64 if pre.Env.ExcessBlobGas != nil { - vmContext.ExcessBlobGas = pre.Env.ExcessBlobGas + excessBlobGas := *pre.Env.ExcessBlobGas + vmContext.BlobBaseFee = eip4844.CalcBlobFee(excessBlobGas) } else { // If it is not explicitly defined, but we have the parent values, we try // to calculate it ourselves. parentExcessBlobGas := pre.Env.ParentExcessBlobGas parentBlobGasUsed := pre.Env.ParentBlobGasUsed if parentExcessBlobGas != nil && parentBlobGasUsed != nil { - excessBlobGas := eip4844.CalcExcessBlobGas(*parentExcessBlobGas, *parentBlobGasUsed) - vmContext.ExcessBlobGas = &excessBlobGas + excessBlobGas = eip4844.CalcExcessBlobGas(*parentExcessBlobGas, *parentBlobGasUsed) + vmContext.BlobBaseFee = eip4844.CalcBlobFee(excessBlobGas) } } // If DAO is supported/enabled, we need to handle it here. In geth 'proper', it's @@ -182,13 +185,20 @@ chainConfig.DAOForkBlock != nil && chainConfig.DAOForkBlock.Cmp(new(big.Int).SetUint64(pre.Env.Number)) == 0 { misc.ApplyDAOHardFork(statedb) } + if beaconRoot := pre.Env.ParentBeaconBlockRoot; beaconRoot != nil { + evm := vm.NewEVM(vmContext, vm.TxContext{}, statedb, chainConfig, vmConfig) + core.ProcessBeaconBlockRoot(*beaconRoot, evm, statedb) + } var blobGasUsed uint64 for i, tx := range txs { - if tx.Type() == types.BlobTxType && vmContext.ExcessBlobGas == nil { + if tx.Type() == types.BlobTxType && vmContext.BlobBaseFee == nil { errMsg := "blob tx used but field env.ExcessBlobGas missing" log.Warn("rejected tx", "index", i, "hash", tx.Hash(), "error", errMsg) rejectedTxs = append(rejectedTxs, &rejectedTx{i, errMsg}) continue + } + if tx.Type() == types.BlobTxType { + blobGasUsed += uint64(params.BlobTxBlobGasPerBlob * len(tx.BlobHashes())) } msg, err := core.TransactionToMessage(tx, signer, pre.Env.BaseFee) if err != nil { @@ -218,9 +228,6 @@ log.Info("rejected tx", "index", i, "hash", tx.Hash(), "from", msg.From, "error", err) rejectedTxs = append(rejectedTxs, &rejectedTx{i, err.Error()}) gaspool.SetGas(prevGas) continue - } - if tx.Type() == types.BlobTxType { - blobGasUsed += params.BlobTxBlobGasPerBlob } includedTxs = append(includedTxs, tx) if hashError != nil { @@ -317,8 +324,8 @@ if pre.Env.Withdrawals != nil { h := types.DeriveSha(types.Withdrawals(pre.Env.Withdrawals), trie.NewStackTrie(nil)) execRs.WithdrawalsRoot = &h } - if vmContext.ExcessBlobGas != nil { - execRs.CurrentExcessBlobGas = (*math.HexOrDecimal64)(vmContext.ExcessBlobGas) + if vmContext.BlobBaseFee != nil { + execRs.CurrentExcessBlobGas = (*math.HexOrDecimal64)(&excessBlobGas) execRs.CurrentBlobGasUsed = (*math.HexOrDecimal64)(&blobGasUsed) } // Re-create statedb instance with new root upon the updated database
diff --git ethereum/go-ethereum/cmd/evm/internal/t8ntool/transition.go taikoxyz/taiko-geth/cmd/evm/internal/t8ntool/transition.go index cbb39294d04c13f2ff150f93eb8b02e5c730313c..600bc460f726c4344e8611e2c023bda53ad6c4fd 100644 --- ethereum/go-ethereum/cmd/evm/internal/t8ntool/transition.go +++ taikoxyz/taiko-geth/cmd/evm/internal/t8ntool/transition.go @@ -192,105 +192,20 @@ } // Set the chain id chainConfig.ChainID = big.NewInt(ctx.Int64(ChainIDFlag.Name))   - var txsWithKeys []*txWithKey - if txStr != stdinSelector { - inFile, err := os.Open(txStr) - if err != nil { - return NewError(ErrorIO, fmt.Errorf("failed reading txs file: %v", err)) - } - defer inFile.Close() - decoder := json.NewDecoder(inFile) - if strings.HasSuffix(txStr, ".rlp") { - var body hexutil.Bytes - if err := decoder.Decode(&body); err != nil { - return err - } - var txs types.Transactions - if err := rlp.DecodeBytes(body, &txs); err != nil { - return err - } - for _, tx := range txs { - txsWithKeys = append(txsWithKeys, &txWithKey{ - key: nil, - tx: tx, - }) - } - } else { - if err := decoder.Decode(&txsWithKeys); err != nil { - return NewError(ErrorJson, fmt.Errorf("failed unmarshaling txs-file: %v", err)) - } - } - } else { - if len(inputData.TxRlp) > 0 { - // Decode the body of already signed transactions - body := common.FromHex(inputData.TxRlp) - var txs types.Transactions - if err := rlp.DecodeBytes(body, &txs); err != nil { - return err - } - for _, tx := range txs { - txsWithKeys = append(txsWithKeys, &txWithKey{ - key: nil, - tx: tx, - }) - } - } else { - // JSON encoded transactions - txsWithKeys = inputData.Txs - } + if txs, err = loadTransactions(txStr, inputData, prestate.Env, chainConfig); err != nil { + return err } - // We may have to sign the transactions. - signer := types.MakeSigner(chainConfig, big.NewInt(int64(prestate.Env.Number)), prestate.Env.Timestamp) - - if txs, err = signUnsignedTransactions(txsWithKeys, signer); err != nil { - return NewError(ErrorJson, fmt.Errorf("failed signing transactions: %v", err)) + if err := applyLondonChecks(&prestate.Env, chainConfig); err != nil { + return err } - // Sanity check, to not `panic` in state_transition - if chainConfig.IsLondon(big.NewInt(int64(prestate.Env.Number))) { - if prestate.Env.BaseFee != nil { - // Already set, base fee has precedent over parent base fee. - } else if prestate.Env.ParentBaseFee != nil && prestate.Env.Number != 0 { - parent := &types.Header{ - Number: new(big.Int).SetUint64(prestate.Env.Number - 1), - BaseFee: prestate.Env.ParentBaseFee, - GasUsed: prestate.Env.ParentGasUsed, - GasLimit: prestate.Env.ParentGasLimit, - } - prestate.Env.BaseFee = eip1559.CalcBaseFee(chainConfig, parent) - } else { - return NewError(ErrorConfig, errors.New("EIP-1559 config but missing 'currentBaseFee' in env section")) - } + if err := applyShanghaiChecks(&prestate.Env, chainConfig); err != nil { + return err } - if chainConfig.IsShanghai(big.NewInt(int64(prestate.Env.Number)), prestate.Env.Timestamp) && prestate.Env.Withdrawals == nil { - return NewError(ErrorConfig, errors.New("Shanghai config but missing 'withdrawals' in env section")) + if err := applyMergeChecks(&prestate.Env, chainConfig); err != nil { + return err } - isMerged := chainConfig.TerminalTotalDifficulty != nil && chainConfig.TerminalTotalDifficulty.BitLen() == 0 - env := prestate.Env - if isMerged { - // post-merge: - // - random must be supplied - // - difficulty must be zero - switch { - case env.Random == nil: - return NewError(ErrorConfig, errors.New("post-merge requires currentRandom to be defined in env")) - case env.Difficulty != nil && env.Difficulty.BitLen() != 0: - return NewError(ErrorConfig, errors.New("post-merge difficulty must be zero (or omitted) in env")) - } - prestate.Env.Difficulty = nil - } else if env.Difficulty == nil { - // pre-merge: - // If difficulty was not provided by caller, we need to calculate it. - switch { - case env.ParentDifficulty == nil: - return NewError(ErrorConfig, errors.New("currentDifficulty was not provided, and cannot be calculated due to missing parentDifficulty")) - case env.Number == 0: - return NewError(ErrorConfig, errors.New("currentDifficulty needs to be provided for block number 0")) - case env.Timestamp <= env.ParentTimestamp: - return NewError(ErrorConfig, fmt.Errorf("currentDifficulty cannot be calculated -- currentTime (%d) needs to be after parent time (%d)", - env.Timestamp, env.ParentTimestamp)) - } - prestate.Env.Difficulty = calcDifficulty(chainConfig, env.Number, env.Timestamp, - env.ParentTimestamp, env.ParentDifficulty, env.ParentUncleHash) + if err := applyCancunChecks(&prestate.Env, chainConfig); err != nil { + return err } // Run the test and aggregate the result s, result, err := prestate.Apply(vmConfig, chainConfig, txs, ctx.Int64(RewardFlag.Name), getTracer) @@ -358,31 +273,147 @@ // To manage this, we read the transactions twice, first trying to read the secretKeys, // and secondly to read them with the standard tx json format func signUnsignedTransactions(txs []*txWithKey, signer types.Signer) (types.Transactions, error) { var signedTxs []*types.Transaction - for i, txWithKey := range txs { - tx := txWithKey.tx - key := txWithKey.key - v, r, s := tx.RawSignatureValues() - if key != nil && v.BitLen()+r.BitLen()+s.BitLen() == 0 { - // This transaction needs to be signed - var ( - signed *types.Transaction - err error - ) - if txWithKey.protected { - signed, err = types.SignTx(tx, signer, key) - } else { - signed, err = types.SignTx(tx, types.FrontierSigner{}, key) + for i, tx := range txs { + var ( + v, r, s = tx.tx.RawSignatureValues() + signed *types.Transaction + err error + ) + if tx.key == nil || v.BitLen()+r.BitLen()+s.BitLen() != 0 { + // Already signed + signedTxs = append(signedTxs, tx.tx) + continue + } + // This transaction needs to be signed + if tx.protected { + signed, err = types.SignTx(tx.tx, signer, tx.key) + } else { + signed, err = types.SignTx(tx.tx, types.FrontierSigner{}, tx.key) + } + if err != nil { + return nil, NewError(ErrorJson, fmt.Errorf("tx %d: failed to sign tx: %v", i, err)) + } + signedTxs = append(signedTxs, signed) + } + return signedTxs, nil +} + +func loadTransactions(txStr string, inputData *input, env stEnv, chainConfig *params.ChainConfig) (types.Transactions, error) { + var txsWithKeys []*txWithKey + var signed types.Transactions + if txStr != stdinSelector { + data, err := os.ReadFile(txStr) + if err != nil { + return nil, NewError(ErrorIO, fmt.Errorf("failed reading txs file: %v", err)) + } + if strings.HasSuffix(txStr, ".rlp") { // A file containing an rlp list + var body hexutil.Bytes + if err := json.Unmarshal(data, &body); err != nil { + return nil, err } - if err != nil { - return nil, NewError(ErrorJson, fmt.Errorf("tx %d: failed to sign tx: %v", i, err)) + // Already signed transactions + if err := rlp.DecodeBytes(body, &signed); err != nil { + return nil, err } - signedTxs = append(signedTxs, signed) - } else { - // Already signed - signedTxs = append(signedTxs, tx) + return signed, nil + } + if err := json.Unmarshal(data, &txsWithKeys); err != nil { + return nil, NewError(ErrorJson, fmt.Errorf("failed unmarshaling txs-file: %v", err)) + } + } else { + if len(inputData.TxRlp) > 0 { + // Decode the body of already signed transactions + body := common.FromHex(inputData.TxRlp) + // Already signed transactions + if err := rlp.DecodeBytes(body, &signed); err != nil { + return nil, err + } + return signed, nil + } + // JSON encoded transactions + txsWithKeys = inputData.Txs + } + // We may have to sign the transactions. + signer := types.LatestSignerForChainID(chainConfig.ChainID) + return signUnsignedTransactions(txsWithKeys, signer) +} + +func applyLondonChecks(env *stEnv, chainConfig *params.ChainConfig) error { + if !chainConfig.IsLondon(big.NewInt(int64(env.Number))) { + return nil + } + // Sanity check, to not `panic` in state_transition + if env.BaseFee != nil { + // Already set, base fee has precedent over parent base fee. + return nil + } + if env.ParentBaseFee == nil || env.Number == 0 { + return NewError(ErrorConfig, errors.New("EIP-1559 config but missing 'currentBaseFee' in env section")) + } + env.BaseFee = eip1559.CalcBaseFee(chainConfig, &types.Header{ + Number: new(big.Int).SetUint64(env.Number - 1), + BaseFee: env.ParentBaseFee, + GasUsed: env.ParentGasUsed, + GasLimit: env.ParentGasLimit, + }) + return nil +} + +func applyShanghaiChecks(env *stEnv, chainConfig *params.ChainConfig) error { + if !chainConfig.IsShanghai(big.NewInt(int64(env.Number)), env.Timestamp) { + return nil + } + if env.Withdrawals == nil { + return NewError(ErrorConfig, errors.New("Shanghai config but missing 'withdrawals' in env section")) + } + return nil +} + +func applyMergeChecks(env *stEnv, chainConfig *params.ChainConfig) error { + isMerged := chainConfig.TerminalTotalDifficulty != nil && chainConfig.TerminalTotalDifficulty.BitLen() == 0 + if !isMerged { + // pre-merge: If difficulty was not provided by caller, we need to calculate it. + if env.Difficulty != nil { + // already set + return nil + } + switch { + case env.ParentDifficulty == nil: + return NewError(ErrorConfig, errors.New("currentDifficulty was not provided, and cannot be calculated due to missing parentDifficulty")) + case env.Number == 0: + return NewError(ErrorConfig, errors.New("currentDifficulty needs to be provided for block number 0")) + case env.Timestamp <= env.ParentTimestamp: + return NewError(ErrorConfig, fmt.Errorf("currentDifficulty cannot be calculated -- currentTime (%d) needs to be after parent time (%d)", + env.Timestamp, env.ParentTimestamp)) } + env.Difficulty = calcDifficulty(chainConfig, env.Number, env.Timestamp, + env.ParentTimestamp, env.ParentDifficulty, env.ParentUncleHash) + return nil } - return signedTxs, nil + // post-merge: + // - random must be supplied + // - difficulty must be zero + switch { + case env.Random == nil: + return NewError(ErrorConfig, errors.New("post-merge requires currentRandom to be defined in env")) + case env.Difficulty != nil && env.Difficulty.BitLen() != 0: + return NewError(ErrorConfig, errors.New("post-merge difficulty must be zero (or omitted) in env")) + } + env.Difficulty = nil + return nil +} + +func applyCancunChecks(env *stEnv, chainConfig *params.ChainConfig) error { + if !chainConfig.IsCancun(big.NewInt(int64(env.Number)), env.Timestamp) { + env.ParentBeaconBlockRoot = nil // un-set it if it has been set too early + return nil + } + // Post-cancun + // We require EIP-4788 beacon root to be set in the env + if env.ParentBeaconBlockRoot == nil { + return NewError(ErrorConfig, errors.New("post-cancun env requires parentBeaconBlockRoot to be set")) + } + return nil }   type Alloc map[common.Address]core.GenesisAccount
diff --git ethereum/go-ethereum/cmd/evm/testdata/29/readme.md taikoxyz/taiko-geth/cmd/evm/testdata/29/readme.md new file mode 100644 index 0000000000000000000000000000000000000000..ab02ce9cf8d1bf675ac13125137ecf8b6c0a8a97 --- /dev/null +++ taikoxyz/taiko-geth/cmd/evm/testdata/29/readme.md @@ -0,0 +1,29 @@ +## EIP 4788 + +This test contains testcases for EIP-4788. The 4788-contract is +located at address `0x000F3df6D732807Ef1319fB7B8bB8522d0Beac02`, and this test executes a simple transaction. It also +implicitly invokes the system tx, which sets calls the contract and sets the +storage values + +``` +$ dir=./testdata/29/ && go run . t8n --state.fork=Cancun --input.alloc=$dir/alloc.json --input.txs=$dir/txs.json --input.env=$dir/env.json --output.alloc=stdout +INFO [09-27|15:34:53.049] Trie dumping started root=19a4f8..01573c +INFO [09-27|15:34:53.049] Trie dumping complete accounts=2 elapsed="192.759µs" +INFO [09-27|15:34:53.050] Wrote file file=result.json +{ + "alloc": { + "0x000f3df6d732807ef1319fb7b8bb8522d0beac02": { + "code": "0x3373fffffffffffffffffffffffffffffffffffffffe14604457602036146024575f5ffd5b620180005f350680545f35146037575f5ffd5b6201800001545f5260205ff35b6201800042064281555f359062018000015500", + "storage": { + "0x000000000000000000000000000000000000000000000000000000000000079e": "0x000000000000000000000000000000000000000000000000000000000000079e", + "0x000000000000000000000000000000000000000000000000000000000001879e": "0x0000beac00beac00beac00beac00beac00beac00beac00beac00beac00beac00" + }, + "balance": "0x1" + }, + "0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b": { + "balance": "0x16345785d871db8", + "nonce": "0x1" + } + } +} +```
diff --git ethereum/go-ethereum/cmd/evm/testdata/8/readme.md taikoxyz/taiko-geth/cmd/evm/testdata/8/readme.md index 4dffdab91ebd75d3806a55b237d70783d56a39c4..85aae189243c551af1efa603db2d5c92ea79974e 100644 --- ethereum/go-ethereum/cmd/evm/testdata/8/readme.md +++ taikoxyz/taiko-geth/cmd/evm/testdata/8/readme.md @@ -32,7 +32,7 @@ {"pc":1,"op":84,"gas":"0x484be","gasCost":"0x64","memSize":0,"stack":["0x0"],"depth":1,"refund":0,"opName":"SLOAD"} {"pc":4,"op":84,"gas":"0x48456","gasCost":"0x64","memSize":0,"stack":["0x3"],"depth":1,"refund":0,"opName":"SLOAD"} ```   -Simlarly, we can provide the input transactions via `stdin` instead of as file: +Similarly, we can provide the input transactions via `stdin` instead of as file:   ``` $ dir=./testdata/8 \
diff --git ethereum/go-ethereum/cmd/evm/testdata/9/readme.md taikoxyz/taiko-geth/cmd/evm/testdata/9/readme.md index 539478028869519dda38ceb4907831f52ea4897f..357e200682f6cd3e59a644c1c6083fc8bc54521d 100644 --- ethereum/go-ethereum/cmd/evm/testdata/9/readme.md +++ taikoxyz/taiko-geth/cmd/evm/testdata/9/readme.md @@ -1,6 +1,6 @@ ## EIP-1559 testing   -This test contains testcases for EIP-1559, which uses an new transaction type and has a new block parameter. +This test contains testcases for EIP-1559, which uses a new transaction type and has a new block parameter.   ### Prestate
diff --git ethereum/go-ethereum/cmd/geth/testdata/vcheck/minisig-sigs-new/data.json.minisig taikoxyz/taiko-geth/cmd/geth/testdata/vcheck/minisig-sigs-new/data.json.minisig new file mode 100644 index 0000000000000000000000000000000000000000..eaea9f9053f43037c0702fd8dde0f706459bfec4 --- /dev/null +++ taikoxyz/taiko-geth/cmd/geth/testdata/vcheck/minisig-sigs-new/data.json.minisig @@ -0,0 +1,4 @@ +untrusted comment: signature from minisign secret key +RUQkliYstQBOKLK05Sy5f3bVRMBqJT26ABo6Vbp3BNJAVjejoqYCu4GWE/+7qcDfHBqYIniDCbFIUvYEnOHxV6vZ93wO1xJWDQw= +trusted comment: timestamp:1693986492 file:data.json hashed +6Fdw2H+W1ZXK7QXSF77Z5AWC7+AEFAfDmTSxNGylU5HLT1AuSJQmxslj+VjtUBamYCvOuET7plbXza942AlWDw==
diff --git ethereum/go-ethereum/common/types.go taikoxyz/taiko-geth/common/types.go index bf74e43716a1afe6d844ee48120dc7347f303817..aadca87f82af89543de3387e24a90cba5fe1846f 100644 --- ethereum/go-ethereum/common/types.go +++ taikoxyz/taiko-geth/common/types.go @@ -44,6 +44,12 @@ var ( hashT = reflect.TypeOf(Hash{}) addressT = reflect.TypeOf(Address{}) + + // MaxAddress represents the maximum possible address value. + MaxAddress = HexToAddress("0xffffffffffffffffffffffffffffffffffffffff") + + // MaxHash represents the maximum possible hash value. + MaxHash = HexToHash("0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff") )   // Hash represents the 32 byte Keccak256 hash of arbitrary data. @@ -238,9 +244,6 @@ }   // Bytes gets the string representation of the underlying address. func (a Address) Bytes() []byte { return a[:] } - -// Hash converts an address to a hash by left-padding it with zeros. -func (a Address) Hash() Hash { return BytesToHash(a[:]) }   // Big converts an address to a big integer. func (a Address) Big() *big.Int { return new(big.Int).SetBytes(a[:]) }
diff --git ethereum/go-ethereum/common/types_test.go taikoxyz/taiko-geth/common/types_test.go index ad892671b5b34e889373d032cc3cd5d3613f0116..cec689ea39f7556e2765d0d98bd09eaf96c4e688 100644 --- ethereum/go-ethereum/common/types_test.go +++ taikoxyz/taiko-geth/common/types_test.go @@ -25,6 +25,7 @@ "math/big" "reflect" "strings" "testing" + "time" )   func TestBytesConversion(t *testing.T) { @@ -583,3 +584,14 @@ if addr != dec { t.Fatal("Unexpected address after unmarshal") } } + +func BenchmarkPrettyDuration(b *testing.B) { + var x = PrettyDuration(time.Duration(int64(1203123912312))) + b.Logf("Pre %s", time.Duration(x).String()) + var a string + b.ResetTimer() + for i := 0; i < b.N; i++ { + a = x.String() + } + b.Logf("Post %s", a) +}
diff --git ethereum/go-ethereum/consensus/misc/eip4844/eip4844.go taikoxyz/taiko-geth/consensus/misc/eip4844/eip4844.go index 583bcdeecd6e369ae6b890cddab071a5a26097da..2dad9a0cd3de18ac8db0dde8ba7101300b11d6d9 100644 --- ethereum/go-ethereum/consensus/misc/eip4844/eip4844.go +++ taikoxyz/taiko-geth/consensus/misc/eip4844/eip4844.go @@ -42,8 +42,8 @@ if header.BlobGasUsed == nil { return errors.New("header is missing blobGasUsed") } // Verify that the blob gas used remains within reasonable limits. - if *header.BlobGasUsed > params.BlobTxMaxBlobGasPerBlock { - return fmt.Errorf("blob gas used %d exceeds maximum allowance %d", *header.BlobGasUsed, params.BlobTxMaxBlobGasPerBlock) + if *header.BlobGasUsed > params.MaxBlobGasPerBlock { + return fmt.Errorf("blob gas used %d exceeds maximum allowance %d", *header.BlobGasUsed, params.MaxBlobGasPerBlock) } if *header.BlobGasUsed%params.BlobTxBlobGasPerBlob != 0 { return fmt.Errorf("blob gas used %d not a multiple of blob gas per blob %d", header.BlobGasUsed, params.BlobTxBlobGasPerBlob)
diff --git ethereum/go-ethereum/consensus/misc/eip4844/eip4844_test.go taikoxyz/taiko-geth/consensus/misc/eip4844/eip4844_test.go index 677cdd252c442875e5bd09a96645e4a2cd640a8d..ec417380fcb083b54b3343aafa72767c9b8cbe06 100644 --- ethereum/go-ethereum/consensus/misc/eip4844/eip4844_test.go +++ taikoxyz/taiko-geth/consensus/misc/eip4844/eip4844_test.go @@ -45,14 +45,14 @@ // The excess blob gas should decrease by however much the target was // under-shot, capped at zero. {params.BlobTxTargetBlobGasPerBlock, params.BlobTxTargetBlobGasPerBlock / params.BlobTxBlobGasPerBlob, params.BlobTxTargetBlobGasPerBlock}, - {params.BlobTxTargetBlobGasPerBlock, (params.BlobTxTargetBlobGasPerBlock / params.BlobTxBlobGasPerBlob) - 1, params.BlobTxBlobGasPerBlob}, - {params.BlobTxTargetBlobGasPerBlock, (params.BlobTxTargetBlobGasPerBlock / params.BlobTxBlobGasPerBlob) - 2, 0}, + {params.BlobTxTargetBlobGasPerBlock, (params.BlobTxTargetBlobGasPerBlock / params.BlobTxBlobGasPerBlob) - 1, params.BlobTxTargetBlobGasPerBlock - params.BlobTxBlobGasPerBlob}, + {params.BlobTxTargetBlobGasPerBlock, (params.BlobTxTargetBlobGasPerBlock / params.BlobTxBlobGasPerBlob) - 2, params.BlobTxTargetBlobGasPerBlock - (2 * params.BlobTxBlobGasPerBlob)}, {params.BlobTxBlobGasPerBlob - 1, (params.BlobTxTargetBlobGasPerBlock / params.BlobTxBlobGasPerBlob) - 1, 0}, } - for _, tt := range tests { + for i, tt := range tests { result := CalcExcessBlobGas(tt.excess, tt.blobs*params.BlobTxBlobGasPerBlob) if result != tt.want { - t.Errorf("excess blob gas mismatch: have %v, want %v", result, tt.want) + t.Errorf("test %d: excess blob gas mismatch: have %v, want %v", i, result, tt.want) } } } @@ -63,9 +63,9 @@ excessBlobGas uint64 blobfee int64 }{ {0, 1}, - {1542706, 1}, - {1542707, 2}, - {10 * 1024 * 1024, 111}, + {2314057, 1}, + {2314058, 2}, + {10 * 1024 * 1024, 23}, } for i, tt := range tests { have := CalcBlobFee(tt.excessBlobGas)
diff --git ethereum/go-ethereum/core/state/pruner/pruner.go taikoxyz/taiko-geth/core/state/pruner/pruner.go index 64c4a3a6ebaa7c64c15694439b12192801717399..5acf54f64272014a6c7383afc81c5970b6a0196b 100644 --- ethereum/go-ethereum/core/state/pruner/pruner.go +++ taikoxyz/taiko-geth/core/state/pruner/pruner.go @@ -85,13 +85,16 @@ headBlock := rawdb.ReadHeadBlock(db) if headBlock == nil { return nil, errors.New("failed to load head block") } + // Offline pruning is only supported in legacy hash based scheme. + triedb := trie.NewDatabase(db, trie.HashDefaults) + snapconfig := snapshot.Config{ CacheSize: 256, Recovery: false, NoBuild: true, AsyncBuild: false, } - snaptree, err := snapshot.New(snapconfig, db, trie.NewDatabase(db), headBlock.Root()) + snaptree, err := snapshot.New(snapconfig, db, triedb, headBlock.Root()) if err != nil { return nil, err // The relevant snapshot(s) might not exist } @@ -361,7 +364,9 @@ Recovery: true, NoBuild: true, AsyncBuild: false, } - snaptree, err := snapshot.New(snapconfig, db, trie.NewDatabase(db), headBlock.Root()) + // Offline pruning is only supported in legacy hash based scheme. + triedb := trie.NewDatabase(db, trie.HashDefaults) + snaptree, err := snapshot.New(snapconfig, db, triedb, headBlock.Root()) if err != nil { return err // The relevant snapshot(s) might not exist } @@ -403,7 +408,7 @@ genesis := rawdb.ReadBlock(db, genesisHash, 0) if genesis == nil { return errors.New("missing genesis block") } - t, err := trie.NewStateTrie(trie.StateTrieID(genesis.Root()), trie.NewDatabase(db)) + t, err := trie.NewStateTrie(trie.StateTrieID(genesis.Root()), trie.NewDatabase(db, trie.HashDefaults)) if err != nil { return err } @@ -427,7 +432,7 @@ return err } if acc.Root != types.EmptyRootHash { id := trie.StorageTrieID(genesis.Root(), common.BytesToHash(accIter.LeafKey()), acc.Root) - storageTrie, err := trie.NewStateTrie(id, trie.NewDatabase(db)) + storageTrie, err := trie.NewStateTrie(id, trie.NewDatabase(db, trie.HashDefaults)) if err != nil { return err }
diff --git ethereum/go-ethereum/core/state/snapshot/conversion.go taikoxyz/taiko-geth/core/state/snapshot/conversion.go index 1e683f76ce04f5359c7022c0edc51349d3ef57f7..321bfbc6a2dc1165aeca05eacf101ae070da9432 100644 --- ethereum/go-ethereum/core/state/snapshot/conversion.go +++ taikoxyz/taiko-geth/core/state/snapshot/conversion.go @@ -364,11 +364,11 @@ func stackTrieGenerate(db ethdb.KeyValueWriter, scheme string, owner common.Hash, in chan trieKV, out chan common.Hash) { var nodeWriter trie.NodeWriteFunc if db != nil { - nodeWriter = func(owner common.Hash, path []byte, hash common.Hash, blob []byte) { + nodeWriter = func(path []byte, hash common.Hash, blob []byte) { rawdb.WriteTrieNode(db, owner, path, hash, blob, scheme) } } - t := trie.NewStackTrieWithOwner(nodeWriter, owner) + t := trie.NewStackTrie(nodeWriter) for leaf := range in { t.Update(leaf.key[:], leaf.value) }
diff --git ethereum/go-ethereum/core/state/snapshot/generate.go taikoxyz/taiko-geth/core/state/snapshot/generate.go index 0a85f0006d87bb65a4190d5d53fd089d3076128e..204584c956eabb73c0457d318d7af27b3119b5c7 100644 --- ethereum/go-ethereum/core/state/snapshot/generate.go +++ taikoxyz/taiko-geth/core/state/snapshot/generate.go @@ -247,11 +247,6 @@ if err != nil { ctx.stats.Log("Trie missing, state snapshotting paused", dl.root, dl.genMarker) return nil, errMissingTrie } - // Firstly find out the key of last iterated element. - var last []byte - if len(keys) > 0 { - last = keys[len(keys)-1] - } // Generate the Merkle proofs for the first and last element if origin == nil { origin = common.Hash{}.Bytes() @@ -266,9 +261,9 @@ proofErr: err, tr: tr, }, nil } - if last != nil { - if err := tr.Prove(last, proof); err != nil { - log.Debug("Failed to prove range", "kind", kind, "last", last, "err", err) + if len(keys) > 0 { + if err := tr.Prove(keys[len(keys)-1], proof); err != nil { + log.Debug("Failed to prove range", "kind", kind, "last", keys[len(keys)-1], "err", err) return &proofResult{ keys: keys, vals: vals, @@ -280,7 +275,7 @@ } } // Verify the snapshot segment with range prover, ensure that all flat states // in this range correspond to merkle trie. - cont, err := trie.VerifyRangeProof(root, origin, last, keys, vals, proof) + cont, err := trie.VerifyRangeProof(root, origin, keys, vals, proof) return &proofResult{ keys: keys, vals: vals, @@ -356,7 +351,8 @@ // main account trie as a primary lookup when resolving hashes var resolver trie.NodeResolver if len(result.keys) > 0 { mdb := rawdb.NewMemoryDatabase() - tdb := trie.NewDatabase(mdb) + tdb := trie.NewDatabase(mdb, trie.HashDefaults) + defer tdb.Close() snapTrie := trie.NewEmpty(tdb) for i, key := range result.keys { snapTrie.Update(key, result.vals[i]) @@ -445,6 +441,10 @@ } internal += time.Since(istart) } if iter.Err != nil { + // Trie errors should never happen. Still, in case of a bug, expose the + // error here, as the outer code will presume errors are interrupts, not + // some deeper issues. + log.Error("State snapshotter failed to iterate trie", "err", err) return false, nil, iter.Err } // Delete all stale snapshot states remaining
diff --git ethereum/go-ethereum/core/state/snapshot/generate_test.go taikoxyz/taiko-geth/core/state/snapshot/generate_test.go index c503676241f903340626052405e1112dae3c1933..07016b675ce854ff07f541e51647a2614391219d 100644 --- ethereum/go-ethereum/core/state/snapshot/generate_test.go +++ taikoxyz/taiko-geth/core/state/snapshot/generate_test.go @@ -30,6 +30,8 @@ "github.com/ethereum/go-ethereum/ethdb" "github.com/ethereum/go-ethereum/log" "github.com/ethereum/go-ethereum/rlp" "github.com/ethereum/go-ethereum/trie" + "github.com/ethereum/go-ethereum/trie/triedb/hashdb" + "github.com/ethereum/go-ethereum/trie/triedb/pathdb" "github.com/ethereum/go-ethereum/trie/trienode" "golang.org/x/crypto/sha3" ) @@ -45,10 +47,15 @@ }   // Tests that snapshot generation from an empty database. func TestGeneration(t *testing.T) { + testGeneration(t, rawdb.HashScheme) + testGeneration(t, rawdb.PathScheme) +} + +func testGeneration(t *testing.T, scheme string) { // We can't use statedb to make a test trie (circular dependency), so make // a fake one manually. We're going with a small account trie of 3 accounts, // two of which also has the same 3-slot storage trie attached. - var helper = newHelper() + var helper = newHelper(scheme) stRoot := helper.makeStorageTrie(common.Hash{}, []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}, false)   helper.addTrieAccount("acc-1", &types.StateAccount{Balance: big.NewInt(1), Root: stRoot, CodeHash: types.EmptyCodeHash.Bytes()}) @@ -79,10 +86,15 @@ }   // Tests that snapshot generation with existent flat state. func TestGenerateExistentState(t *testing.T) { + testGenerateExistentState(t, rawdb.HashScheme) + testGenerateExistentState(t, rawdb.PathScheme) +} + +func testGenerateExistentState(t *testing.T, scheme string) { // We can't use statedb to make a test trie (circular dependency), so make // a fake one manually. We're going with a small account trie of 3 accounts, // two of which also has the same 3-slot storage trie attached. - var helper = newHelper() + var helper = newHelper(scheme)   stRoot := helper.makeStorageTrie(hashData([]byte("acc-1")), []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}, true) helper.addTrieAccount("acc-1", &types.StateAccount{Balance: big.NewInt(1), Root: stRoot, CodeHash: types.EmptyCodeHash.Bytes()}) @@ -148,9 +160,15 @@ accTrie *trie.StateTrie nodes *trienode.MergedNodeSet }   -func newHelper() *testHelper { +func newHelper(scheme string) *testHelper { diskdb := rawdb.NewMemoryDatabase() - triedb := trie.NewDatabase(diskdb) + config := &trie.Config{} + if scheme == rawdb.PathScheme { + config.PathDB = &pathdb.Config{} // disable caching + } else { + config.HashDB = &hashdb.Config{} // disable caching + } + triedb := trie.NewDatabase(diskdb, config) accTrie, _ := trie.NewStateTrie(trie.StateTrieID(types.EmptyRootHash), triedb) return &testHelper{ diskdb: diskdb, @@ -233,7 +251,12 @@ // - extra slots in the beginning // - extra slots in the middle // - extra slots in the end func TestGenerateExistentStateWithWrongStorage(t *testing.T) { - helper := newHelper() + testGenerateExistentStateWithWrongStorage(t, rawdb.HashScheme) + testGenerateExistentStateWithWrongStorage(t, rawdb.PathScheme) +} + +func testGenerateExistentStateWithWrongStorage(t *testing.T, scheme string) { + helper := newHelper(scheme)   // Account one, empty root but non-empty database helper.addAccount("acc-1", &types.StateAccount{Balance: big.NewInt(1), Root: types.EmptyRootHash, CodeHash: types.EmptyCodeHash.Bytes()}) @@ -325,7 +348,12 @@ // - miss accounts // - wrong accounts // - extra accounts func TestGenerateExistentStateWithWrongAccounts(t *testing.T) { - helper := newHelper() + testGenerateExistentStateWithWrongAccounts(t, rawdb.HashScheme) + testGenerateExistentStateWithWrongAccounts(t, rawdb.PathScheme) +} + +func testGenerateExistentStateWithWrongAccounts(t *testing.T, scheme string) { + helper := newHelper(scheme)   helper.makeStorageTrie(hashData([]byte("acc-1")), []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}, true) helper.makeStorageTrie(hashData([]byte("acc-2")), []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}, true) @@ -380,10 +408,15 @@ // Tests that snapshot generation errors out correctly in case of a missing trie // node in the account trie. func TestGenerateCorruptAccountTrie(t *testing.T) { + testGenerateCorruptAccountTrie(t, rawdb.HashScheme) + testGenerateCorruptAccountTrie(t, rawdb.PathScheme) +} + +func testGenerateCorruptAccountTrie(t *testing.T, scheme string) { // We can't use statedb to make a test trie (circular dependency), so make // a fake one manually. We're going with a small account trie of 3 accounts, // without any storage slots to keep the test smaller. - helper := newHelper() + helper := newHelper(scheme)   helper.addTrieAccount("acc-1", &types.StateAccount{Balance: big.NewInt(1), Root: types.EmptyRootHash, CodeHash: types.EmptyCodeHash.Bytes()}) // 0xc7a30f39aff471c95d8a837497ad0e49b65be475cc0953540f80cfcdbdcd9074 helper.addTrieAccount("acc-2", &types.StateAccount{Balance: big.NewInt(2), Root: types.EmptyRootHash, CodeHash: types.EmptyCodeHash.Bytes()}) // 0x65145f923027566669a1ae5ccac66f945b55ff6eaeb17d2ea8e048b7d381f2d7 @@ -391,9 +424,11 @@ helper.addTrieAccount("acc-3", &types.StateAccount{Balance: big.NewInt(3), Root: types.EmptyRootHash, CodeHash: types.EmptyCodeHash.Bytes()}) // 0x19ead688e907b0fab07176120dceec244a72aff2f0aa51e8b827584e378772f4   root := helper.Commit() // Root: 0xa04693ea110a31037fb5ee814308a6f1d76bdab0b11676bdf4541d2de55ba978   - // Delete an account trie leaf and ensure the generator chokes - helper.triedb.Commit(root, false) - helper.diskdb.Delete(common.HexToHash("0x65145f923027566669a1ae5ccac66f945b55ff6eaeb17d2ea8e048b7d381f2d7").Bytes()) + // Delete an account trie node and ensure the generator chokes + targetPath := []byte{0xc} + targetHash := common.HexToHash("0x65145f923027566669a1ae5ccac66f945b55ff6eaeb17d2ea8e048b7d381f2d7") + + rawdb.DeleteTrieNode(helper.diskdb, common.Hash{}, targetPath, targetHash, scheme)   snap := generateSnapshot(helper.diskdb, helper.triedb, 16, root) select { @@ -414,11 +449,19 @@ // Tests that snapshot generation errors out correctly in case of a missing root // trie node for a storage trie. It's similar to internal corruption but it is // handled differently inside the generator. func TestGenerateMissingStorageTrie(t *testing.T) { + testGenerateMissingStorageTrie(t, rawdb.HashScheme) + testGenerateMissingStorageTrie(t, rawdb.PathScheme) +} + +func testGenerateMissingStorageTrie(t *testing.T, scheme string) { // We can't use statedb to make a test trie (circular dependency), so make // a fake one manually. We're going with a small account trie of 3 accounts, // two of which also has the same 3-slot storage trie attached. - helper := newHelper() - + var ( + acc1 = hashData([]byte("acc-1")) + acc3 = hashData([]byte("acc-3")) + helper = newHelper(scheme) + ) stRoot := helper.makeStorageTrie(hashData([]byte("acc-1")), []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}, true) // 0xddefcd9376dd029653ef384bd2f0a126bb755fe84fdcc9e7cf421ba454f2bc67 helper.addTrieAccount("acc-1", &types.StateAccount{Balance: big.NewInt(1), Root: stRoot, CodeHash: types.EmptyCodeHash.Bytes()}) // 0x9250573b9c18c664139f3b6a7a8081b7d8f8916a8fcc5d94feec6c29f5fd4e9e helper.addTrieAccount("acc-2", &types.StateAccount{Balance: big.NewInt(2), Root: types.EmptyRootHash, CodeHash: types.EmptyCodeHash.Bytes()}) // 0x65145f923027566669a1ae5ccac66f945b55ff6eaeb17d2ea8e048b7d381f2d7 @@ -427,8 +470,9 @@ helper.addTrieAccount("acc-3", &types.StateAccount{Balance: big.NewInt(3), Root: stRoot, CodeHash: types.EmptyCodeHash.Bytes()}) // 0x50815097425d000edfc8b3a4a13e175fc2bdcfee8bdfbf2d1ff61041d3c235b2   root := helper.Commit()   - // Delete a storage trie root and ensure the generator chokes - helper.diskdb.Delete(stRoot.Bytes()) + // Delete storage trie root of account one and three. + rawdb.DeleteTrieNode(helper.diskdb, acc1, nil, stRoot, scheme) + rawdb.DeleteTrieNode(helper.diskdb, acc3, nil, stRoot, scheme)   snap := generateSnapshot(helper.diskdb, helper.triedb, 16, root) select { @@ -448,10 +492,15 @@ // Tests that snapshot generation errors out correctly in case of a missing trie // node in a storage trie. func TestGenerateCorruptStorageTrie(t *testing.T) { + testGenerateCorruptStorageTrie(t, rawdb.HashScheme) + testGenerateCorruptStorageTrie(t, rawdb.PathScheme) +} + +func testGenerateCorruptStorageTrie(t *testing.T, scheme string) { // We can't use statedb to make a test trie (circular dependency), so make // a fake one manually. We're going with a small account trie of 3 accounts, // two of which also has the same 3-slot storage trie attached. - helper := newHelper() + helper := newHelper(scheme)   stRoot := helper.makeStorageTrie(hashData([]byte("acc-1")), []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}, true) // 0xddefcd9376dd029653ef384bd2f0a126bb755fe84fdcc9e7cf421ba454f2bc67 helper.addTrieAccount("acc-1", &types.StateAccount{Balance: big.NewInt(1), Root: stRoot, CodeHash: types.EmptyCodeHash.Bytes()}) // 0x9250573b9c18c664139f3b6a7a8081b7d8f8916a8fcc5d94feec6c29f5fd4e9e @@ -461,8 +510,11 @@ helper.addTrieAccount("acc-3", &types.StateAccount{Balance: big.NewInt(3), Root: stRoot, CodeHash: types.EmptyCodeHash.Bytes()}) // 0x50815097425d000edfc8b3a4a13e175fc2bdcfee8bdfbf2d1ff61041d3c235b2   root := helper.Commit()   - // Delete a storage trie leaf and ensure the generator chokes - helper.diskdb.Delete(common.HexToHash("0x18a0f4d79cff4459642dd7604f303886ad9d77c30cf3d7d7cedb3a693ab6d371").Bytes()) + // Delete a node in the storage trie. + targetPath := []byte{0x4} + targetHash := common.HexToHash("0x18a0f4d79cff4459642dd7604f303886ad9d77c30cf3d7d7cedb3a693ab6d371") + rawdb.DeleteTrieNode(helper.diskdb, hashData([]byte("acc-1")), targetPath, targetHash, scheme) + rawdb.DeleteTrieNode(helper.diskdb, hashData([]byte("acc-3")), targetPath, targetHash, scheme)   snap := generateSnapshot(helper.diskdb, helper.triedb, 16, root) select { @@ -481,7 +533,12 @@ }   // Tests that snapshot generation when an extra account with storage exists in the snap state. func TestGenerateWithExtraAccounts(t *testing.T) { - helper := newHelper() + testGenerateWithExtraAccounts(t, rawdb.HashScheme) + testGenerateWithExtraAccounts(t, rawdb.PathScheme) +} + +func testGenerateWithExtraAccounts(t *testing.T, scheme string) { + helper := newHelper(scheme) { // Account one in the trie stRoot := helper.makeStorageTrie(hashData([]byte("acc-1")), @@ -549,10 +606,15 @@ }   // Tests that snapshot generation when an extra account with storage exists in the snap state. func TestGenerateWithManyExtraAccounts(t *testing.T) { + testGenerateWithManyExtraAccounts(t, rawdb.HashScheme) + testGenerateWithManyExtraAccounts(t, rawdb.PathScheme) +} + +func testGenerateWithManyExtraAccounts(t *testing.T, scheme string) { if false { enableLogging() } - helper := newHelper() + helper := newHelper(scheme) { // Account one in the trie stRoot := helper.makeStorageTrie(hashData([]byte("acc-1")), @@ -605,11 +667,16 @@ // The trie has a lot of deletions. // So in trie, we iterate 2 entries 0x03, 0x07. We create the 0x07 in the database and abort the procedure, because the trie is exhausted. // But in the database, we still have the stale storage slots 0x04, 0x05. They are not iterated yet, but the procedure is finished. func TestGenerateWithExtraBeforeAndAfter(t *testing.T) { + testGenerateWithExtraBeforeAndAfter(t, rawdb.HashScheme) + testGenerateWithExtraBeforeAndAfter(t, rawdb.PathScheme) +} + +func testGenerateWithExtraBeforeAndAfter(t *testing.T, scheme string) { accountCheckRange = 3 if false { enableLogging() } - helper := newHelper() + helper := newHelper(scheme) { acc := &types.StateAccount{Balance: big.NewInt(1), Root: types.EmptyRootHash, CodeHash: types.EmptyCodeHash.Bytes()} val, _ := rlp.EncodeToBytes(acc) @@ -642,11 +709,16 @@ // TestGenerateWithMalformedSnapdata tests what happes if we have some junk // in the snapshot database, which cannot be parsed back to an account func TestGenerateWithMalformedSnapdata(t *testing.T) { + testGenerateWithMalformedSnapdata(t, rawdb.HashScheme) + testGenerateWithMalformedSnapdata(t, rawdb.PathScheme) +} + +func testGenerateWithMalformedSnapdata(t *testing.T, scheme string) { accountCheckRange = 3 if false { enableLogging() } - helper := newHelper() + helper := newHelper(scheme) { acc := &types.StateAccount{Balance: big.NewInt(1), Root: types.EmptyRootHash, CodeHash: types.EmptyCodeHash.Bytes()} val, _ := rlp.EncodeToBytes(acc) @@ -679,10 +751,15 @@ } }   func TestGenerateFromEmptySnap(t *testing.T) { + testGenerateFromEmptySnap(t, rawdb.HashScheme) + testGenerateFromEmptySnap(t, rawdb.PathScheme) +} + +func testGenerateFromEmptySnap(t *testing.T, scheme string) { //enableLogging() accountCheckRange = 10 storageCheckRange = 20 - helper := newHelper() + helper := newHelper(scheme) // Add 1K accounts to the trie for i := 0; i < 400; i++ { stRoot := helper.makeStorageTrie(hashData([]byte(fmt.Sprintf("acc-%d", i))), []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}, true) @@ -714,8 +791,13 @@ // trie: 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08 // This hits a case where the snap verification passes, but there are more elements in the trie // which we must also add. func TestGenerateWithIncompleteStorage(t *testing.T) { + testGenerateWithIncompleteStorage(t, rawdb.HashScheme) + testGenerateWithIncompleteStorage(t, rawdb.PathScheme) +} + +func testGenerateWithIncompleteStorage(t *testing.T, scheme string) { storageCheckRange = 4 - helper := newHelper() + helper := newHelper(scheme) stKeys := []string{"1", "2", "3", "4", "5", "6", "7", "8"} stVals := []string{"v1", "v2", "v3", "v4", "v5", "v6", "v7", "v8"} // We add 8 accounts, each one is missing exactly one of the storage slots. This means @@ -813,7 +895,12 @@ // the storage data is existent while the corresponding account data is missing. // // This test will populate some dangling storages to see if they can be cleaned up. func TestGenerateCompleteSnapshotWithDanglingStorage(t *testing.T) { - var helper = newHelper() + testGenerateCompleteSnapshotWithDanglingStorage(t, rawdb.HashScheme) + testGenerateCompleteSnapshotWithDanglingStorage(t, rawdb.PathScheme) +} + +func testGenerateCompleteSnapshotWithDanglingStorage(t *testing.T, scheme string) { + var helper = newHelper(scheme)   stRoot := helper.makeStorageTrie(hashData([]byte("acc-1")), []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}, true) helper.addAccount("acc-1", &types.StateAccount{Balance: big.NewInt(1), Root: stRoot, CodeHash: types.EmptyCodeHash.Bytes()}) @@ -848,7 +935,12 @@ // the storage data is existent while the corresponding account data is missing. // // This test will populate some dangling storages to see if they can be cleaned up. func TestGenerateBrokenSnapshotWithDanglingStorage(t *testing.T) { - var helper = newHelper() + testGenerateBrokenSnapshotWithDanglingStorage(t, rawdb.HashScheme) + testGenerateBrokenSnapshotWithDanglingStorage(t, rawdb.PathScheme) +} + +func testGenerateBrokenSnapshotWithDanglingStorage(t *testing.T, scheme string) { + var helper = newHelper(scheme)   stRoot := helper.makeStorageTrie(hashData([]byte("acc-1")), []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}, true) helper.addTrieAccount("acc-1", &types.StateAccount{Balance: big.NewInt(1), Root: stRoot, CodeHash: types.EmptyCodeHash.Bytes()})
diff --git ethereum/go-ethereum/core/state/snapshot/snapshot.go taikoxyz/taiko-geth/core/state/snapshot/snapshot.go index efc0fc26afdf15f52cd0ed6971cca8da774ed743..e30a0005ccce86abfb9d6c6c07ad0f493ec7608f 100644 --- ethereum/go-ethereum/core/state/snapshot/snapshot.go +++ taikoxyz/taiko-geth/core/state/snapshot/snapshot.go @@ -564,7 +564,7 @@ // Ensure we don't delete too much data blindly (contract can be // huge). It's ok to flush, the root will go missing in case of a // crash and we'll detect and regenerate the snapshot. - if batch.ValueSize() > ethdb.IdealBatchSize { + if batch.ValueSize() > 64*1024*1024 { if err := batch.Write(); err != nil { log.Crit("Failed to write storage deletions", "err", err) } @@ -590,7 +590,7 @@ // Ensure we don't write too much data blindly. It's ok to flush, the // root will go missing in case of a crash and we'll detect and regen // the snapshot. - if batch.ValueSize() > ethdb.IdealBatchSize { + if batch.ValueSize() > 64*1024*1024 { if err := batch.Write(); err != nil { log.Crit("Failed to write storage deletions", "err", err) } @@ -852,3 +852,21 @@ defer t.lock.Unlock()   return t.diskRoot() } + +// Size returns the memory usage of the diff layers above the disk layer and the +// dirty nodes buffered in the disk layer. Currently, the implementation uses a +// special diff layer (the first) as an aggregator simulating a dirty buffer, so +// the second return will always be 0. However, this will be made consistent with +// the pathdb, which will require a second return. +func (t *Tree) Size() (diffs common.StorageSize, buf common.StorageSize) { + t.lock.RLock() + defer t.lock.RUnlock() + + var size common.StorageSize + for _, layer := range t.layers { + if layer, ok := layer.(*diffLayer); ok { + size += common.StorageSize(layer.memory) + } + } + return size, 0 +}
diff --git ethereum/go-ethereum/core/txpool/blobpool/blobpool.go taikoxyz/taiko-geth/core/txpool/blobpool/blobpool.go index c0dd6e8acc90fc19eca11d2a423736fe49f36b29..32c6c0e8feeff9db0bf2ebaedb9869decc82b336 100644 --- ethereum/go-ethereum/core/txpool/blobpool/blobpool.go +++ taikoxyz/taiko-geth/core/txpool/blobpool/blobpool.go @@ -19,6 +19,7 @@ package blobpool   import ( "container/heap" + "errors" "fmt" "math" "math/big" @@ -35,7 +36,6 @@ "github.com/ethereum/go-ethereum/core" "github.com/ethereum/go-ethereum/core/state" "github.com/ethereum/go-ethereum/core/txpool" "github.com/ethereum/go-ethereum/core/types" - "github.com/ethereum/go-ethereum/crypto/kzg4844" "github.com/ethereum/go-ethereum/event" "github.com/ethereum/go-ethereum/log" "github.com/ethereum/go-ethereum/metrics" @@ -53,7 +53,7 @@ // maxBlobsPerTransaction is the maximum number of blobs a single transaction // is allowed to contain. Whilst the spec states it's unlimited, the block // data slots are protocol bound, which implicitly also limit this. - maxBlobsPerTransaction = params.BlobTxMaxBlobGasPerBlock / params.BlobTxBlobGasPerBlob + maxBlobsPerTransaction = params.MaxBlobGasPerBlock / params.BlobTxBlobGasPerBlob   // txAvgSize is an approximate byte size of a transaction metadata to avoid // tiny overflows causing all txs to move a shelf higher, wasting disk space. @@ -83,16 +83,6 @@ // but not yet finalized transaction blobs. limboedTransactionStore = "limbo" )   -// blobTx is a wrapper around types.BlobTx which also contains the literal blob -// data along with all the transaction metadata. -type blobTx struct { - Tx *types.Transaction - - Blobs []kzg4844.Blob - Commits []kzg4844.Commitment - Proofs []kzg4844.Proof -} - // blobTxMeta is the minimal subset of types.BlobTx necessary to validate and // schedule the blob transactions into the following blocks. Only ever add the // bare minimum needed fields to keep the size down (and thus number of entries @@ -107,6 +97,8 @@ costCap *uint256.Int // Needed to validate cumulative balance sufficiency execTipCap *uint256.Int // Needed to prioritize inclusion order across accounts and validate replacement price bump execFeeCap *uint256.Int // Needed to validate replacement price bump blobFeeCap *uint256.Int // Needed to validate replacement price bump + execGas uint64 // Needed to check inclusion validity before reading the blob + blobGas uint64 // Needed to check inclusion validity before reading the blob   basefeeJumps float64 // Absolute number of 1559 fee adjustments needed to reach the tx's fee cap blobfeeJumps float64 // Absolute number of 4844 fee adjustments needed to reach the tx's blob fee cap @@ -128,6 +120,8 @@ costCap: uint256.MustFromBig(tx.Cost()), execTipCap: uint256.MustFromBig(tx.GasTipCap()), execFeeCap: uint256.MustFromBig(tx.GasFeeCap()), blobFeeCap: uint256.MustFromBig(tx.BlobGasFeeCap()), + execGas: tx.Gas(), + blobGas: tx.BlobGas(), } meta.basefeeJumps = dynamicFeeJumps(meta.execFeeCap) meta.blobfeeJumps = dynamicFeeJumps(meta.blobFeeCap) @@ -317,8 +311,8 @@ index map[common.Address][]*blobTxMeta // Blob transactions grouped by accounts, sorted by nonce spent map[common.Address]*uint256.Int // Expenditure tracking for individual accounts evict *evictHeap // Heap of cheapest accounts for eviction when full   - eventFeed event.Feed // Event feed to send out new tx events on pool inclusion - eventScope event.SubscriptionScope // Event scope to track and mass unsubscribe on termination + discoverFeed event.Feed // Event feed to send out new tx events on pool discovery (reorg excluded) + insertFeed event.Feed // Event feed to send out new tx events on pool inclusion (reorg included)   lock sync.RWMutex // Mutex protecting the pool during reorg handling } @@ -365,7 +359,13 @@ if err := os.MkdirAll(limbodir, 0700); err != nil { return err } } + // Initialize the state with head block, or fallback to empty one in + // case the head state is not available(might occur when node is not + // fully synced). state, err := p.chain.StateAt(head.Root) + if err != nil { + state, err = p.chain.StateAt(types.EmptyRootHash) + } if err != nil { return err } @@ -440,8 +440,6 @@ } if err := p.store.Close(); err != nil { errs = append(errs, err) } - p.eventScope.Close() - switch { case errs == nil: return nil @@ -455,22 +453,27 @@ // parseTransaction is a callback method on pool creation that gets called for // each transaction on disk to create the in-memory metadata index. func (p *BlobPool) parseTransaction(id uint64, size uint32, blob []byte) error { - item := new(blobTx) - if err := rlp.DecodeBytes(blob, item); err != nil { + tx := new(types.Transaction) + if err := rlp.DecodeBytes(blob, tx); err != nil { // This path is impossible unless the disk data representation changes // across restarts. For that ever unprobable case, recover gracefully // by ignoring this data entry. log.Error("Failed to decode blob pool entry", "id", id, "err", err) return err } - meta := newBlobTxMeta(id, size, item.Tx) + if tx.BlobTxSidecar() == nil { + log.Error("Missing sidecar in blob pool entry", "id", id, "hash", tx.Hash()) + return errors.New("missing blob sidecar") + } + + meta := newBlobTxMeta(id, size, tx)   - sender, err := p.signer.Sender(item.Tx) + sender, err := p.signer.Sender(tx) if err != nil { // This path is impossible unless the signature validity changes across // restarts. For that ever unprobable case, recover gracefully by ignoring // this data entry. - log.Error("Failed to recover blob tx sender", "id", id, "hash", item.Tx.Hash(), "err", err) + log.Error("Failed to recover blob tx sender", "id", id, "hash", tx.Hash(), "err", err) return err } if _, ok := p.index[sender]; !ok { @@ -718,17 +721,17 @@ if err != nil { log.Error("Blobs missing for included transaction", "from", addr, "nonce", nonce, "id", id, "err", err) return } - item := new(blobTx) - if err = rlp.DecodeBytes(data, item); err != nil { + var tx types.Transaction + if err = rlp.DecodeBytes(data, &tx); err != nil { log.Error("Blobs corrupted for included transaction", "from", addr, "nonce", nonce, "id", id, "err", err) return } - block, ok := inclusions[item.Tx.Hash()] + block, ok := inclusions[tx.Hash()] if !ok { log.Warn("Blob transaction swapped out by signer", "from", addr, "nonce", nonce, "id", id) return } - if err := p.limbo.push(item.Tx.Hash(), block, item.Blobs, item.Commits, item.Proofs); err != nil { + if err := p.limbo.push(&tx, block); err != nil { log.Warn("Failed to offload blob tx into limbo", "err", err) return } @@ -757,14 +760,20 @@ // Run the reorg between the old and new head and figure out which accounts // need to be rechecked and which transactions need to be readded if reinject, inclusions := p.reorg(oldHead, newHead); reinject != nil { + var adds []*types.Transaction for addr, txs := range reinject { // Blindly push all the lost transactions back into the pool for _, tx := range txs { - p.reinject(addr, tx) + if err := p.reinject(addr, tx.Hash()); err == nil { + adds = append(adds, tx.WithoutBlobTxSidecar()) + } } // Recheck the account's pooled transactions to drop included and // invalidated one p.recheck(addr, inclusions) + } + if len(adds) > 0 { + p.insertFeed.Send(core.NewTxsEvent{Txs: adds}) } } // Flush out any blobs from limbo that are older than the latest finality @@ -920,32 +929,35 @@ // // Note, the method will not initialize the eviction cache values as those will // be done once for all transactions belonging to an account after all individual // transactions are injected back into the pool. -func (p *BlobPool) reinject(addr common.Address, tx *types.Transaction) { +func (p *BlobPool) reinject(addr common.Address, txhash common.Hash) error { // Retrieve the associated blob from the limbo. Without the blobs, we cannot // add the transaction back into the pool as it is not mineable. - blobs, commits, proofs, err := p.limbo.pull(tx.Hash()) + tx, err := p.limbo.pull(txhash) if err != nil { log.Error("Blobs unavailable, dropping reorged tx", "err", err) - return + return err } - // Serialize the transaction back into the primary datastore - blob, err := rlp.EncodeToBytes(&blobTx{Tx: tx, Blobs: blobs, Commits: commits, Proofs: proofs}) + // TODO: seems like an easy optimization here would be getting the serialized tx + // from limbo instead of re-serializing it here. + + // Serialize the transaction back into the primary datastore. + blob, err := rlp.EncodeToBytes(tx) if err != nil { log.Error("Failed to encode transaction for storage", "hash", tx.Hash(), "err", err) - return + return err } id, err := p.store.Put(blob) if err != nil { log.Error("Failed to write transaction into storage", "hash", tx.Hash(), "err", err) - return + return err } + // Update the indixes and metrics meta := newBlobTxMeta(id, p.store.Size(id), tx) - if _, ok := p.index[addr]; !ok { if err := p.reserve(addr, true); err != nil { log.Warn("Failed to reserve account for blob pool", "tx", tx.Hash(), "from", addr, "err", err) - return + return err } p.index[addr] = []*blobTxMeta{meta} p.spent[addr] = meta.costCap @@ -956,6 +968,7 @@ p.spent[addr] = new(uint256.Int).Add(p.spent[addr], meta.costCap) } p.lookup[meta.hash] = meta.id p.stored += uint64(meta.size) + return nil }   // SetGasTip implements txpool.SubPool, allowing the blob pool's gas requirements @@ -1023,7 +1036,7 @@ }   // validateTx checks whether a transaction is valid according to the consensus // rules and adheres to some heuristic limits of the local node (price and size). -func (p *BlobPool) validateTx(tx *types.Transaction, blobs []kzg4844.Blob, commits []kzg4844.Commitment, proofs []kzg4844.Proof) error { +func (p *BlobPool) validateTx(tx *types.Transaction) error { // Ensure the transaction adheres to basic pool filters (type, size, tip) and // consensus rules baseOpts := &txpool.ValidationOptions{ @@ -1032,7 +1045,7 @@ Accept: 1 << types.BlobTxType, MaxSize: txMaxSize, MinTip: p.gasTip.ToBig(), } - if err := txpool.ValidateTransaction(tx, blobs, commits, proofs, p.head, p.signer, baseOpts); err != nil { + if err := txpool.ValidateTransaction(tx, p.head, p.signer, baseOpts); err != nil { return err } // Ensure the transaction adheres to the stateful pool filters (nonce, balance) @@ -1117,7 +1130,7 @@ return ok }   // Get returns a transaction if it is contained in the pool, or nil otherwise. -func (p *BlobPool) Get(hash common.Hash) *txpool.Transaction { +func (p *BlobPool) Get(hash common.Hash) *types.Transaction { // Track the amount of time waiting to retrieve a fully resolved blob tx from // the pool and the amount of time actually spent on pulling the data from disk. getStart := time.Now() @@ -1139,32 +1152,37 @@ if err != nil { log.Error("Tracked blob transaction missing from store", "hash", hash, "id", id, "err", err) return nil } - item := new(blobTx) + item := new(types.Transaction) if err = rlp.DecodeBytes(data, item); err != nil { log.Error("Blobs corrupted for traced transaction", "hash", hash, "id", id, "err", err) return nil } - return &txpool.Transaction{ - Tx: item.Tx, - BlobTxBlobs: item.Blobs, - BlobTxCommits: item.Commits, - BlobTxProofs: item.Proofs, - } + return item }   // Add inserts a set of blob transactions into the pool if they pass validation (both // consensus validity and pool restictions). -func (p *BlobPool) Add(txs []*txpool.Transaction, local bool, sync bool) []error { - errs := make([]error, len(txs)) +func (p *BlobPool) Add(txs []*types.Transaction, local bool, sync bool) []error { + var ( + adds = make([]*types.Transaction, 0, len(txs)) + errs = make([]error, len(txs)) + ) for i, tx := range txs { - errs[i] = p.add(tx.Tx, tx.BlobTxBlobs, tx.BlobTxCommits, tx.BlobTxProofs) + errs[i] = p.add(tx) + if errs[i] == nil { + adds = append(adds, tx.WithoutBlobTxSidecar()) + } + } + if len(adds) > 0 { + p.discoverFeed.Send(core.NewTxsEvent{Txs: adds}) + p.insertFeed.Send(core.NewTxsEvent{Txs: adds}) } return errs }   // Add inserts a new blob transaction into the pool if it passes validation (both // consensus validity and pool restictions). -func (p *BlobPool) add(tx *types.Transaction, blobs []kzg4844.Blob, commits []kzg4844.Commitment, proofs []kzg4844.Proof) (err error) { +func (p *BlobPool) add(tx *types.Transaction) (err error) { // The blob pool blocks on adding a transaction. This is because blob txs are // only even pulled form the network, so this method will act as the overload // protection for fetches. @@ -1178,7 +1196,7 @@ addtimeHist.Update(time.Since(start).Nanoseconds()) }(time.Now())   // Ensure the transaction is valid from all perspectives - if err := p.validateTx(tx, blobs, commits, proofs); err != nil { + if err := p.validateTx(tx); err != nil { log.Trace("Transaction validation failed", "hash", tx.Hash(), "err", err) return err } @@ -1203,7 +1221,7 @@ }() } // Transaction permitted into the pool from a nonce and cost perspective, // insert it into the database and update the indices - blob, err := rlp.EncodeToBytes(&blobTx{Tx: tx, Blobs: blobs, Commits: commits, Proofs: proofs}) + blob, err := rlp.EncodeToBytes(tx) if err != nil { log.Error("Failed to encode transaction for storage", "hash", tx.Hash(), "err", err) return err @@ -1385,6 +1403,8 @@ Hash: tx.hash, Time: time.Now(), // TODO(karalabe): Maybe save these and use that? GasFeeCap: tx.execFeeCap.ToBig(), GasTipCap: tx.execTipCap.ToBig(), + Gas: tx.execGas, + BlobGas: tx.blobGas, }) } if len(lazies) > 0 { @@ -1469,10 +1489,14 @@ limboDatarealGauge.Update(int64(datareal)) limboSlotusedGauge.Update(int64(slotused)) }   -// SubscribeTransactions registers a subscription of NewTxsEvent and -// starts sending event to the given channel. -func (p *BlobPool) SubscribeTransactions(ch chan<- core.NewTxsEvent) event.Subscription { - return p.eventScope.Track(p.eventFeed.Subscribe(ch)) +// SubscribeTransactions registers a subscription for new transaction events, +// supporting feeding only newly seen or also resurrected transactions. +func (p *BlobPool) SubscribeTransactions(ch chan<- core.NewTxsEvent, reorgs bool) event.Subscription { + if reorgs { + return p.insertFeed.Subscribe(ch) + } else { + return p.discoverFeed.Subscribe(ch) + } }   // Nonce returns the next nonce of an account, with all transactions executable
diff --git ethereum/go-ethereum/core/txpool/blobpool/blobpool_test.go taikoxyz/taiko-geth/core/txpool/blobpool/blobpool_test.go index 78a5039b5b13d256b122abd91428d2eccf4ee683..8914301e14c32648498077d51ee1d3ddc5484734 100644 --- ethereum/go-ethereum/core/txpool/blobpool/blobpool_test.go +++ taikoxyz/taiko-geth/core/txpool/blobpool/blobpool_test.go @@ -193,8 +193,8 @@ // makeTx is a utility method to construct a random blob transaction and sign it // with a valid key, only setting the interesting fields from the perspective of // the blob pool. func makeTx(nonce uint64, gasTipCap uint64, gasFeeCap uint64, blobFeeCap uint64, key *ecdsa.PrivateKey) *types.Transaction { - tx, _ := types.SignNewTx(key, types.LatestSigner(testChainConfig), makeUnsignedTx(nonce, gasTipCap, gasFeeCap, blobFeeCap)) - return tx + blobtx := makeUnsignedTx(nonce, gasTipCap, gasFeeCap, blobFeeCap) + return types.MustSignNewTx(key, types.LatestSigner(testChainConfig), blobtx) }   // makeUnsignedTx is a utility method to construct a random blob tranasaction @@ -209,6 +209,11 @@ Gas: 21000, BlobFeeCap: uint256.NewInt(blobFeeCap), BlobHashes: []common.Hash{emptyBlobVHash}, Value: uint256.NewInt(100), + Sidecar: &types.BlobTxSidecar{ + Blobs: []kzg4844.Blob{emptyBlob}, + Commitments: []kzg4844.Commitment{emptyBlobCommit}, + Proofs: []kzg4844.Proof{emptyBlobProof}, + }, } }   @@ -341,7 +346,7 @@ V: new(uint256.Int), R: new(uint256.Int), S: new(uint256.Int), }) - blob, _ := rlp.EncodeToBytes(&blobTx{Tx: tx}) + blob, _ := rlp.EncodeToBytes(tx) badsig, _ := store.Put(blob)   // Insert a sequence of transactions with a nonce gap in between to verify @@ -354,7 +359,7 @@ gapped = make(map[uint64]struct{}) ) for _, nonce := range []uint64{0, 1, 3, 4, 6, 7} { // first gap at #2, another at #5 tx := makeTx(nonce, 1, 1, 1, gapper) - blob, _ := rlp.EncodeToBytes(&blobTx{Tx: tx}) + blob, _ := rlp.EncodeToBytes(tx)   id, _ := store.Put(blob) if nonce < 2 { @@ -371,7 +376,7 @@ dangling = make(map[uint64]struct{}) ) for _, nonce := range []uint64{1, 2, 3} { // first gap at #0, all set dangling tx := makeTx(nonce, 1, 1, 1, dangler) - blob, _ := rlp.EncodeToBytes(&blobTx{Tx: tx}) + blob, _ := rlp.EncodeToBytes(tx)   id, _ := store.Put(blob) dangling[id] = struct{}{} @@ -384,7 +389,7 @@ filled = make(map[uint64]struct{}) ) for _, nonce := range []uint64{0, 1, 2} { // account nonce at 3, all set filled tx := makeTx(nonce, 1, 1, 1, filler) - blob, _ := rlp.EncodeToBytes(&blobTx{Tx: tx}) + blob, _ := rlp.EncodeToBytes(tx)   id, _ := store.Put(blob) filled[id] = struct{}{} @@ -397,7 +402,7 @@ overlapped = make(map[uint64]struct{}) ) for _, nonce := range []uint64{0, 1, 2, 3} { // account nonce at 2, half filled tx := makeTx(nonce, 1, 1, 1, overlapper) - blob, _ := rlp.EncodeToBytes(&blobTx{Tx: tx}) + blob, _ := rlp.EncodeToBytes(tx)   id, _ := store.Put(blob) if nonce >= 2 { @@ -419,7 +424,7 @@ tx = makeTx(uint64(i), 0, 0, 0, underpayer) } else { tx = makeTx(uint64(i), 1, 1, 1, underpayer) } - blob, _ := rlp.EncodeToBytes(&blobTx{Tx: tx}) + blob, _ := rlp.EncodeToBytes(tx)   id, _ := store.Put(blob) underpaid[id] = struct{}{} @@ -438,7 +443,7 @@ tx = makeTx(uint64(i), 0, 0, 0, outpricer) } else { tx = makeTx(uint64(i), 1, 1, 1, outpricer) } - blob, _ := rlp.EncodeToBytes(&blobTx{Tx: tx}) + blob, _ := rlp.EncodeToBytes(tx)   id, _ := store.Put(blob) if i < 2 { @@ -460,7 +465,7 @@ tx = makeTx(nonce, 1, 100, 1, exceeder) } else { tx = makeTx(nonce, 1, 1, 1, exceeder) } - blob, _ := rlp.EncodeToBytes(&blobTx{Tx: tx}) + blob, _ := rlp.EncodeToBytes(tx)   id, _ := store.Put(blob) exceeded[id] = struct{}{} @@ -478,7 +483,7 @@ tx = makeTx(nonce, 1, 100, 1, overdrafter) } else { tx = makeTx(nonce, 1, 1, 1, overdrafter) } - blob, _ := rlp.EncodeToBytes(&blobTx{Tx: tx}) + blob, _ := rlp.EncodeToBytes(tx)   id, _ := store.Put(blob) if nonce < 1 { @@ -494,7 +499,7 @@ overcapper, _ = crypto.GenerateKey() overcapped = make(map[uint64]struct{}) ) for nonce := uint64(0); nonce < maxTxsPerAccount+3; nonce++ { - blob, _ := rlp.EncodeToBytes(&blobTx{Tx: makeTx(nonce, 1, 1, 1, overcapper)}) + blob, _ := rlp.EncodeToBytes(makeTx(nonce, 1, 1, 1, overcapper))   id, _ := store.Put(blob) if nonce < maxTxsPerAccount { @@ -625,7 +630,7 @@ totalSpent = uint256.NewInt(21000*(100+90+200+10+80+300) + blobSize*(55+66+77+33+22+11) + 100*6) // 21000 gas x price + 128KB x blobprice + value ) for _, i := range []int{5, 3, 4, 2, 0, 1} { // Randomize the tx insertion order to force sorting on load tx := makeTx(uint64(i), txExecTipCaps[i], txExecFeeCaps[i], txBlobFeeCaps[i], key) - blob, _ := rlp.EncodeToBytes(&blobTx{Tx: tx}) + blob, _ := rlp.EncodeToBytes(tx) store.Put(blob) } store.Close() @@ -718,9 +723,9 @@ tx1 = makeTx(0, 1, 1000, 90, key1) tx2 = makeTx(0, 1, 800, 70, key2) tx3 = makeTx(0, 1, 1500, 110, key3)   - blob1, _ = rlp.EncodeToBytes(&blobTx{Tx: tx1}) - blob2, _ = rlp.EncodeToBytes(&blobTx{Tx: tx2}) - blob3, _ = rlp.EncodeToBytes(&blobTx{Tx: tx3}) + blob1, _ = rlp.EncodeToBytes(tx1) + blob2, _ = rlp.EncodeToBytes(tx2) + blob3, _ = rlp.EncodeToBytes(tx3)   heapOrder = []common.Address{addr2, addr1, addr3} heapIndex = map[common.Address]int{addr2: 0, addr1: 1, addr3: 2} @@ -794,9 +799,9 @@ tx1 = makeTx(0, 1, 1000, 100, key1) tx2 = makeTx(0, 1, 800, 70, key2) tx3 = makeTx(0, 1, 1500, 110, key3)   - blob1, _ = rlp.EncodeToBytes(&blobTx{Tx: tx1, Blobs: []kzg4844.Blob{emptyBlob}, Commits: []kzg4844.Commitment{emptyBlobCommit}, Proofs: []kzg4844.Proof{emptyBlobProof}}) - blob2, _ = rlp.EncodeToBytes(&blobTx{Tx: tx2, Blobs: []kzg4844.Blob{emptyBlob}, Commits: []kzg4844.Commitment{emptyBlobCommit}, Proofs: []kzg4844.Proof{emptyBlobProof}}) - blob3, _ = rlp.EncodeToBytes(&blobTx{Tx: tx3, Blobs: []kzg4844.Blob{emptyBlob}, Commits: []kzg4844.Commitment{emptyBlobCommit}, Proofs: []kzg4844.Proof{emptyBlobProof}}) + blob1, _ = rlp.EncodeToBytes(tx1) + blob2, _ = rlp.EncodeToBytes(tx2) + blob3, _ = rlp.EncodeToBytes(tx3)   keep = []common.Address{addr1, addr3} drop = []common.Address{addr2} @@ -1210,10 +1215,8 @@ statedb.SetNonce(addrs[acc], seed.nonce)   // Sign the seed transactions and store them in the data store for _, tx := range seed.txs { - var ( - signed, _ = types.SignNewTx(keys[acc], types.LatestSigner(testChainConfig), tx) - blob, _ = rlp.EncodeToBytes(&blobTx{Tx: signed, Blobs: []kzg4844.Blob{emptyBlob}, Commits: []kzg4844.Commitment{emptyBlobCommit}, Proofs: []kzg4844.Proof{emptyBlobProof}}) - ) + signed := types.MustSignNewTx(keys[acc], types.LatestSigner(testChainConfig), tx) + blob, _ := rlp.EncodeToBytes(signed) store.Put(blob) } } @@ -1236,7 +1239,7 @@ // Add each transaction one by one, verifying the pool internals in between for j, add := range tt.adds { signed, _ := types.SignNewTx(keys[add.from], types.LatestSigner(testChainConfig), add.tx) - if err := pool.add(signed, []kzg4844.Blob{emptyBlob}, []kzg4844.Commitment{emptyBlobCommit}, []kzg4844.Proof{emptyBlobProof}); !errors.Is(err, add.err) { + if err := pool.add(signed); !errors.Is(err, add.err) { t.Errorf("test %d, tx %d: adding transaction error mismatch: have %v, want %v", i, j, err, add.err) } verifyPoolInternals(t, pool)
diff --git ethereum/go-ethereum/core/txpool/blobpool/evictheap.go taikoxyz/taiko-geth/core/txpool/blobpool/evictheap.go index 7607a911c15bf1540ec4eb0d2f0e49d3175a5d1d..df594099f79b655ac9785f2dac6750d3909f98b1 100644 --- ethereum/go-ethereum/core/txpool/blobpool/evictheap.go +++ taikoxyz/taiko-geth/core/txpool/blobpool/evictheap.go @@ -44,7 +44,7 @@ addrs []common.Address // Heap of addresses to retrieve the cheapest out of index map[common.Address]int // Indices into the heap for replacements }   -// newPriceHeap creates a new heap of cheapets accounts in the blob pool to evict +// newPriceHeap creates a new heap of cheapest accounts in the blob pool to evict // from in case of over saturation. func newPriceHeap(basefee *uint256.Int, blobfee *uint256.Int, index *map[common.Address][]*blobTxMeta) *evictHeap { heap := &evictHeap{
diff --git ethereum/go-ethereum/core/txpool/blobpool/limbo.go taikoxyz/taiko-geth/core/txpool/blobpool/limbo.go index 4cb5042c2bb5a416ea25b667b5b4520cf757b0b8..d1fe9c739477bce660141673d86dde1e896ddecc 100644 --- ethereum/go-ethereum/core/txpool/blobpool/limbo.go +++ taikoxyz/taiko-geth/core/txpool/blobpool/limbo.go @@ -21,7 +21,6 @@ "errors"   "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/core/types" - "github.com/ethereum/go-ethereum/crypto/kzg4844" "github.com/ethereum/go-ethereum/log" "github.com/ethereum/go-ethereum/rlp" "github.com/holiman/billy" @@ -31,12 +30,9 @@ // limboBlob is a wrapper around an opaque blobset that also contains the tx hash // to which it belongs as well as the block number in which it was included for // finality eviction. type limboBlob struct { - Owner common.Hash // Owner transaction's hash to support resurrecting reorged txs - Block uint64 // Block in which the blob transaction was included - - Blobs []kzg4844.Blob // The opaque blobs originally part of the transaction - Commits []kzg4844.Commitment // The commitments for the original blobs - Proofs []kzg4844.Proof // The proofs verifying the commitments + TxHash common.Hash // Owner transaction's hash to support resurrecting reorged txs + Block uint64 // Block in which the blob transaction was included + Tx *types.Transaction }   // limbo is a light, indexed database to temporarily store recently included @@ -98,19 +94,19 @@ // by ignoring this data entry. log.Error("Failed to decode blob limbo entry", "id", id, "err", err) return err } - if _, ok := l.index[item.Owner]; ok { + if _, ok := l.index[item.TxHash]; ok { // This path is impossible, unless due to a programming error a blob gets // inserted into the limbo which was already part of if. Recover gracefully // by ignoring this data entry. - log.Error("Dropping duplicate blob limbo entry", "owner", item.Owner, "id", id) + log.Error("Dropping duplicate blob limbo entry", "owner", item.TxHash, "id", id) return errors.New("duplicate blob") } - l.index[item.Owner] = id + l.index[item.TxHash] = id   if _, ok := l.groups[item.Block]; !ok { l.groups[item.Block] = make(map[uint64]common.Hash) } - l.groups[item.Block][id] = item.Owner + l.groups[item.Block][id] = item.TxHash   return nil } @@ -139,15 +135,15 @@ }   // push stores a new blob transaction into the limbo, waiting until finality for // it to be automatically evicted. -func (l *limbo) push(tx common.Hash, block uint64, blobs []kzg4844.Blob, commits []kzg4844.Commitment, proofs []kzg4844.Proof) error { +func (l *limbo) push(tx *types.Transaction, block uint64) error { // If the blobs are already tracked by the limbo, consider it a programming // error. There's not much to do against it, but be loud. - if _, ok := l.index[tx]; ok { + if _, ok := l.index[tx.Hash()]; ok { log.Error("Limbo cannot push already tracked blobs", "tx", tx) return errors.New("already tracked blob transaction") } - if err := l.setAndIndex(tx, block, blobs, commits, proofs); err != nil { - log.Error("Failed to set and index liboed blobs", "tx", tx, "err", err) + if err := l.setAndIndex(tx, block); err != nil { + log.Error("Failed to set and index limboed blobs", "tx", tx, "err", err) return err } return nil @@ -156,21 +152,21 @@ // pull retrieves a previously pushed set of blobs back from the limbo, removing // it at the same time. This method should be used when a previously included blob // transaction gets reorged out. -func (l *limbo) pull(tx common.Hash) ([]kzg4844.Blob, []kzg4844.Commitment, []kzg4844.Proof, error) { +func (l *limbo) pull(tx common.Hash) (*types.Transaction, error) { // If the blobs are not tracked by the limbo, there's not much to do. This // can happen for example if a blob transaction is mined without pushing it // into the network first. id, ok := l.index[tx] if !ok { log.Trace("Limbo cannot pull non-tracked blobs", "tx", tx) - return nil, nil, nil, errors.New("unseen blob transaction") + return nil, errors.New("unseen blob transaction") } item, err := l.getAndDrop(id) if err != nil { log.Error("Failed to get and drop limboed blobs", "tx", tx, "id", id, "err", err) - return nil, nil, nil, err + return nil, err } - return item.Blobs, item.Commits, item.Proofs, nil + return item.Tx, nil }   // update changes the block number under which a blob transaction is tracked. This @@ -180,33 +176,33 @@ // The method may log errors for various unexpcted scenarios but will not return // any of it since there's no clear error case. Some errors may be due to coding // issues, others caused by signers mining MEV stuff or swapping transactions. In // all cases, the pool needs to continue operating. -func (l *limbo) update(tx common.Hash, block uint64) { +func (l *limbo) update(txhash common.Hash, block uint64) { // If the blobs are not tracked by the limbo, there's not much to do. This // can happen for example if a blob transaction is mined without pushing it // into the network first. - id, ok := l.index[tx] + id, ok := l.index[txhash] if !ok { - log.Trace("Limbo cannot update non-tracked blobs", "tx", tx) + log.Trace("Limbo cannot update non-tracked blobs", "tx", txhash) return } // If there was no change in the blob's inclusion block, don't mess around // with heavy database operations. if _, ok := l.groups[block][id]; ok { - log.Trace("Blob transaction unchanged in limbo", "tx", tx, "block", block) + log.Trace("Blob transaction unchanged in limbo", "tx", txhash, "block", block) return } - // Retrieve the old blobs from the data store and write tehm back with a new + // Retrieve the old blobs from the data store and write them back with a new // block number. IF anything fails, there's not much to do, go on. item, err := l.getAndDrop(id) if err != nil { - log.Error("Failed to get and drop limboed blobs", "tx", tx, "id", id, "err", err) + log.Error("Failed to get and drop limboed blobs", "tx", txhash, "id", id, "err", err) return } - if err := l.setAndIndex(tx, block, item.Blobs, item.Commits, item.Proofs); err != nil { - log.Error("Failed to set and index limboed blobs", "tx", tx, "err", err) + if err := l.setAndIndex(item.Tx, block); err != nil { + log.Error("Failed to set and index limboed blobs", "tx", txhash, "err", err) return } - log.Trace("Blob transaction updated in limbo", "tx", tx, "old-block", item.Block, "new-block", block) + log.Trace("Blob transaction updated in limbo", "tx", txhash, "old-block", item.Block, "new-block", block) }   // getAndDrop retrieves a blob item from the limbo store and deletes it both from @@ -220,7 +216,7 @@ item := new(limboBlob) if err = rlp.DecodeBytes(data, item); err != nil { return nil, err } - delete(l.index, item.Owner) + delete(l.index, item.TxHash) delete(l.groups[item.Block], id) if len(l.groups[item.Block]) == 0 { delete(l.groups, item.Block) @@ -233,13 +229,12 @@ }   // setAndIndex assembles a limbo blob database entry and stores it, also updating // the in-memory indices. -func (l *limbo) setAndIndex(tx common.Hash, block uint64, blobs []kzg4844.Blob, commits []kzg4844.Commitment, proofs []kzg4844.Proof) error { +func (l *limbo) setAndIndex(tx *types.Transaction, block uint64) error { + txhash := tx.Hash() item := &limboBlob{ - Owner: tx, - Block: block, - Blobs: blobs, - Commits: commits, - Proofs: proofs, + TxHash: txhash, + Block: block, + Tx: tx, } data, err := rlp.EncodeToBytes(item) if err != nil { @@ -249,10 +244,10 @@ id, err := l.store.Put(data) if err != nil { return err } - l.index[tx] = id + l.index[txhash] = id if _, ok := l.groups[block]; !ok { l.groups[block] = make(map[uint64]common.Hash) } - l.groups[block][id] = tx + l.groups[block][id] = txhash return nil }
diff --git ethereum/go-ethereum/core/txpool/blobpool/priority.go taikoxyz/taiko-geth/core/txpool/blobpool/priority.go index 18e545c2a876156b186089cafc8bab61cf82fa76..a8332bd9b0e6680eb38465b4bec73fe6b4d02303 100644 --- ethereum/go-ethereum/core/txpool/blobpool/priority.go +++ taikoxyz/taiko-geth/core/txpool/blobpool/priority.go @@ -27,7 +27,7 @@ // log2_1_125 is used in the eviction priority calculation. var log2_1_125 = math.Log2(1.125)   // evictionPriority calculates the eviction priority based on the algorithm -// described in the BlobPool docs for a both fee components. +// described in the BlobPool docs for both fee components. // // This method takes about 8ns on a very recent laptop CPU, recalculating about // 125 million transaction priority values per second.
diff --git ethereum/go-ethereum/core/txpool/blobpool/slotter_test.go taikoxyz/taiko-geth/core/txpool/blobpool/slotter_test.go index 2751a1872541f4b72782d7421447c68a2548aac6..a7b43b4d22245331d8c4c1fe6f574177dcf5249a 100644 --- ethereum/go-ethereum/core/txpool/blobpool/slotter_test.go +++ taikoxyz/taiko-geth/core/txpool/blobpool/slotter_test.go @@ -38,14 +38,16 @@ 1*blobSize + txAvgSize, // 1 blob + some expected tx infos 2*blobSize + txAvgSize, // 2 blob + some expected tx infos (could be fewer blobs and more tx data) 3*blobSize + txAvgSize, // 3 blob + some expected tx infos (could be fewer blobs and more tx data) 4*blobSize + txAvgSize, // 4 blob + some expected tx infos (could be fewer blobs and more tx data) - 5*blobSize + txAvgSize, // 1-4 blobs + unexpectedly large tx infos < 4 blobs + max tx metadata size - 6*blobSize + txAvgSize, // 1-4 blobs + unexpectedly large tx infos < 4 blobs + max tx metadata size - 7*blobSize + txAvgSize, // 1-4 blobs + unexpectedly large tx infos < 4 blobs + max tx metadata size - 8*blobSize + txAvgSize, // 1-4 blobs + unexpectedly large tx infos < 4 blobs + max tx metadata size - 9*blobSize + txAvgSize, // 1-4 blobs + unexpectedly large tx infos < 4 blobs + max tx metadata size - 10*blobSize + txAvgSize, // 1-4 blobs + unexpectedly large tx infos < 4 blobs + max tx metadata size - 11*blobSize + txAvgSize, // 1-4 blobs + unexpectedly large tx infos < 4 blobs + max tx metadata size - 12*blobSize + txAvgSize, // 1-4 blobs + unexpectedly large tx infos >= 4 blobs + max tx metadata size + 5*blobSize + txAvgSize, // 1-6 blobs + unexpectedly large tx infos < 4 blobs + max tx metadata size + 6*blobSize + txAvgSize, // 1-6 blobs + unexpectedly large tx infos < 4 blobs + max tx metadata size + 7*blobSize + txAvgSize, // 1-6 blobs + unexpectedly large tx infos < 4 blobs + max tx metadata size + 8*blobSize + txAvgSize, // 1-6 blobs + unexpectedly large tx infos < 4 blobs + max tx metadata size + 9*blobSize + txAvgSize, // 1-6 blobs + unexpectedly large tx infos < 4 blobs + max tx metadata size + 10*blobSize + txAvgSize, // 1-6 blobs + unexpectedly large tx infos < 4 blobs + max tx metadata size + 11*blobSize + txAvgSize, // 1-6 blobs + unexpectedly large tx infos < 4 blobs + max tx metadata size + 12*blobSize + txAvgSize, // 1-6 blobs + unexpectedly large tx infos < 4 blobs + max tx metadata size + 13*blobSize + txAvgSize, // 1-6 blobs + unexpectedly large tx infos < 4 blobs + max tx metadata size + 14*blobSize + txAvgSize, // 1-6 blobs + unexpectedly large tx infos >= 4 blobs + max tx metadata size } if len(shelves) != len(want) { t.Errorf("shelves count mismatch: have %d, want %d", len(shelves), len(want))
diff --git ethereum/go-ethereum/core/txpool/legacypool/legacypool.go taikoxyz/taiko-geth/core/txpool/legacypool/legacypool.go index b1ae8bac81408683f18bc0c02169f8ba45048a51..e71204185f0306ec5d2e6ef4b79fe5ca69319809 100644 --- ethereum/go-ethereum/core/txpool/legacypool/legacypool.go +++ taikoxyz/taiko-geth/core/txpool/legacypool/legacypool.go @@ -208,7 +208,6 @@ chainconfig *params.ChainConfig chain BlockChain gasTip atomic.Pointer[big.Int] txFeed event.Feed - scope event.SubscriptionScope signer types.Signer mu sync.RWMutex   @@ -298,7 +297,20 @@ pool.reserve = reserve   // Set the basic pool parameters pool.gasTip.Store(gasTip) - pool.reset(nil, head) + + // Initialize the state with head block, or fallback to empty one in + // case the head state is not available(might occur when node is not + // fully synced). + statedb, err := pool.chain.StateAt(head.Root) + if err != nil { + statedb, err = pool.chain.StateAt(types.EmptyRootHash) + } + if err != nil { + return err + } + pool.currentHead.Store(head) + pool.currentState = statedb + pool.pendingNonces = newNoncer(statedb)   // Start the reorg loop early, so it can handle requests generated during // journal loading. @@ -391,9 +403,6 @@ }   // Close terminates the transaction pool. func (pool *LegacyPool) Close() error { - // Unsubscribe all subscriptions registered from txpool - pool.scope.Close() - // Terminate the pool reorger and return close(pool.reorgShutdownCh) pool.wg.Wait() @@ -406,16 +415,20 @@ return nil }   // Reset implements txpool.SubPool, allowing the legacy pool's internal state to be -// kept in sync with the main transacion pool's internal state. +// kept in sync with the main transaction pool's internal state. func (pool *LegacyPool) Reset(oldHead, newHead *types.Header) { wait := pool.requestReset(oldHead, newHead) <-wait }   -// SubscribeTransactions registers a subscription of NewTxsEvent and -// starts sending event to the given channel. -func (pool *LegacyPool) SubscribeTransactions(ch chan<- core.NewTxsEvent) event.Subscription { - return pool.scope.Track(pool.txFeed.Subscribe(ch)) +// SubscribeTransactions registers a subscription for new transaction events, +// supporting feeding only newly seen or also resurrected transactions. +func (pool *LegacyPool) SubscribeTransactions(ch chan<- core.NewTxsEvent, reorgs bool) event.Subscription { + // The legacy pool has a very messed up internal shuffling, so it's kind of + // hard to separate newly discovered transaction from resurrected ones. This + // is because the new txs are added to the queue, resurrected ones too and + // reorgs run lazily, so separating the two would need a marker. + return pool.txFeed.Subscribe(ch) }   // SetGasTip updates the minimum gas tip required by the transaction pool for a @@ -535,10 +548,12 @@ for i := 0; i < len(txs); i++ { lazies[i] = &txpool.LazyTransaction{ Pool: pool, Hash: txs[i].Hash(), - Tx: &txpool.Transaction{Tx: txs[i]}, + Tx: txs[i], Time: txs[i].Time(), GasFeeCap: txs[i].GasFeeCap(), GasTipCap: txs[i].GasTipCap(), + Gas: txs[i].Gas(), + BlobGas: txs[i].BlobGas(), } } pending[addr] = lazies @@ -588,7 +603,7 @@ } if local { opts.MinTip = new(big.Int) } - if err := txpool.ValidateTransaction(tx, nil, nil, nil, pool.currentHead.Load(), pool.signer, opts); err != nil { + if err := txpool.ValidateTransaction(tx, pool.currentHead.Load(), pool.signer, opts); err != nil { return err } return nil @@ -637,7 +652,7 @@ // pending promotion and execution. If the transaction is a replacement for an already // pending or queued one, it overwrites the previous transaction if its price is higher. // // If a newly added transaction is marked as local, its sending account will be -// be added to the allowlist, preventing any associated transaction from being dropped +// added to the allowlist, preventing any associated transaction from being dropped // out of the pool due to pricing constraints. func (pool *LegacyPool) add(tx *types.Transaction, local bool) (replaced bool, err error) { // If the transaction is already known, discard it @@ -900,26 +915,13 @@ pool.beats[addr] = time.Now() return true }   -// Add enqueues a batch of transactions into the pool if they are valid. Depending -// on the local flag, full pricing contraints will or will not be applied. -// -// If sync is set, the method will block until all internal maintenance related -// to the add is finished. Only use this during tests for determinism! -func (pool *LegacyPool) Add(txs []*txpool.Transaction, local bool, sync bool) []error { - unwrapped := make([]*types.Transaction, len(txs)) - for i, tx := range txs { - unwrapped[i] = tx.Tx - } - return pool.addTxs(unwrapped, local, sync) -} - // addLocals enqueues a batch of transactions into the pool if they are valid, marking the -// senders as a local ones, ensuring they go around the local pricing constraints. +// senders as local ones, ensuring they go around the local pricing constraints. // // This method is used to add transactions from the RPC API and performs synchronous pool // reorganization and event propagation. func (pool *LegacyPool) addLocals(txs []*types.Transaction) []error { - return pool.addTxs(txs, !pool.config.NoLocals, true) + return pool.Add(txs, !pool.config.NoLocals, true) }   // addLocal enqueues a single local transaction into the pool if it is valid. This is @@ -935,7 +937,7 @@ // // This method is used to add transactions from the p2p network and does not wait for pool // reorganization and internal event propagation. func (pool *LegacyPool) addRemotes(txs []*types.Transaction) []error { - return pool.addTxs(txs, false, false) + return pool.Add(txs, false, false) }   // addRemote enqueues a single transaction into the pool if it is valid. This is a convenience @@ -947,16 +949,20 @@ }   // addRemotesSync is like addRemotes, but waits for pool reorganization. Tests use this method. func (pool *LegacyPool) addRemotesSync(txs []*types.Transaction) []error { - return pool.addTxs(txs, false, true) + return pool.Add(txs, false, true) }   // This is like addRemotes with a single transaction, but waits for pool reorganization. Tests use this method. func (pool *LegacyPool) addRemoteSync(tx *types.Transaction) error { - return pool.addTxs([]*types.Transaction{tx}, false, true)[0] + return pool.Add([]*types.Transaction{tx}, false, true)[0] }   -// addTxs attempts to queue a batch of transactions if they are valid. -func (pool *LegacyPool) addTxs(txs []*types.Transaction, local, sync bool) []error { +// Add enqueues a batch of transactions into the pool if they are valid. Depending +// on the local flag, full pricing constraints will or will not be applied. +// +// If sync is set, the method will block until all internal maintenance related +// to the add is finished. Only use this during tests for determinism! +func (pool *LegacyPool) Add(txs []*types.Transaction, local, sync bool) []error { // Filter out known ones without obtaining the pool lock or recovering signatures var ( errs = make([]error, len(txs)) @@ -1042,12 +1048,12 @@ return txpool.TxStatusUnknown }   // Get returns a transaction if it is contained in the pool and nil otherwise. -func (pool *LegacyPool) Get(hash common.Hash) *txpool.Transaction { +func (pool *LegacyPool) Get(hash common.Hash) *types.Transaction { tx := pool.get(hash) if tx == nil { return nil } - return &txpool.Transaction{Tx: tx} + return tx }   // get returns a transaction if it is contained in the pool and nil otherwise.
diff --git ethereum/go-ethereum/core/txpool/legacypool/list.go taikoxyz/taiko-geth/core/txpool/legacypool/list.go index d5d24c85a5019f0ddce8ce8ea5fa1eda6e57532f..05ae0b58cd59766145c3dc4c80045878368f8e28 100644 --- ethereum/go-ethereum/core/txpool/legacypool/list.go +++ taikoxyz/taiko-geth/core/txpool/legacypool/list.go @@ -53,9 +53,10 @@ // sortedMap is a nonce->transaction hash map with a heap based index to allow // iterating over the contents in a nonce-incrementing way. type sortedMap struct { - items map[uint64]*types.Transaction // Hash map storing the transaction data - index *nonceHeap // Heap of nonces of all the stored transactions (non-strict mode) - cache types.Transactions // Cache of the transactions already sorted + items map[uint64]*types.Transaction // Hash map storing the transaction data + index *nonceHeap // Heap of nonces of all the stored transactions (non-strict mode) + cache types.Transactions // Cache of the transactions already sorted + cacheMu sync.Mutex // Mutex covering the cache }   // newSortedMap creates a new nonce-sorted transaction map. @@ -78,7 +79,9 @@ nonce := tx.Nonce() if m.items[nonce] == nil { heap.Push(m.index, nonce) } + m.cacheMu.Lock() m.items[nonce], m.cache = tx, nil + m.cacheMu.Unlock() }   // Forward removes all transactions from the map with a nonce lower than the @@ -94,9 +97,11 @@ removed = append(removed, m.items[nonce]) delete(m.items, nonce) } // If we had a cached order, shift the front + m.cacheMu.Lock() if m.cache != nil { m.cache = m.cache[len(removed):] } + m.cacheMu.Unlock() return removed }   @@ -120,7 +125,9 @@ for nonce := range m.items { *m.index = append(*m.index, nonce) } heap.Init(m.index) + m.cacheMu.Lock() m.cache = nil + m.cacheMu.Unlock() }   // filter is identical to Filter, but **does not** regenerate the heap. This method @@ -136,7 +143,9 @@ delete(m.items, nonce) } } if len(removed) > 0 { + m.cacheMu.Lock() m.cache = nil + m.cacheMu.Unlock() } return removed } @@ -160,9 +169,11 @@ *m.index = (*m.index)[:threshold] heap.Init(m.index)   // If we had a cache, shift the back + m.cacheMu.Lock() if m.cache != nil { m.cache = m.cache[:len(m.cache)-len(drops)] } + m.cacheMu.Unlock() return drops }   @@ -182,7 +193,9 @@ break } } delete(m.items, nonce) + m.cacheMu.Lock() m.cache = nil + m.cacheMu.Unlock()   return true } @@ -192,7 +205,7 @@ // provided nonce that is ready for processing. The returned transactions will be // removed from the list. // // Note, all transactions with nonces lower than start will also be returned to -// prevent getting into and invalid state. This is not something that should ever +// prevent getting into an invalid state. This is not something that should ever // happen but better to be self correcting than failing! func (m *sortedMap) Ready(start uint64) types.Transactions { // Short circuit if no transactions are available @@ -206,7 +219,9 @@ ready = append(ready, m.items[next]) delete(m.items, next) heap.Pop(m.index) } + m.cacheMu.Lock() m.cache = nil + m.cacheMu.Unlock()   return ready } @@ -217,6 +232,8 @@ return len(m.items) }   func (m *sortedMap) flatten() types.Transactions { + m.cacheMu.Lock() + defer m.cacheMu.Unlock() // If the sorting was not cached yet, create and cache it if m.cache == nil { m.cache = make(types.Transactions, 0, len(m.items)) @@ -232,8 +249,8 @@ // Flatten creates a nonce-sorted slice of transactions based on the loosely // sorted internal representation. The result of the sorting is cached in case // it's requested again before any modifications are made to the contents. func (m *sortedMap) Flatten() types.Transactions { - // Copy the cache to prevent accidental modifications cache := m.flatten() + // Copy the cache to prevent accidental modification txs := make(types.Transactions, len(cache)) copy(txs, cache) return txs @@ -404,7 +421,7 @@ // provided nonce that is ready for processing. The returned transactions will be // removed from the list. // // Note, all transactions with nonces lower than start will also be returned to -// prevent getting into and invalid state. This is not something that should ever +// prevent getting into an invalid state. This is not something that should ever // happen but better to be self correcting than failing! func (l *list) Ready(start uint64) types.Transactions { txs := l.txs.Ready(start)
diff --git ethereum/go-ethereum/core/vm/runtime/env.go taikoxyz/taiko-geth/core/vm/runtime/env.go index ffc631a90c95aae39999b570b8b5252f14417820..64aa550a25032526287f6f8c1ca63989eae5ba61 100644 --- ethereum/go-ethereum/core/vm/runtime/env.go +++ taikoxyz/taiko-geth/core/vm/runtime/env.go @@ -37,6 +37,8 @@ Time: cfg.Time, Difficulty: cfg.Difficulty, GasLimit: cfg.GasLimit, BaseFee: cfg.BaseFee, + BlobBaseFee: cfg.BlobBaseFee, + Random: cfg.Random, }   return vm.NewEVM(blockContext, txContext, cfg.State, cfg.ChainConfig, cfg.EVMConfig)
diff --git ethereum/go-ethereum/core/vm/runtime/runtime.go taikoxyz/taiko-geth/core/vm/runtime/runtime.go index a3e75c67212c379a10694f61faf3f9f8fe189c9b..cfd7e4dbc4ee3b8b3a47436c2bfa188f1abc9174 100644 --- ethereum/go-ethereum/core/vm/runtime/runtime.go +++ taikoxyz/taiko-geth/core/vm/runtime/runtime.go @@ -44,7 +44,9 @@ Value *big.Int Debug bool EVMConfig vm.Config BaseFee *big.Int + BlobBaseFee *big.Int BlobHashes []common.Hash + Random *common.Hash   State *state.StateDB GetHashFn func(n uint64) common.Hash @@ -93,6 +95,9 @@ } } if cfg.BaseFee == nil { cfg.BaseFee = big.NewInt(params.InitialBaseFee) + } + if cfg.BlobBaseFee == nil { + cfg.BlobBaseFee = new(big.Int) } }
diff --git ethereum/go-ethereum/crypto/bls12381/g2.go taikoxyz/taiko-geth/crypto/bls12381/g2.go index 4d6f1ff11de82c6dbd961866d298d91fcca6659e..e5fe75af20c726b5d2b942590ef0108ab4457b32 100644 --- ethereum/go-ethereum/crypto/bls12381/g2.go +++ taikoxyz/taiko-geth/crypto/bls12381/g2.go @@ -121,7 +121,7 @@ } return p, nil }   -// DecodePoint given encoded (x, y) coordinates in 256 bytes returns a valid G1 Point. +// DecodePoint given encoded (x, y) coordinates in 256 bytes returns a valid G2 Point. func (g *G2) DecodePoint(in []byte) (*PointG2, error) { if len(in) != 256 { return nil, errors.New("invalid g2 point length")
diff --git ethereum/go-ethereum/crypto/bn256/cloudflare/optate.go taikoxyz/taiko-geth/crypto/bn256/cloudflare/optate.go index b71e50e3a21ceff53c98027c54c592b977b4ee06..e8caa7a08656953ebd6306fa78f3efc1f3351b37 100644 --- ethereum/go-ethereum/crypto/bn256/cloudflare/optate.go +++ taikoxyz/taiko-geth/crypto/bn256/cloudflare/optate.go @@ -199,9 +199,8 @@ mulLine(ret, a, b, c) r = newR   r2.Square(&minusQ2.y) - a, b, c, newR = lineFunctionAdd(r, minusQ2, bAffine, r2) + a, b, c, _ = lineFunctionAdd(r, minusQ2, bAffine, r2) mulLine(ret, a, b, c) - r = newR   return ret }
diff --git ethereum/go-ethereum/eth/protocols/eth/broadcast.go taikoxyz/taiko-geth/eth/protocols/eth/broadcast.go index c431aa4005a674b09dad20dfb2d066d64d43b0ba..3045303f222e126ce8362bfa5b92ad48e6b289b3 100644 --- ethereum/go-ethereum/eth/protocols/eth/broadcast.go +++ taikoxyz/taiko-geth/eth/protocols/eth/broadcast.go @@ -81,8 +81,8 @@ size common.StorageSize ) for i := 0; i < len(queue) && size < maxTxPacketSize; i++ { if tx := p.txpool.Get(queue[i]); tx != nil { - txs = append(txs, tx.Tx) - size += common.StorageSize(tx.Tx.Size()) + txs = append(txs, tx) + size += common.StorageSize(tx.Size()) } hashesCount++ } @@ -151,8 +151,8 @@ ) for count = 0; count < len(queue) && size < maxTxPacketSize; count++ { if tx := p.txpool.Get(queue[count]); tx != nil { pending = append(pending, queue[count]) - pendingTypes = append(pendingTypes, tx.Tx.Type()) - pendingSizes = append(pendingSizes, uint32(tx.Tx.Size())) + pendingTypes = append(pendingTypes, tx.Type()) + pendingSizes = append(pendingSizes, uint32(tx.Size())) size += common.HashLength } }
diff --git ethereum/go-ethereum/eth/protocols/eth/discovery.go taikoxyz/taiko-geth/eth/protocols/eth/discovery.go index 87857244b58988c2afca79a38ddb3c5130cde8e2..a7bdd47daf07df237acf996a002bb1d956ea2eb8 100644 --- ethereum/go-ethereum/eth/protocols/eth/discovery.go +++ taikoxyz/taiko-geth/eth/protocols/eth/discovery.go @@ -61,6 +61,6 @@ // currentENREntry constructs an `eth` ENR entry based on the current state of the chain. func currentENREntry(chain *core.BlockChain) *enrEntry { head := chain.CurrentHeader() return &enrEntry{ - ForkID: forkid.NewID(chain.Config(), chain.Genesis().Hash(), head.Number.Uint64(), head.Time), + ForkID: forkid.NewID(chain.Config(), chain.Genesis(), head.Number.Uint64(), head.Time), } }
diff --git ethereum/go-ethereum/eth/protocols/eth/handler.go taikoxyz/taiko-geth/eth/protocols/eth/handler.go index 7f51d4f5cdd3abe9f79ed5f6374db0a1887cfd60..42d0412a127c8b62ba0a5693cf98dde6652122ed 100644 --- ethereum/go-ethereum/eth/protocols/eth/handler.go +++ taikoxyz/taiko-geth/eth/protocols/eth/handler.go @@ -23,7 +23,7 @@ "time"   "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/core" - "github.com/ethereum/go-ethereum/core/txpool" + "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/metrics" "github.com/ethereum/go-ethereum/p2p" "github.com/ethereum/go-ethereum/p2p/enode" @@ -43,10 +43,6 @@ // maxBodiesServe is the maximum number of block bodies to serve. This number // is mostly there to limit the number of disk lookups. With 24KB block sizes // nowadays, the practical limit will always be softResponseLimit. maxBodiesServe = 1024 - - // maxNodeDataServe is the maximum number of state trie nodes to serve. This - // number is there to limit the number of disk lookups. - maxNodeDataServe = 1024   // maxReceiptsServe is the maximum number of block receipts to serve. This // number is mostly there to limit the number of disk lookups. With block @@ -90,16 +86,20 @@ // TxPool defines the methods needed by the protocol handler to serve transactions. type TxPool interface { // Get retrieves the transaction from the local txpool with the given hash. - Get(hash common.Hash) *txpool.Transaction + Get(hash common.Hash) *types.Transaction }   // MakeProtocols constructs the P2P protocol definitions for `eth`. func MakeProtocols(backend Backend, network uint64, dnsdisc enode.Iterator) []p2p.Protocol { - protocols := make([]p2p.Protocol, len(ProtocolVersions)) - for i, version := range ProtocolVersions { + protocols := make([]p2p.Protocol, 0, len(ProtocolVersions)) + for _, version := range ProtocolVersions { + // Blob transactions require eth/68 announcements, disable everything else + if version <= ETH67 && backend.Chain().Config().CancunTime != nil { + continue + } version := version // Closure   - protocols[i] = p2p.Protocol{ + protocols = append(protocols, p2p.Protocol{ Name: ProtocolName, Version: version, Length: protocolLengths[version], @@ -119,7 +119,7 @@ return backend.PeerInfo(id) }, Attributes: []enr.Entry{currentENREntry(backend.Chain())}, DialCandidates: dnsdisc, - } + }) } return protocols } @@ -166,36 +166,19 @@ Decode(val interface{}) error Time() time.Time }   -var eth66 = map[uint64]msgHandler{ - NewBlockHashesMsg: handleNewBlockhashes, - NewBlockMsg: handleNewBlock, - TransactionsMsg: handleTransactions, - NewPooledTransactionHashesMsg: handleNewPooledTransactionHashes66, - GetBlockHeadersMsg: handleGetBlockHeaders66, - BlockHeadersMsg: handleBlockHeaders66, - GetBlockBodiesMsg: handleGetBlockBodies66, - BlockBodiesMsg: handleBlockBodies66, - GetNodeDataMsg: handleGetNodeData66, - NodeDataMsg: handleNodeData66, - GetReceiptsMsg: handleGetReceipts66, - ReceiptsMsg: handleReceipts66, - GetPooledTransactionsMsg: handleGetPooledTransactions66, - PooledTransactionsMsg: handlePooledTransactions66, -} - var eth67 = map[uint64]msgHandler{ NewBlockHashesMsg: handleNewBlockhashes, NewBlockMsg: handleNewBlock, TransactionsMsg: handleTransactions, - NewPooledTransactionHashesMsg: handleNewPooledTransactionHashes66, - GetBlockHeadersMsg: handleGetBlockHeaders66, - BlockHeadersMsg: handleBlockHeaders66, - GetBlockBodiesMsg: handleGetBlockBodies66, - BlockBodiesMsg: handleBlockBodies66, - GetReceiptsMsg: handleGetReceipts66, - ReceiptsMsg: handleReceipts66, - GetPooledTransactionsMsg: handleGetPooledTransactions66, - PooledTransactionsMsg: handlePooledTransactions66, + NewPooledTransactionHashesMsg: handleNewPooledTransactionHashes67, + GetBlockHeadersMsg: handleGetBlockHeaders, + BlockHeadersMsg: handleBlockHeaders, + GetBlockBodiesMsg: handleGetBlockBodies, + BlockBodiesMsg: handleBlockBodies, + GetReceiptsMsg: handleGetReceipts, + ReceiptsMsg: handleReceipts, + GetPooledTransactionsMsg: handleGetPooledTransactions, + PooledTransactionsMsg: handlePooledTransactions, }   var eth68 = map[uint64]msgHandler{ @@ -203,14 +186,14 @@ NewBlockHashesMsg: handleNewBlockhashes, NewBlockMsg: handleNewBlock, TransactionsMsg: handleTransactions, NewPooledTransactionHashesMsg: handleNewPooledTransactionHashes68, - GetBlockHeadersMsg: handleGetBlockHeaders66, - BlockHeadersMsg: handleBlockHeaders66, - GetBlockBodiesMsg: handleGetBlockBodies66, - BlockBodiesMsg: handleBlockBodies66, - GetReceiptsMsg: handleGetReceipts66, - ReceiptsMsg: handleReceipts66, - GetPooledTransactionsMsg: handleGetPooledTransactions66, - PooledTransactionsMsg: handlePooledTransactions66, + GetBlockHeadersMsg: handleGetBlockHeaders, + BlockHeadersMsg: handleBlockHeaders, + GetBlockBodiesMsg: handleGetBlockBodies, + BlockBodiesMsg: handleBlockBodies, + GetReceiptsMsg: handleGetReceipts, + ReceiptsMsg: handleReceipts, + GetPooledTransactionsMsg: handleGetPooledTransactions, + PooledTransactionsMsg: handlePooledTransactions, }   // handleMessage is invoked whenever an inbound message is received from a remote @@ -226,14 +209,10 @@ return fmt.Errorf("%w: %v > %v", errMsgTooLarge, msg.Size, maxMessageSize) } defer msg.Discard()   - var handlers = eth66 - if peer.Version() == ETH67 { - handlers = eth67 - } + var handlers = eth67 if peer.Version() >= ETH68 { handlers = eth68 } - // Track the amount of time it takes to serve the request and run the handler if metrics.Enabled { h := fmt.Sprintf("%s/%s/%d/%#02x", p2p.HandleHistName, ProtocolName, peer.Version(), msg.Code)
diff --git ethereum/go-ethereum/eth/protocols/eth/handler_test.go taikoxyz/taiko-geth/eth/protocols/eth/handler_test.go index 3f1dc9fe76e6e8449d273f95ffe0c3bb385deea3..41e18bfb3e01b7f32d7b29cca720fda9de26a4cb 100644 --- ethereum/go-ethereum/eth/protocols/eth/handler_test.go +++ taikoxyz/taiko-geth/eth/protocols/eth/handler_test.go @@ -28,7 +28,6 @@ "github.com/ethereum/go-ethereum/consensus/beacon" "github.com/ethereum/go-ethereum/consensus/ethash" "github.com/ethereum/go-ethereum/core" "github.com/ethereum/go-ethereum/core/rawdb" - "github.com/ethereum/go-ethereum/core/state" "github.com/ethereum/go-ethereum/core/txpool" "github.com/ethereum/go-ethereum/core/txpool/legacypool" "github.com/ethereum/go-ethereum/core/types" @@ -112,7 +111,7 @@ if _, err := chain.InsertChain(bs); err != nil { panic(err) } for _, block := range bs { - chain.StateCache().TrieDB().Commit(block.Root(), false) + chain.TrieDB().Commit(block.Root(), false) } txconfig := legacypool.DefaultConfig txconfig.Journal = "" // Don't litter the disk with test journals @@ -151,7 +150,6 @@ panic("data processing tests should be done in the handler package") }   // Tests that block headers can be retrieved from a remote chain based on user queries. -func TestGetBlockHeaders66(t *testing.T) { testGetBlockHeaders(t, ETH66) } func TestGetBlockHeaders67(t *testing.T) { testGetBlockHeaders(t, ETH67) } func TestGetBlockHeaders68(t *testing.T) { testGetBlockHeaders(t, ETH68) }   @@ -178,29 +176,29 @@ } // Create a batch of tests for various scenarios limit := uint64(maxHeadersServe) tests := []struct { - query *GetBlockHeadersPacket // The query to execute for header retrieval - expect []common.Hash // The hashes of the block whose headers are expected + query *GetBlockHeadersRequest // The query to execute for header retrieval + expect []common.Hash // The hashes of the block whose headers are expected }{ // A single random block should be retrievable by hash { - &GetBlockHeadersPacket{Origin: HashOrNumber{Hash: backend.chain.GetBlockByNumber(limit / 2).Hash()}, Amount: 1}, + &GetBlockHeadersRequest{Origin: HashOrNumber{Hash: backend.chain.GetBlockByNumber(limit / 2).Hash()}, Amount: 1}, []common.Hash{backend.chain.GetBlockByNumber(limit / 2).Hash()}, }, // A single random block should be retrievable by number { - &GetBlockHeadersPacket{Origin: HashOrNumber{Number: limit / 2}, Amount: 1}, + &GetBlockHeadersRequest{Origin: HashOrNumber{Number: limit / 2}, Amount: 1}, []common.Hash{backend.chain.GetBlockByNumber(limit / 2).Hash()}, }, // Multiple headers should be retrievable in both directions { - &GetBlockHeadersPacket{Origin: HashOrNumber{Number: limit / 2}, Amount: 3}, + &GetBlockHeadersRequest{Origin: HashOrNumber{Number: limit / 2}, Amount: 3}, []common.Hash{ backend.chain.GetBlockByNumber(limit / 2).Hash(), backend.chain.GetBlockByNumber(limit/2 + 1).Hash(), backend.chain.GetBlockByNumber(limit/2 + 2).Hash(), }, }, { - &GetBlockHeadersPacket{Origin: HashOrNumber{Number: limit / 2}, Amount: 3, Reverse: true}, + &GetBlockHeadersRequest{Origin: HashOrNumber{Number: limit / 2}, Amount: 3, Reverse: true}, []common.Hash{ backend.chain.GetBlockByNumber(limit / 2).Hash(), backend.chain.GetBlockByNumber(limit/2 - 1).Hash(), @@ -209,14 +207,14 @@ }, }, // Multiple headers with skip lists should be retrievable { - &GetBlockHeadersPacket{Origin: HashOrNumber{Number: limit / 2}, Skip: 3, Amount: 3}, + &GetBlockHeadersRequest{Origin: HashOrNumber{Number: limit / 2}, Skip: 3, Amount: 3}, []common.Hash{ backend.chain.GetBlockByNumber(limit / 2).Hash(), backend.chain.GetBlockByNumber(limit/2 + 4).Hash(), backend.chain.GetBlockByNumber(limit/2 + 8).Hash(), }, }, { - &GetBlockHeadersPacket{Origin: HashOrNumber{Number: limit / 2}, Skip: 3, Amount: 3, Reverse: true}, + &GetBlockHeadersRequest{Origin: HashOrNumber{Number: limit / 2}, Skip: 3, Amount: 3, Reverse: true}, []common.Hash{ backend.chain.GetBlockByNumber(limit / 2).Hash(), backend.chain.GetBlockByNumber(limit/2 - 4).Hash(), @@ -225,31 +223,31 @@ }, }, // The chain endpoints should be retrievable { - &GetBlockHeadersPacket{Origin: HashOrNumber{Number: 0}, Amount: 1}, + &GetBlockHeadersRequest{Origin: HashOrNumber{Number: 0}, Amount: 1}, []common.Hash{backend.chain.GetBlockByNumber(0).Hash()}, }, { - &GetBlockHeadersPacket{Origin: HashOrNumber{Number: backend.chain.CurrentBlock().Number.Uint64()}, Amount: 1}, + &GetBlockHeadersRequest{Origin: HashOrNumber{Number: backend.chain.CurrentBlock().Number.Uint64()}, Amount: 1}, []common.Hash{backend.chain.CurrentBlock().Hash()}, }, { // If the peer requests a bit into the future, we deliver what we have - &GetBlockHeadersPacket{Origin: HashOrNumber{Number: backend.chain.CurrentBlock().Number.Uint64()}, Amount: 10}, + &GetBlockHeadersRequest{Origin: HashOrNumber{Number: backend.chain.CurrentBlock().Number.Uint64()}, Amount: 10}, []common.Hash{backend.chain.CurrentBlock().Hash()}, }, // Ensure protocol limits are honored { - &GetBlockHeadersPacket{Origin: HashOrNumber{Number: backend.chain.CurrentBlock().Number.Uint64() - 1}, Amount: limit + 10, Reverse: true}, + &GetBlockHeadersRequest{Origin: HashOrNumber{Number: backend.chain.CurrentBlock().Number.Uint64() - 1}, Amount: limit + 10, Reverse: true}, getHashes(backend.chain.CurrentBlock().Number.Uint64(), limit), }, // Check that requesting more than available is handled gracefully { - &GetBlockHeadersPacket{Origin: HashOrNumber{Number: backend.chain.CurrentBlock().Number.Uint64() - 4}, Skip: 3, Amount: 3}, + &GetBlockHeadersRequest{Origin: HashOrNumber{Number: backend.chain.CurrentBlock().Number.Uint64() - 4}, Skip: 3, Amount: 3}, []common.Hash{ backend.chain.GetBlockByNumber(backend.chain.CurrentBlock().Number.Uint64() - 4).Hash(), backend.chain.GetBlockByNumber(backend.chain.CurrentBlock().Number.Uint64()).Hash(), }, }, { - &GetBlockHeadersPacket{Origin: HashOrNumber{Number: 4}, Skip: 3, Amount: 3, Reverse: true}, + &GetBlockHeadersRequest{Origin: HashOrNumber{Number: 4}, Skip: 3, Amount: 3, Reverse: true}, []common.Hash{ backend.chain.GetBlockByNumber(4).Hash(), backend.chain.GetBlockByNumber(0).Hash(), @@ -257,13 +255,13 @@ }, }, // Check that requesting more than available is handled gracefully, even if mid skip { - &GetBlockHeadersPacket{Origin: HashOrNumber{Number: backend.chain.CurrentBlock().Number.Uint64() - 4}, Skip: 2, Amount: 3}, + &GetBlockHeadersRequest{Origin: HashOrNumber{Number: backend.chain.CurrentBlock().Number.Uint64() - 4}, Skip: 2, Amount: 3}, []common.Hash{ backend.chain.GetBlockByNumber(backend.chain.CurrentBlock().Number.Uint64() - 4).Hash(), backend.chain.GetBlockByNumber(backend.chain.CurrentBlock().Number.Uint64() - 1).Hash(), }, }, { - &GetBlockHeadersPacket{Origin: HashOrNumber{Number: 4}, Skip: 2, Amount: 3, Reverse: true}, + &GetBlockHeadersRequest{Origin: HashOrNumber{Number: 4}, Skip: 2, Amount: 3, Reverse: true}, []common.Hash{ backend.chain.GetBlockByNumber(4).Hash(), backend.chain.GetBlockByNumber(1).Hash(), @@ -271,7 +269,7 @@ }, }, // Check a corner case where requesting more can iterate past the endpoints { - &GetBlockHeadersPacket{Origin: HashOrNumber{Number: 2}, Amount: 5, Reverse: true}, + &GetBlockHeadersRequest{Origin: HashOrNumber{Number: 2}, Amount: 5, Reverse: true}, []common.Hash{ backend.chain.GetBlockByNumber(2).Hash(), backend.chain.GetBlockByNumber(1).Hash(), @@ -280,24 +278,24 @@ }, }, // Check a corner case where skipping overflow loops back into the chain start { - &GetBlockHeadersPacket{Origin: HashOrNumber{Hash: backend.chain.GetBlockByNumber(3).Hash()}, Amount: 2, Reverse: false, Skip: math.MaxUint64 - 1}, + &GetBlockHeadersRequest{Origin: HashOrNumber{Hash: backend.chain.GetBlockByNumber(3).Hash()}, Amount: 2, Reverse: false, Skip: math.MaxUint64 - 1}, []common.Hash{ backend.chain.GetBlockByNumber(3).Hash(), }, }, // Check a corner case where skipping overflow loops back to the same header { - &GetBlockHeadersPacket{Origin: HashOrNumber{Hash: backend.chain.GetBlockByNumber(1).Hash()}, Amount: 2, Reverse: false, Skip: math.MaxUint64}, + &GetBlockHeadersRequest{Origin: HashOrNumber{Hash: backend.chain.GetBlockByNumber(1).Hash()}, Amount: 2, Reverse: false, Skip: math.MaxUint64}, []common.Hash{ backend.chain.GetBlockByNumber(1).Hash(), }, }, // Check that non existing headers aren't returned { - &GetBlockHeadersPacket{Origin: HashOrNumber{Hash: unknown}, Amount: 1}, + &GetBlockHeadersRequest{Origin: HashOrNumber{Hash: unknown}, Amount: 1}, []common.Hash{}, }, { - &GetBlockHeadersPacket{Origin: HashOrNumber{Number: backend.chain.CurrentBlock().Number.Uint64() + 1}, Amount: 1}, + &GetBlockHeadersRequest{Origin: HashOrNumber{Number: backend.chain.CurrentBlock().Number.Uint64() + 1}, Amount: 1}, []common.Hash{}, }, } @@ -309,13 +307,13 @@ for _, hash := range tt.expect { headers = append(headers, backend.chain.GetBlockByHash(hash).Header()) } // Send the hash request and verify the response - p2p.Send(peer.app, GetBlockHeadersMsg, &GetBlockHeadersPacket66{ - RequestId: 123, - GetBlockHeadersPacket: tt.query, + p2p.Send(peer.app, GetBlockHeadersMsg, &GetBlockHeadersPacket{ + RequestId: 123, + GetBlockHeadersRequest: tt.query, }) - if err := p2p.ExpectMsg(peer.app, BlockHeadersMsg, &BlockHeadersPacket66{ - RequestId: 123, - BlockHeadersPacket: headers, + if err := p2p.ExpectMsg(peer.app, BlockHeadersMsg, &BlockHeadersPacket{ + RequestId: 123, + BlockHeadersRequest: headers, }); err != nil { t.Errorf("test %d: headers mismatch: %v", i, err) } @@ -324,11 +322,11 @@ if tt.query.Origin.Hash == (common.Hash{}) { if origin := backend.chain.GetBlockByNumber(tt.query.Origin.Number); origin != nil { tt.query.Origin.Hash, tt.query.Origin.Number = origin.Hash(), 0   - p2p.Send(peer.app, GetBlockHeadersMsg, &GetBlockHeadersPacket66{ - RequestId: 456, - GetBlockHeadersPacket: tt.query, + p2p.Send(peer.app, GetBlockHeadersMsg, &GetBlockHeadersPacket{ + RequestId: 456, + GetBlockHeadersRequest: tt.query, }) - expected := &BlockHeadersPacket66{RequestId: 456, BlockHeadersPacket: headers} + expected := &BlockHeadersPacket{RequestId: 456, BlockHeadersRequest: headers} if err := p2p.ExpectMsg(peer.app, BlockHeadersMsg, expected); err != nil { t.Errorf("test %d by hash: headers mismatch: %v", i, err) } @@ -338,7 +336,6 @@ } }   // Tests that block contents can be retrieved from a remote chain based on their hashes. -func TestGetBlockBodies66(t *testing.T) { testGetBlockBodies(t, ETH66) } func TestGetBlockBodies67(t *testing.T) { testGetBlockBodies(t, ETH67) } func TestGetBlockBodies68(t *testing.T) { testGetBlockBodies(t, ETH68) }   @@ -420,139 +417,20 @@ } }   // Send the hash request and verify the response - p2p.Send(peer.app, GetBlockBodiesMsg, &GetBlockBodiesPacket66{ - RequestId: 123, - GetBlockBodiesPacket: hashes, + p2p.Send(peer.app, GetBlockBodiesMsg, &GetBlockBodiesPacket{ + RequestId: 123, + GetBlockBodiesRequest: hashes, }) - if err := p2p.ExpectMsg(peer.app, BlockBodiesMsg, &BlockBodiesPacket66{ - RequestId: 123, - BlockBodiesPacket: bodies, + if err := p2p.ExpectMsg(peer.app, BlockBodiesMsg, &BlockBodiesPacket{ + RequestId: 123, + BlockBodiesResponse: bodies, }); err != nil { t.Fatalf("test %d: bodies mismatch: %v", i, err) } } }   -// Tests that the state trie nodes can be retrieved based on hashes. -func TestGetNodeData66(t *testing.T) { testGetNodeData(t, ETH66, false) } -func TestGetNodeData67(t *testing.T) { testGetNodeData(t, ETH67, true) } -func TestGetNodeData68(t *testing.T) { testGetNodeData(t, ETH68, true) } - -func testGetNodeData(t *testing.T, protocol uint, drop bool) { - t.Parallel() - - // Define three accounts to simulate transactions with - acc1Key, _ := crypto.HexToECDSA("8a1f9a8f95be41cd7ccb6168179afb4504aefe388d1e14474d32c45c72ce7b7a") - acc2Key, _ := crypto.HexToECDSA("49a7b37aa6f6645917e7b807e9d1c00d4fa71f18343b0d4122a4d2df64dd6fee") - acc1Addr := crypto.PubkeyToAddress(acc1Key.PublicKey) - acc2Addr := crypto.PubkeyToAddress(acc2Key.PublicKey) - - signer := types.HomesteadSigner{} - // Create a chain generator with some simple transactions (blatantly stolen from @fjl/chain_makers_test) - generator := func(i int, block *core.BlockGen) { - switch i { - case 0: - // In block 1, the test bank sends account #1 some ether. - tx, _ := types.SignTx(types.NewTransaction(block.TxNonce(testAddr), acc1Addr, big.NewInt(10_000_000_000_000_000), params.TxGas, block.BaseFee(), nil), signer, testKey) - block.AddTx(tx) - case 1: - // In block 2, the test bank sends some more ether to account #1. - // acc1Addr passes it on to account #2. - tx1, _ := types.SignTx(types.NewTransaction(block.TxNonce(testAddr), acc1Addr, big.NewInt(1_000_000_000_000_000), params.TxGas, block.BaseFee(), nil), signer, testKey) - tx2, _ := types.SignTx(types.NewTransaction(block.TxNonce(acc1Addr), acc2Addr, big.NewInt(1_000_000_000_000_000), params.TxGas, block.BaseFee(), nil), signer, acc1Key) - block.AddTx(tx1) - block.AddTx(tx2) - case 2: - // Block 3 is empty but was mined by account #2. - block.SetCoinbase(acc2Addr) - block.SetExtra([]byte("yeehaw")) - case 3: - // Block 4 includes blocks 2 and 3 as uncle headers (with modified extra data). - b2 := block.PrevBlock(1).Header() - b2.Extra = []byte("foo") - block.AddUncle(b2) - b3 := block.PrevBlock(2).Header() - b3.Extra = []byte("foo") - block.AddUncle(b3) - } - } - // Assemble the test environment - backend := newTestBackendWithGenerator(4, false, generator) - defer backend.close() - - peer, _ := newTestPeer("peer", protocol, backend) - defer peer.close() - - // Collect all state tree hashes. - var hashes []common.Hash - it := backend.db.NewIterator(nil, nil) - for it.Next() { - if key := it.Key(); len(key) == common.HashLength { - hashes = append(hashes, common.BytesToHash(key)) - } - } - it.Release() - - // Request all hashes. - p2p.Send(peer.app, GetNodeDataMsg, &GetNodeDataPacket66{ - RequestId: 123, - GetNodeDataPacket: hashes, - }) - msg, err := peer.app.ReadMsg() - if !drop { - if err != nil { - t.Fatalf("failed to read node data response: %v", err) - } - } else { - if err != nil { - return - } - t.Fatalf("succeeded to read node data response on non-supporting protocol: %v", msg) - } - if msg.Code != NodeDataMsg { - t.Fatalf("response packet code mismatch: have %x, want %x", msg.Code, NodeDataMsg) - } - var res NodeDataPacket66 - if err := msg.Decode(&res); err != nil { - t.Fatalf("failed to decode response node data: %v", err) - } - - // Verify that all hashes correspond to the requested data. - data := res.NodeDataPacket - for i, want := range hashes { - if hash := crypto.Keccak256Hash(data[i]); hash != want { - t.Errorf("data hash mismatch: have %x, want %x", hash, want) - } - } - - // Reconstruct state tree from the received data. - reconstructDB := rawdb.NewMemoryDatabase() - for i := 0; i < len(data); i++ { - rawdb.WriteLegacyTrieNode(reconstructDB, hashes[i], data[i]) - } - - // Sanity check whether all state matches. - accounts := []common.Address{testAddr, acc1Addr, acc2Addr} - for i := uint64(0); i <= backend.chain.CurrentBlock().Number.Uint64(); i++ { - root := backend.chain.GetBlockByNumber(i).Root() - reconstructed, _ := state.New(root, state.NewDatabase(reconstructDB), nil) - for j, acc := range accounts { - state, _ := backend.chain.StateAt(root) - bw := state.GetBalance(acc) - bh := reconstructed.GetBalance(acc) - - if (bw == nil) != (bh == nil) { - t.Errorf("block %d, account %d: balance mismatch: have %v, want %v", i, j, bh, bw) - } - if bw != nil && bh != nil && bw.Cmp(bh) != 0 { - t.Errorf("block %d, account %d: balance mismatch: have %v, want %v", i, j, bh, bw) - } - } - } -} - // Tests that the transaction receipts can be retrieved based on hashes. -func TestGetBlockReceipts66(t *testing.T) { testGetBlockReceipts(t, ETH66) } func TestGetBlockReceipts67(t *testing.T) { testGetBlockReceipts(t, ETH67) } func TestGetBlockReceipts68(t *testing.T) { testGetBlockReceipts(t, ETH68) }   @@ -613,13 +491,13 @@ hashes = append(hashes, block.Hash()) receipts = append(receipts, backend.chain.GetReceiptsByHash(block.Hash())) } // Send the hash request and verify the response - p2p.Send(peer.app, GetReceiptsMsg, &GetReceiptsPacket66{ - RequestId: 123, - GetReceiptsPacket: hashes, + p2p.Send(peer.app, GetReceiptsMsg, &GetReceiptsPacket{ + RequestId: 123, + GetReceiptsRequest: hashes, }) - if err := p2p.ExpectMsg(peer.app, ReceiptsMsg, &ReceiptsPacket66{ - RequestId: 123, - ReceiptsPacket: receipts, + if err := p2p.ExpectMsg(peer.app, ReceiptsMsg, &ReceiptsPacket{ + RequestId: 123, + ReceiptsResponse: receipts, }); err != nil { t.Errorf("receipts mismatch: %v", err) }
diff --git ethereum/go-ethereum/eth/protocols/eth/handlers.go taikoxyz/taiko-geth/eth/protocols/eth/handlers.go index f9fbf72b7b1c6ebae6b8cc40df60da5377993a42..069e92dadf90f1c64a26846620b4682271390aec 100644 --- ethereum/go-ethereum/eth/protocols/eth/handlers.go +++ taikoxyz/taiko-geth/eth/protocols/eth/handlers.go @@ -28,20 +28,19 @@ "github.com/ethereum/go-ethereum/rlp" "github.com/ethereum/go-ethereum/trie" )   -// handleGetBlockHeaders66 is the eth/66 version of handleGetBlockHeaders -func handleGetBlockHeaders66(backend Backend, msg Decoder, peer *Peer) error { +func handleGetBlockHeaders(backend Backend, msg Decoder, peer *Peer) error { // Decode the complex header query - var query GetBlockHeadersPacket66 + var query GetBlockHeadersPacket if err := msg.Decode(&query); err != nil { return fmt.Errorf("%w: message %v: %v", errDecode, msg, err) } - response := ServiceGetBlockHeadersQuery(backend.Chain(), query.GetBlockHeadersPacket, peer) + response := ServiceGetBlockHeadersQuery(backend.Chain(), query.GetBlockHeadersRequest, peer) return peer.ReplyBlockHeadersRLP(query.RequestId, response) }   // ServiceGetBlockHeadersQuery assembles the response to a header query. It is // exposed to allow external packages to test protocol behavior. -func ServiceGetBlockHeadersQuery(chain *core.BlockChain, query *GetBlockHeadersPacket, peer *Peer) []rlp.RawValue { +func ServiceGetBlockHeadersQuery(chain *core.BlockChain, query *GetBlockHeadersRequest, peer *Peer) []rlp.RawValue { if query.Skip == 0 { // The fast path: when the request is for a contiguous segment of headers. return serviceContiguousBlockHeaderQuery(chain, query) @@ -50,7 +49,7 @@ return serviceNonContiguousBlockHeaderQuery(chain, query, peer) } }   -func serviceNonContiguousBlockHeaderQuery(chain *core.BlockChain, query *GetBlockHeadersPacket, peer *Peer) []rlp.RawValue { +func serviceNonContiguousBlockHeaderQuery(chain *core.BlockChain, query *GetBlockHeadersRequest, peer *Peer) []rlp.RawValue { hashMode := query.Origin.Hash != (common.Hash{}) first := true maxNonCanonical := uint64(100) @@ -139,7 +138,7 @@ } return headers }   -func serviceContiguousBlockHeaderQuery(chain *core.BlockChain, query *GetBlockHeadersPacket) []rlp.RawValue { +func serviceContiguousBlockHeaderQuery(chain *core.BlockChain, query *GetBlockHeadersRequest) []rlp.RawValue { count := query.Amount if count > maxHeadersServe { count = maxHeadersServe @@ -202,19 +201,19 @@ return headers } }   -func handleGetBlockBodies66(backend Backend, msg Decoder, peer *Peer) error { +func handleGetBlockBodies(backend Backend, msg Decoder, peer *Peer) error { // Decode the block body retrieval message - var query GetBlockBodiesPacket66 + var query GetBlockBodiesPacket if err := msg.Decode(&query); err != nil { return fmt.Errorf("%w: message %v: %v", errDecode, msg, err) } - response := ServiceGetBlockBodiesQuery(backend.Chain(), query.GetBlockBodiesPacket) + response := ServiceGetBlockBodiesQuery(backend.Chain(), query.GetBlockBodiesRequest) return peer.ReplyBlockBodiesRLP(query.RequestId, response) }   // ServiceGetBlockBodiesQuery assembles the response to a body query. It is // exposed to allow external packages to test protocol behavior. -func ServiceGetBlockBodiesQuery(chain *core.BlockChain, query GetBlockBodiesPacket) []rlp.RawValue { +func ServiceGetBlockBodiesQuery(chain *core.BlockChain, query GetBlockBodiesRequest) []rlp.RawValue { // Gather blocks until the fetch or network limits is reached var ( bytes int @@ -233,56 +232,19 @@ } return bodies }   -func handleGetNodeData66(backend Backend, msg Decoder, peer *Peer) error { - // Decode the trie node data retrieval message - var query GetNodeDataPacket66 - if err := msg.Decode(&query); err != nil { - return fmt.Errorf("%w: message %v: %v", errDecode, msg, err) - } - response := ServiceGetNodeDataQuery(backend.Chain(), query.GetNodeDataPacket) - return peer.ReplyNodeData(query.RequestId, response) -} - -// ServiceGetNodeDataQuery assembles the response to a node data query. It is -// exposed to allow external packages to test protocol behavior. -func ServiceGetNodeDataQuery(chain *core.BlockChain, query GetNodeDataPacket) [][]byte { - // Gather state data until the fetch or network limits is reached - var ( - bytes int - nodes [][]byte - ) - for lookups, hash := range query { - if bytes >= softResponseLimit || len(nodes) >= maxNodeDataServe || - lookups >= 2*maxNodeDataServe { - break - } - // Retrieve the requested state entry - entry, err := chain.TrieNode(hash) - if len(entry) == 0 || err != nil { - // Read the contract code with prefix only to save unnecessary lookups. - entry, err = chain.ContractCodeWithPrefix(hash) - } - if err == nil && len(entry) > 0 { - nodes = append(nodes, entry) - bytes += len(entry) - } - } - return nodes -} - -func handleGetReceipts66(backend Backend, msg Decoder, peer *Peer) error { +func handleGetReceipts(backend Backend, msg Decoder, peer *Peer) error { // Decode the block receipts retrieval message - var query GetReceiptsPacket66 + var query GetReceiptsPacket if err := msg.Decode(&query); err != nil { return fmt.Errorf("%w: message %v: %v", errDecode, msg, err) } - response := ServiceGetReceiptsQuery(backend.Chain(), query.GetReceiptsPacket) + response := ServiceGetReceiptsQuery(backend.Chain(), query.GetReceiptsRequest) return peer.ReplyReceiptsRLP(query.RequestId, response) }   // ServiceGetReceiptsQuery assembles the response to a receipt query. It is // exposed to allow external packages to test protocol behavior. -func ServiceGetReceiptsQuery(chain *core.BlockChain, query GetReceiptsPacket) []rlp.RawValue { +func ServiceGetReceiptsQuery(chain *core.BlockChain, query GetReceiptsRequest) []rlp.RawValue { // Gather state data until the fetch or network limits is reached var ( bytes int @@ -351,15 +313,15 @@ return backend.Handle(peer, ann) }   -func handleBlockHeaders66(backend Backend, msg Decoder, peer *Peer) error { +func handleBlockHeaders(backend Backend, msg Decoder, peer *Peer) error { // A batch of headers arrived to one of our previous requests - res := new(BlockHeadersPacket66) + res := new(BlockHeadersPacket) if err := msg.Decode(res); err != nil { return fmt.Errorf("%w: message %v: %v", errDecode, msg, err) } metadata := func() interface{} { - hashes := make([]common.Hash, len(res.BlockHeadersPacket)) - for i, header := range res.BlockHeadersPacket { + hashes := make([]common.Hash, len(res.BlockHeadersRequest)) + for i, header := range res.BlockHeadersRequest { hashes[i] = header.Hash() } return hashes @@ -367,24 +329,24 @@ } return peer.dispatchResponse(&Response{ id: res.RequestId, code: BlockHeadersMsg, - Res: &res.BlockHeadersPacket, + Res: &res.BlockHeadersRequest, }, metadata) }   -func handleBlockBodies66(backend Backend, msg Decoder, peer *Peer) error { +func handleBlockBodies(backend Backend, msg Decoder, peer *Peer) error { // A batch of block bodies arrived to one of our previous requests - res := new(BlockBodiesPacket66) + res := new(BlockBodiesPacket) if err := msg.Decode(res); err != nil { return fmt.Errorf("%w: message %v: %v", errDecode, msg, err) } metadata := func() interface{} { var ( - txsHashes = make([]common.Hash, len(res.BlockBodiesPacket)) - uncleHashes = make([]common.Hash, len(res.BlockBodiesPacket)) - withdrawalHashes = make([]common.Hash, len(res.BlockBodiesPacket)) + txsHashes = make([]common.Hash, len(res.BlockBodiesResponse)) + uncleHashes = make([]common.Hash, len(res.BlockBodiesResponse)) + withdrawalHashes = make([]common.Hash, len(res.BlockBodiesResponse)) ) hasher := trie.NewStackTrie(nil) - for i, body := range res.BlockBodiesPacket { + for i, body := range res.BlockBodiesResponse { txsHashes[i] = types.DeriveSha(types.Transactions(body.Transactions), hasher) uncleHashes[i] = types.CalcUncleHash(body.Uncles) if body.Withdrawals != nil { @@ -396,33 +358,20 @@ } return peer.dispatchResponse(&Response{ id: res.RequestId, code: BlockBodiesMsg, - Res: &res.BlockBodiesPacket, + Res: &res.BlockBodiesResponse, }, metadata) }   -func handleNodeData66(backend Backend, msg Decoder, peer *Peer) error { - // A batch of node state data arrived to one of our previous requests - res := new(NodeDataPacket66) - if err := msg.Decode(res); err != nil { - return fmt.Errorf("%w: message %v: %v", errDecode, msg, err) - } - return peer.dispatchResponse(&Response{ - id: res.RequestId, - code: NodeDataMsg, - Res: &res.NodeDataPacket, - }, nil) // No post-processing, we're not using this packet anymore -} - -func handleReceipts66(backend Backend, msg Decoder, peer *Peer) error { +func handleReceipts(backend Backend, msg Decoder, peer *Peer) error { // A batch of receipts arrived to one of our previous requests - res := new(ReceiptsPacket66) + res := new(ReceiptsPacket) if err := msg.Decode(res); err != nil { return fmt.Errorf("%w: message %v: %v", errDecode, msg, err) } metadata := func() interface{} { hasher := trie.NewStackTrie(nil) - hashes := make([]common.Hash, len(res.ReceiptsPacket)) - for i, receipt := range res.ReceiptsPacket { + hashes := make([]common.Hash, len(res.ReceiptsResponse)) + for i, receipt := range res.ReceiptsResponse { hashes[i] = types.DeriveSha(types.Receipts(receipt), hasher) } return hashes @@ -430,17 +379,17 @@ } return peer.dispatchResponse(&Response{ id: res.RequestId, code: ReceiptsMsg, - Res: &res.ReceiptsPacket, + Res: &res.ReceiptsResponse, }, metadata) }   -func handleNewPooledTransactionHashes66(backend Backend, msg Decoder, peer *Peer) error { +func handleNewPooledTransactionHashes67(backend Backend, msg Decoder, peer *Peer) error { // New transaction announcement arrived, make sure we have // a valid and fresh chain to handle them if !backend.AcceptTxs() { return nil } - ann := new(NewPooledTransactionHashesPacket66) + ann := new(NewPooledTransactionHashesPacket67) if err := msg.Decode(ann); err != nil { return fmt.Errorf("%w: message %v: %v", errDecode, msg, err) } @@ -471,17 +420,17 @@ } return backend.Handle(peer, ann) }   -func handleGetPooledTransactions66(backend Backend, msg Decoder, peer *Peer) error { +func handleGetPooledTransactions(backend Backend, msg Decoder, peer *Peer) error { // Decode the pooled transactions retrieval message - var query GetPooledTransactionsPacket66 + var query GetPooledTransactionsPacket if err := msg.Decode(&query); err != nil { return fmt.Errorf("%w: message %v: %v", errDecode, msg, err) } - hashes, txs := answerGetPooledTransactions(backend, query.GetPooledTransactionsPacket, peer) + hashes, txs := answerGetPooledTransactions(backend, query.GetPooledTransactionsRequest) return peer.ReplyPooledTransactionsRLP(query.RequestId, hashes, txs) }   -func answerGetPooledTransactions(backend Backend, query GetPooledTransactionsPacket, peer *Peer) ([]common.Hash, []rlp.RawValue) { +func answerGetPooledTransactions(backend Backend, query GetPooledTransactionsRequest) ([]common.Hash, []rlp.RawValue) { // Gather transactions until the fetch or network limits is reached var ( bytes int @@ -498,7 +447,7 @@ if tx == nil { continue } // If known, encode and queue for response packet - if encoded, err := rlp.EncodeToBytes(tx.Tx); err != nil { + if encoded, err := rlp.EncodeToBytes(tx); err != nil { log.Error("Failed to encode transaction", "err", err) } else { hashes = append(hashes, hash) @@ -529,17 +478,17 @@ } return backend.Handle(peer, &txs) }   -func handlePooledTransactions66(backend Backend, msg Decoder, peer *Peer) error { +func handlePooledTransactions(backend Backend, msg Decoder, peer *Peer) error { // Transactions arrived, make sure we have a valid and fresh chain to handle them if !backend.AcceptTxs() { return nil } // Transactions can be processed, parse all of them and deliver to the pool - var txs PooledTransactionsPacket66 + var txs PooledTransactionsPacket if err := msg.Decode(&txs); err != nil { return fmt.Errorf("%w: message %v: %v", errDecode, msg, err) } - for i, tx := range txs.PooledTransactionsPacket { + for i, tx := range txs.PooledTransactionsResponse { // Validate and mark the remote transaction if tx == nil { return fmt.Errorf("%w: transaction %d is nil", errDecode, i) @@ -548,5 +497,5 @@ peer.markTransaction(tx.Hash()) } requestTracker.Fulfil(peer.id, peer.version, PooledTransactionsMsg, txs.RequestId)   - return backend.Handle(peer, &txs.PooledTransactionsPacket) + return backend.Handle(peer, &txs.PooledTransactionsResponse) }
diff --git ethereum/go-ethereum/eth/protocols/eth/handshake_test.go taikoxyz/taiko-geth/eth/protocols/eth/handshake_test.go index 5c6727d91cc76ebb1b1d52b5881ae02a70721cf4..d96cfc8165b5075d1a1b16c36a9e574197683067 100644 --- ethereum/go-ethereum/eth/protocols/eth/handshake_test.go +++ taikoxyz/taiko-geth/eth/protocols/eth/handshake_test.go @@ -27,7 +27,8 @@ "github.com/ethereum/go-ethereum/p2p/enode" )   // Tests that handshake failures are detected and reported correctly. -func TestHandshake66(t *testing.T) { testHandshake(t, ETH66) } +func TestHandshake67(t *testing.T) { testHandshake(t, ETH67) } +func TestHandshake68(t *testing.T) { testHandshake(t, ETH68) }   func testHandshake(t *testing.T, protocol uint) { t.Parallel() @@ -40,7 +41,7 @@ var ( genesis = backend.chain.Genesis() head = backend.chain.CurrentBlock() td = backend.chain.GetTd(head.Hash(), head.Number.Uint64()) - forkID = forkid.NewID(backend.chain.Config(), backend.chain.Genesis().Hash(), backend.chain.CurrentHeader().Number.Uint64(), backend.chain.CurrentHeader().Time) + forkID = forkid.NewID(backend.chain.Config(), backend.chain.Genesis(), backend.chain.CurrentHeader().Number.Uint64(), backend.chain.CurrentHeader().Time) ) tests := []struct { code uint64
diff --git ethereum/go-ethereum/eth/protocols/eth/peer.go taikoxyz/taiko-geth/eth/protocols/eth/peer.go index 219f486c8e6f2df2ab321042d48be02dfce090cf..938af0cab0df294ec354883a4daab515c6051de7 100644 --- ethereum/go-ethereum/eth/protocols/eth/peer.go +++ taikoxyz/taiko-geth/eth/protocols/eth/peer.go @@ -219,7 +219,7 @@ // not be managed directly. func (p *Peer) sendPooledTransactionHashes66(hashes []common.Hash) error { // Mark all the transactions as known, but ensure we don't overflow our limits p.knownTxs.Add(hashes...) - return p2p.Send(p.rw, NewPooledTransactionHashesMsg, NewPooledTransactionHashesPacket66(hashes)) + return p2p.Send(p.rw, NewPooledTransactionHashesMsg, NewPooledTransactionHashesPacket67(hashes)) }   // sendPooledTransactionHashes68 sends transaction hashes (tagged with their type @@ -248,15 +248,15 @@ p.Log().Debug("Dropping transaction announcement", "count", len(hashes)) } }   -// ReplyPooledTransactionsRLP is the eth/66 version of SendPooledTransactionsRLP. +// ReplyPooledTransactionsRLP is the response to RequestTxs. func (p *Peer) ReplyPooledTransactionsRLP(id uint64, hashes []common.Hash, txs []rlp.RawValue) error { // Mark all the transactions as known, but ensure we don't overflow our limits p.knownTxs.Add(hashes...)   - // Not packed into PooledTransactionsPacket to avoid RLP decoding - return p2p.Send(p.rw, PooledTransactionsMsg, &PooledTransactionsRLPPacket66{ - RequestId: id, - PooledTransactionsRLPPacket: txs, + // Not packed into PooledTransactionsResponse to avoid RLP decoding + return p2p.Send(p.rw, PooledTransactionsMsg, &PooledTransactionsRLPPacket{ + RequestId: id, + PooledTransactionsRLPResponse: txs, }) }   @@ -309,36 +309,28 @@ p.Log().Debug("Dropping block propagation", "number", block.NumberU64(), "hash", block.Hash()) } }   -// ReplyBlockHeadersRLP is the eth/66 response to GetBlockHeaders. +// ReplyBlockHeadersRLP is the response to GetBlockHeaders. func (p *Peer) ReplyBlockHeadersRLP(id uint64, headers []rlp.RawValue) error { - return p2p.Send(p.rw, BlockHeadersMsg, &BlockHeadersRLPPacket66{ - RequestId: id, - BlockHeadersRLPPacket: headers, + return p2p.Send(p.rw, BlockHeadersMsg, &BlockHeadersRLPPacket{ + RequestId: id, + BlockHeadersRLPResponse: headers, }) }   -// ReplyBlockBodiesRLP is the eth/66 response to GetBlockBodies. +// ReplyBlockBodiesRLP is the response to GetBlockBodies. func (p *Peer) ReplyBlockBodiesRLP(id uint64, bodies []rlp.RawValue) error { - // Not packed into BlockBodiesPacket to avoid RLP decoding - return p2p.Send(p.rw, BlockBodiesMsg, &BlockBodiesRLPPacket66{ - RequestId: id, - BlockBodiesRLPPacket: bodies, - }) -} - -// ReplyNodeData is the eth/66 response to GetNodeData. -func (p *Peer) ReplyNodeData(id uint64, data [][]byte) error { - return p2p.Send(p.rw, NodeDataMsg, &NodeDataPacket66{ - RequestId: id, - NodeDataPacket: data, + // Not packed into BlockBodiesResponse to avoid RLP decoding + return p2p.Send(p.rw, BlockBodiesMsg, &BlockBodiesRLPPacket{ + RequestId: id, + BlockBodiesRLPResponse: bodies, }) }   -// ReplyReceiptsRLP is the eth/66 response to GetReceipts. +// ReplyReceiptsRLP is the response to GetReceipts. func (p *Peer) ReplyReceiptsRLP(id uint64, receipts []rlp.RawValue) error { - return p2p.Send(p.rw, ReceiptsMsg, &ReceiptsRLPPacket66{ - RequestId: id, - ReceiptsRLPPacket: receipts, + return p2p.Send(p.rw, ReceiptsMsg, &ReceiptsRLPPacket{ + RequestId: id, + ReceiptsRLPResponse: receipts, }) }   @@ -353,9 +345,9 @@ id: id, sink: sink, code: GetBlockHeadersMsg, want: BlockHeadersMsg, - data: &GetBlockHeadersPacket66{ + data: &GetBlockHeadersPacket{ RequestId: id, - GetBlockHeadersPacket: &GetBlockHeadersPacket{ + GetBlockHeadersRequest: &GetBlockHeadersRequest{ Origin: HashOrNumber{Hash: hash}, Amount: uint64(1), Skip: uint64(0), @@ -380,9 +372,9 @@ id: id, sink: sink, code: GetBlockHeadersMsg, want: BlockHeadersMsg, - data: &GetBlockHeadersPacket66{ + data: &GetBlockHeadersPacket{ RequestId: id, - GetBlockHeadersPacket: &GetBlockHeadersPacket{ + GetBlockHeadersRequest: &GetBlockHeadersRequest{ Origin: HashOrNumber{Hash: origin}, Amount: uint64(amount), Skip: uint64(skip), @@ -407,9 +399,9 @@ id: id, sink: sink, code: GetBlockHeadersMsg, want: BlockHeadersMsg, - data: &GetBlockHeadersPacket66{ + data: &GetBlockHeadersPacket{ RequestId: id, - GetBlockHeadersPacket: &GetBlockHeadersPacket{ + GetBlockHeadersRequest: &GetBlockHeadersRequest{ Origin: HashOrNumber{Number: origin}, Amount: uint64(amount), Skip: uint64(skip), @@ -434,31 +426,9 @@ id: id, sink: sink, code: GetBlockBodiesMsg, want: BlockBodiesMsg, - data: &GetBlockBodiesPacket66{ - RequestId: id, - GetBlockBodiesPacket: hashes, - }, - } - if err := p.dispatchRequest(req); err != nil { - return nil, err - } - return req, nil -} - -// RequestNodeData fetches a batch of arbitrary data from a node's known state -// data, corresponding to the specified hashes. -func (p *Peer) RequestNodeData(hashes []common.Hash, sink chan *Response) (*Request, error) { - p.Log().Debug("Fetching batch of state data", "count", len(hashes)) - id := rand.Uint64() - - req := &Request{ - id: id, - sink: sink, - code: GetNodeDataMsg, - want: NodeDataMsg, - data: &GetNodeDataPacket66{ - RequestId: id, - GetNodeDataPacket: hashes, + data: &GetBlockBodiesPacket{ + RequestId: id, + GetBlockBodiesRequest: hashes, }, } if err := p.dispatchRequest(req); err != nil { @@ -477,9 +447,9 @@ id: id, sink: sink, code: GetReceiptsMsg, want: ReceiptsMsg, - data: &GetReceiptsPacket66{ - RequestId: id, - GetReceiptsPacket: hashes, + data: &GetReceiptsPacket{ + RequestId: id, + GetReceiptsRequest: hashes, }, } if err := p.dispatchRequest(req); err != nil { @@ -494,9 +464,9 @@ p.Log().Debug("Fetching batch of transactions", "count", len(hashes)) id := rand.Uint64()   requestTracker.Track(p.id, p.version, GetPooledTransactionsMsg, PooledTransactionsMsg, id) - return p2p.Send(p.rw, GetPooledTransactionsMsg, &GetPooledTransactionsPacket66{ - RequestId: id, - GetPooledTransactionsPacket: hashes, + return p2p.Send(p.rw, GetPooledTransactionsMsg, &GetPooledTransactionsPacket{ + RequestId: id, + GetPooledTransactionsRequest: hashes, }) }
diff --git ethereum/go-ethereum/eth/protocols/eth/protocol.go taikoxyz/taiko-geth/eth/protocols/eth/protocol.go index 4b9f5ad6ba5286963f7bd12a91475c5a940248e4..0f44f83de159cb38c430b9f0a0a37b70a02f33f6 100644 --- ethereum/go-ethereum/eth/protocols/eth/protocol.go +++ taikoxyz/taiko-geth/eth/protocols/eth/protocol.go @@ -30,7 +30,6 @@ )   // Constants to match up protocol versions and messages const ( - ETH66 = 66 ETH67 = 67 ETH68 = 68 ) @@ -41,11 +40,11 @@ const ProtocolName = "eth"   // ProtocolVersions are the supported versions of the `eth` protocol (first // is primary). -var ProtocolVersions = []uint{ETH68, ETH67, ETH66} +var ProtocolVersions = []uint{ETH68, ETH67}   // protocolLengths are the number of implemented message corresponding to // different protocol versions. -var protocolLengths = map[uint]uint64{ETH68: 17, ETH67: 17, ETH66: 17} +var protocolLengths = map[uint]uint64{ETH68: 17, ETH67: 17}   // maxMessageSize is the maximum cap on the size of a protocol message. const maxMessageSize = 10 * 1024 * 1024 @@ -62,8 +61,6 @@ NewBlockMsg = 0x07 NewPooledTransactionHashesMsg = 0x08 GetPooledTransactionsMsg = 0x09 PooledTransactionsMsg = 0x0a - GetNodeDataMsg = 0x0d - NodeDataMsg = 0x0e GetReceiptsMsg = 0x0f ReceiptsMsg = 0x10 ) @@ -85,7 +82,7 @@ Name() string // Name returns a string corresponding to the message type. Kind() byte // Kind returns the message type. }   -// StatusPacket is the network packet for the status message for eth/64 and later. +// StatusPacket is the network packet for the status message. type StatusPacket struct { ProtocolVersion uint32 NetworkID uint64 @@ -118,18 +115,18 @@ // TransactionsPacket is the network packet for broadcasting new transactions. type TransactionsPacket []*types.Transaction   -// GetBlockHeadersPacket represents a block header query. -type GetBlockHeadersPacket struct { +// GetBlockHeadersRequest represents a block header query. +type GetBlockHeadersRequest struct { Origin HashOrNumber // Block from which to retrieve headers Amount uint64 // Maximum number of headers to retrieve Skip uint64 // Blocks to skip between consecutive headers Reverse bool // Query direction (false = rising towards latest, true = falling towards genesis) }   -// GetBlockHeadersPacket66 represents a block header query over eth/66 -type GetBlockHeadersPacket66 struct { +// GetBlockHeadersPacket represents a block header query with request ID wrapping. +type GetBlockHeadersPacket struct { RequestId uint64 - *GetBlockHeadersPacket + *GetBlockHeadersRequest }   // HashOrNumber is a combined field for specifying an origin block. @@ -168,23 +165,23 @@ return fmt.Errorf("invalid input size %d for origin", size) } }   -// BlockHeadersPacket represents a block header response. -type BlockHeadersPacket []*types.Header +// BlockHeadersRequest represents a block header response. +type BlockHeadersRequest []*types.Header   -// BlockHeadersPacket66 represents a block header response over eth/66. -type BlockHeadersPacket66 struct { +// BlockHeadersPacket represents a block header response over with request ID wrapping. +type BlockHeadersPacket struct { RequestId uint64 - BlockHeadersPacket + BlockHeadersRequest }   -// BlockHeadersRLPPacket represents a block header response, to use when we already +// BlockHeadersRLPResponse represents a block header response, to use when we already // have the headers rlp encoded. -type BlockHeadersRLPPacket []rlp.RawValue +type BlockHeadersRLPResponse []rlp.RawValue   -// BlockHeadersRLPPacket66 represents a block header response over eth/66. -type BlockHeadersRLPPacket66 struct { +// BlockHeadersRLPPacket represents a block header response with request ID wrapping. +type BlockHeadersRLPPacket struct { RequestId uint64 - BlockHeadersRLPPacket + BlockHeadersRLPResponse }   // NewBlockPacket is the network packet for the block propagation message. @@ -206,33 +203,34 @@ } return nil }   -// GetBlockBodiesPacket represents a block body query. -type GetBlockBodiesPacket []common.Hash +// GetBlockBodiesRequest represents a block body query. +type GetBlockBodiesRequest []common.Hash   -// GetBlockBodiesPacket66 represents a block body query over eth/66. -type GetBlockBodiesPacket66 struct { +// GetBlockBodiesPacket represents a block body query with request ID wrapping. +type GetBlockBodiesPacket struct { RequestId uint64 - GetBlockBodiesPacket + GetBlockBodiesRequest }   -// BlockBodiesPacket is the network packet for block content distribution. -type BlockBodiesPacket []*BlockBody +// BlockBodiesResponse is the network packet for block content distribution. +type BlockBodiesResponse []*BlockBody   -// BlockBodiesPacket66 is the network packet for block content distribution over eth/66. -type BlockBodiesPacket66 struct { +// BlockBodiesPacket is the network packet for block content distribution with +// request ID wrapping. +type BlockBodiesPacket struct { RequestId uint64 - BlockBodiesPacket + BlockBodiesResponse }   -// BlockBodiesRLPPacket is used for replying to block body requests, in cases +// BlockBodiesRLPResponse is used for replying to block body requests, in cases // where we already have them RLP-encoded, and thus can avoid the decode-encode // roundtrip. -type BlockBodiesRLPPacket []rlp.RawValue +type BlockBodiesRLPResponse []rlp.RawValue   -// BlockBodiesRLPPacket66 is the BlockBodiesRLPPacket over eth/66 -type BlockBodiesRLPPacket66 struct { +// BlockBodiesRLPPacket is the BlockBodiesRLPResponse with request ID wrapping. +type BlockBodiesRLPPacket struct { RequestId uint64 - BlockBodiesRLPPacket + BlockBodiesRLPResponse }   // BlockBody represents the data content of a single block. @@ -244,7 +242,7 @@ }   // Unpack retrieves the transactions and uncles from the range packet and returns // them in a split flat format that's more consistent with the internal data structures. -func (p *BlockBodiesPacket) Unpack() ([][]*types.Transaction, [][]*types.Header, [][]*types.Withdrawal) { +func (p *BlockBodiesResponse) Unpack() ([][]*types.Transaction, [][]*types.Header, [][]*types.Withdrawal) { // TODO(matt): add support for withdrawals to fetchers var ( txset = make([][]*types.Transaction, len(*p)) @@ -257,53 +255,36 @@ } return txset, uncleset, withdrawalset }   -// GetNodeDataPacket represents a trie node data query. -type GetNodeDataPacket []common.Hash +// GetReceiptsRequest represents a block receipts query. +type GetReceiptsRequest []common.Hash   -// GetNodeDataPacket66 represents a trie node data query over eth/66. -type GetNodeDataPacket66 struct { +// GetReceiptsPacket represents a block receipts query with request ID wrapping. +type GetReceiptsPacket struct { RequestId uint64 - GetNodeDataPacket + GetReceiptsRequest }   -// NodeDataPacket is the network packet for trie node data distribution. -type NodeDataPacket [][]byte +// ReceiptsResponse is the network packet for block receipts distribution. +type ReceiptsResponse [][]*types.Receipt   -// NodeDataPacket66 is the network packet for trie node data distribution over eth/66. -type NodeDataPacket66 struct { +// ReceiptsPacket is the network packet for block receipts distribution with +// request ID wrapping. +type ReceiptsPacket struct { RequestId uint64 - NodeDataPacket + ReceiptsResponse }   -// GetReceiptsPacket represents a block receipts query. -type GetReceiptsPacket []common.Hash +// ReceiptsRLPResponse is used for receipts, when we already have it encoded +type ReceiptsRLPResponse []rlp.RawValue   -// GetReceiptsPacket66 represents a block receipts query over eth/66. -type GetReceiptsPacket66 struct { +// ReceiptsRLPPacket is ReceiptsRLPResponse with request ID wrapping. +type ReceiptsRLPPacket struct { RequestId uint64 - GetReceiptsPacket + ReceiptsRLPResponse }   -// ReceiptsPacket is the network packet for block receipts distribution. -type ReceiptsPacket [][]*types.Receipt - -// ReceiptsPacket66 is the network packet for block receipts distribution over eth/66. -type ReceiptsPacket66 struct { - RequestId uint64 - ReceiptsPacket -} - -// ReceiptsRLPPacket is used for receipts, when we already have it encoded -type ReceiptsRLPPacket []rlp.RawValue - -// ReceiptsRLPPacket66 is the eth-66 version of ReceiptsRLPPacket -type ReceiptsRLPPacket66 struct { - RequestId uint64 - ReceiptsRLPPacket -} - -// NewPooledTransactionHashesPacket66 represents a transaction announcement packet on eth/66 and eth/67. -type NewPooledTransactionHashesPacket66 []common.Hash +// NewPooledTransactionHashesPacket67 represents a transaction announcement packet on eth/67. +type NewPooledTransactionHashesPacket67 []common.Hash   // NewPooledTransactionHashesPacket68 represents a transaction announcement packet on eth/68 and newer. type NewPooledTransactionHashesPacket68 struct { @@ -312,31 +293,33 @@ Sizes []uint32 Hashes []common.Hash }   -// GetPooledTransactionsPacket represents a transaction query. -type GetPooledTransactionsPacket []common.Hash +// GetPooledTransactionsRequest represents a transaction query. +type GetPooledTransactionsRequest []common.Hash   -type GetPooledTransactionsPacket66 struct { +// GetPooledTransactionsPacket represents a transaction query with request ID wrapping. +type GetPooledTransactionsPacket struct { RequestId uint64 - GetPooledTransactionsPacket + GetPooledTransactionsRequest }   -// PooledTransactionsPacket is the network packet for transaction distribution. -type PooledTransactionsPacket []*types.Transaction +// PooledTransactionsResponse is the network packet for transaction distribution. +type PooledTransactionsResponse []*types.Transaction   -// PooledTransactionsPacket66 is the network packet for transaction distribution over eth/66. -type PooledTransactionsPacket66 struct { +// PooledTransactionsPacket is the network packet for transaction distribution +// with request ID wrapping. +type PooledTransactionsPacket struct { RequestId uint64 - PooledTransactionsPacket + PooledTransactionsResponse }   -// PooledTransactionsRLPPacket is the network packet for transaction distribution, used +// PooledTransactionsRLPResponse is the network packet for transaction distribution, used // in the cases we already have them in rlp-encoded form -type PooledTransactionsRLPPacket []rlp.RawValue +type PooledTransactionsRLPResponse []rlp.RawValue   -// PooledTransactionsRLPPacket66 is the eth/66 form of PooledTransactionsRLPPacket -type PooledTransactionsRLPPacket66 struct { +// PooledTransactionsRLPPacket is PooledTransactionsRLPResponse with request ID wrapping. +type PooledTransactionsRLPPacket struct { RequestId uint64 - PooledTransactionsRLPPacket + PooledTransactionsRLPResponse }   func (*StatusPacket) Name() string { return "Status" } @@ -348,40 +331,34 @@ func (*TransactionsPacket) Name() string { return "Transactions" } func (*TransactionsPacket) Kind() byte { return TransactionsMsg }   -func (*GetBlockHeadersPacket) Name() string { return "GetBlockHeaders" } -func (*GetBlockHeadersPacket) Kind() byte { return GetBlockHeadersMsg } +func (*GetBlockHeadersRequest) Name() string { return "GetBlockHeaders" } +func (*GetBlockHeadersRequest) Kind() byte { return GetBlockHeadersMsg }   -func (*BlockHeadersPacket) Name() string { return "BlockHeaders" } -func (*BlockHeadersPacket) Kind() byte { return BlockHeadersMsg } +func (*BlockHeadersRequest) Name() string { return "BlockHeaders" } +func (*BlockHeadersRequest) Kind() byte { return BlockHeadersMsg }   -func (*GetBlockBodiesPacket) Name() string { return "GetBlockBodies" } -func (*GetBlockBodiesPacket) Kind() byte { return GetBlockBodiesMsg } +func (*GetBlockBodiesRequest) Name() string { return "GetBlockBodies" } +func (*GetBlockBodiesRequest) Kind() byte { return GetBlockBodiesMsg }   -func (*BlockBodiesPacket) Name() string { return "BlockBodies" } -func (*BlockBodiesPacket) Kind() byte { return BlockBodiesMsg } +func (*BlockBodiesResponse) Name() string { return "BlockBodies" } +func (*BlockBodiesResponse) Kind() byte { return BlockBodiesMsg }   func (*NewBlockPacket) Name() string { return "NewBlock" } func (*NewBlockPacket) Kind() byte { return NewBlockMsg }   -func (*NewPooledTransactionHashesPacket66) Name() string { return "NewPooledTransactionHashes" } -func (*NewPooledTransactionHashesPacket66) Kind() byte { return NewPooledTransactionHashesMsg } +func (*NewPooledTransactionHashesPacket67) Name() string { return "NewPooledTransactionHashes" } +func (*NewPooledTransactionHashesPacket67) Kind() byte { return NewPooledTransactionHashesMsg } func (*NewPooledTransactionHashesPacket68) Name() string { return "NewPooledTransactionHashes" } func (*NewPooledTransactionHashesPacket68) Kind() byte { return NewPooledTransactionHashesMsg }   -func (*GetPooledTransactionsPacket) Name() string { return "GetPooledTransactions" } -func (*GetPooledTransactionsPacket) Kind() byte { return GetPooledTransactionsMsg } - -func (*PooledTransactionsPacket) Name() string { return "PooledTransactions" } -func (*PooledTransactionsPacket) Kind() byte { return PooledTransactionsMsg } - -func (*GetNodeDataPacket) Name() string { return "GetNodeData" } -func (*GetNodeDataPacket) Kind() byte { return GetNodeDataMsg } +func (*GetPooledTransactionsRequest) Name() string { return "GetPooledTransactions" } +func (*GetPooledTransactionsRequest) Kind() byte { return GetPooledTransactionsMsg }   -func (*NodeDataPacket) Name() string { return "NodeData" } -func (*NodeDataPacket) Kind() byte { return NodeDataMsg } +func (*PooledTransactionsResponse) Name() string { return "PooledTransactions" } +func (*PooledTransactionsResponse) Kind() byte { return PooledTransactionsMsg }   -func (*GetReceiptsPacket) Name() string { return "GetReceipts" } -func (*GetReceiptsPacket) Kind() byte { return GetReceiptsMsg } +func (*GetReceiptsRequest) Name() string { return "GetReceipts" } +func (*GetReceiptsRequest) Kind() byte { return GetReceiptsMsg }   -func (*ReceiptsPacket) Name() string { return "Receipts" } -func (*ReceiptsPacket) Kind() byte { return ReceiptsMsg } +func (*ReceiptsResponse) Name() string { return "Receipts" } +func (*ReceiptsResponse) Kind() byte { return ReceiptsMsg }
diff --git ethereum/go-ethereum/eth/protocols/eth/protocol_test.go taikoxyz/taiko-geth/eth/protocols/eth/protocol_test.go index a86fbb0a6906ae9480e6d94c18c541fd79af8cbd..bc2545dea286a6b8cd633dd5dc54866d7175162f 100644 --- ethereum/go-ethereum/eth/protocols/eth/protocol_test.go +++ taikoxyz/taiko-geth/eth/protocols/eth/protocol_test.go @@ -35,19 +35,19 @@ hash[i] = byte(i) } // Assemble some table driven tests tests := []struct { - packet *GetBlockHeadersPacket + packet *GetBlockHeadersRequest fail bool }{ // Providing the origin as either a hash or a number should both work - {fail: false, packet: &GetBlockHeadersPacket{Origin: HashOrNumber{Number: 314}}}, - {fail: false, packet: &GetBlockHeadersPacket{Origin: HashOrNumber{Hash: hash}}}, + {fail: false, packet: &GetBlockHeadersRequest{Origin: HashOrNumber{Number: 314}}}, + {fail: false, packet: &GetBlockHeadersRequest{Origin: HashOrNumber{Hash: hash}}},   // Providing arbitrary query field should also work - {fail: false, packet: &GetBlockHeadersPacket{Origin: HashOrNumber{Number: 314}, Amount: 314, Skip: 1, Reverse: true}}, - {fail: false, packet: &GetBlockHeadersPacket{Origin: HashOrNumber{Hash: hash}, Amount: 314, Skip: 1, Reverse: true}}, + {fail: false, packet: &GetBlockHeadersRequest{Origin: HashOrNumber{Number: 314}, Amount: 314, Skip: 1, Reverse: true}}, + {fail: false, packet: &GetBlockHeadersRequest{Origin: HashOrNumber{Hash: hash}, Amount: 314, Skip: 1, Reverse: true}},   // Providing both the origin hash and origin number must fail - {fail: true, packet: &GetBlockHeadersPacket{Origin: HashOrNumber{Hash: hash, Number: 314}}}, + {fail: true, packet: &GetBlockHeadersRequest{Origin: HashOrNumber{Hash: hash, Number: 314}}}, } // Iterate over each of the tests and try to encode and then decode for i, tt := range tests { @@ -58,7 +58,7 @@ } else if err == nil && tt.fail { t.Fatalf("test %d: encode should have failed", i) } if !tt.fail { - packet := new(GetBlockHeadersPacket) + packet := new(GetBlockHeadersRequest) if err := rlp.DecodeBytes(bytes, packet); err != nil { t.Fatalf("test %d: failed to decode packet: %v", i, err) } @@ -70,46 +70,40 @@ } } }   -// TestEth66EmptyMessages tests encoding of empty eth66 messages -func TestEth66EmptyMessages(t *testing.T) { +// TestEmptyMessages tests encoding of empty messages. +func TestEmptyMessages(t *testing.T) { // All empty messages encodes to the same format want := common.FromHex("c4820457c0")   for i, msg := range []interface{}{ // Headers - GetBlockHeadersPacket66{1111, nil}, - BlockHeadersPacket66{1111, nil}, + GetBlockHeadersPacket{1111, nil}, + BlockHeadersPacket{1111, nil}, // Bodies - GetBlockBodiesPacket66{1111, nil}, - BlockBodiesPacket66{1111, nil}, - BlockBodiesRLPPacket66{1111, nil}, - // Node data - GetNodeDataPacket66{1111, nil}, - NodeDataPacket66{1111, nil}, + GetBlockBodiesPacket{1111, nil}, + BlockBodiesPacket{1111, nil}, + BlockBodiesRLPPacket{1111, nil}, // Receipts - GetReceiptsPacket66{1111, nil}, - ReceiptsPacket66{1111, nil}, + GetReceiptsPacket{1111, nil}, + ReceiptsPacket{1111, nil}, // Transactions - GetPooledTransactionsPacket66{1111, nil}, - PooledTransactionsPacket66{1111, nil}, - PooledTransactionsRLPPacket66{1111, nil}, + GetPooledTransactionsPacket{1111, nil}, + PooledTransactionsPacket{1111, nil}, + PooledTransactionsRLPPacket{1111, nil},   // Headers - BlockHeadersPacket66{1111, BlockHeadersPacket([]*types.Header{})}, + BlockHeadersPacket{1111, BlockHeadersRequest([]*types.Header{})}, // Bodies - GetBlockBodiesPacket66{1111, GetBlockBodiesPacket([]common.Hash{})}, - BlockBodiesPacket66{1111, BlockBodiesPacket([]*BlockBody{})}, - BlockBodiesRLPPacket66{1111, BlockBodiesRLPPacket([]rlp.RawValue{})}, - // Node data - GetNodeDataPacket66{1111, GetNodeDataPacket([]common.Hash{})}, - NodeDataPacket66{1111, NodeDataPacket([][]byte{})}, + GetBlockBodiesPacket{1111, GetBlockBodiesRequest([]common.Hash{})}, + BlockBodiesPacket{1111, BlockBodiesResponse([]*BlockBody{})}, + BlockBodiesRLPPacket{1111, BlockBodiesRLPResponse([]rlp.RawValue{})}, // Receipts - GetReceiptsPacket66{1111, GetReceiptsPacket([]common.Hash{})}, - ReceiptsPacket66{1111, ReceiptsPacket([][]*types.Receipt{})}, + GetReceiptsPacket{1111, GetReceiptsRequest([]common.Hash{})}, + ReceiptsPacket{1111, ReceiptsResponse([][]*types.Receipt{})}, // Transactions - GetPooledTransactionsPacket66{1111, GetPooledTransactionsPacket([]common.Hash{})}, - PooledTransactionsPacket66{1111, PooledTransactionsPacket([]*types.Transaction{})}, - PooledTransactionsRLPPacket66{1111, PooledTransactionsRLPPacket([]rlp.RawValue{})}, + GetPooledTransactionsPacket{1111, GetPooledTransactionsRequest([]common.Hash{})}, + PooledTransactionsPacket{1111, PooledTransactionsResponse([]*types.Transaction{})}, + PooledTransactionsRLPPacket{1111, PooledTransactionsRLPResponse([]rlp.RawValue{})}, } { if have, _ := rlp.EncodeToBytes(msg); !bytes.Equal(have, want) { t.Errorf("test %d, type %T, have\n\t%x\nwant\n\t%x", i, msg, have, want) @@ -117,8 +111,8 @@ } } }   -// TestEth66Messages tests the encoding of all redefined eth66 messages -func TestEth66Messages(t *testing.T) { +// TestMessages tests the encoding of all messages. +func TestMessages(t *testing.T) { // Some basic structs used during testing var ( header *types.Header @@ -169,10 +163,6 @@ hashes = []common.Hash{ common.HexToHash("deadc0de"), common.HexToHash("feedbeef"), } - byteSlices := [][]byte{ - common.FromHex("deadc0de"), - common.FromHex("feedbeef"), - } // init the receipts { receipts = []*types.Receipt{ @@ -203,59 +193,51 @@ message interface{} want []byte }{ { - GetBlockHeadersPacket66{1111, &GetBlockHeadersPacket{HashOrNumber{hashes[0], 0}, 5, 5, false}}, + GetBlockHeadersPacket{1111, &GetBlockHeadersRequest{HashOrNumber{hashes[0], 0}, 5, 5, false}}, common.FromHex("e8820457e4a000000000000000000000000000000000000000000000000000000000deadc0de050580"), }, { - GetBlockHeadersPacket66{1111, &GetBlockHeadersPacket{HashOrNumber{common.Hash{}, 9999}, 5, 5, false}}, + GetBlockHeadersPacket{1111, &GetBlockHeadersRequest{HashOrNumber{common.Hash{}, 9999}, 5, 5, false}}, common.FromHex("ca820457c682270f050580"), }, { - BlockHeadersPacket66{1111, BlockHeadersPacket{header}}, + BlockHeadersPacket{1111, BlockHeadersRequest{header}}, common.FromHex("f90202820457f901fcf901f9a00000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000000940000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000000b90100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008208ae820d0582115c8215b3821a0a827788a00000000000000000000000000000000000000000000000000000000000000000880000000000000000"), }, { - GetBlockBodiesPacket66{1111, GetBlockBodiesPacket(hashes)}, + GetBlockBodiesPacket{1111, GetBlockBodiesRequest(hashes)}, common.FromHex("f847820457f842a000000000000000000000000000000000000000000000000000000000deadc0dea000000000000000000000000000000000000000000000000000000000feedbeef"), }, { - BlockBodiesPacket66{1111, BlockBodiesPacket([]*BlockBody{blockBody})}, + BlockBodiesPacket{1111, BlockBodiesResponse([]*BlockBody{blockBody})}, common.FromHex("f902dc820457f902d6f902d3f8d2f867088504a817c8088302e2489435353535353535353535353535353535353535358202008025a064b1702d9298fee62dfeccc57d322a463ad55ca201256d01f62b45b2e1c21c12a064b1702d9298fee62dfeccc57d322a463ad55ca201256d01f62b45b2e1c21c10f867098504a817c809830334509435353535353535353535353535353535353535358202d98025a052f8f61201b2b11a78d6e866abc9c3db2ae8631fa656bfe5cb53668255367afba052f8f61201b2b11a78d6e866abc9c3db2ae8631fa656bfe5cb53668255367afbf901fcf901f9a00000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000000940000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000000b90100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008208ae820d0582115c8215b3821a0a827788a00000000000000000000000000000000000000000000000000000000000000000880000000000000000"), }, { // Identical to non-rlp-shortcut version - BlockBodiesRLPPacket66{1111, BlockBodiesRLPPacket([]rlp.RawValue{blockBodyRlp})}, + BlockBodiesRLPPacket{1111, BlockBodiesRLPResponse([]rlp.RawValue{blockBodyRlp})}, common.FromHex("f902dc820457f902d6f902d3f8d2f867088504a817c8088302e2489435353535353535353535353535353535353535358202008025a064b1702d9298fee62dfeccc57d322a463ad55ca201256d01f62b45b2e1c21c12a064b1702d9298fee62dfeccc57d322a463ad55ca201256d01f62b45b2e1c21c10f867098504a817c809830334509435353535353535353535353535353535353535358202d98025a052f8f61201b2b11a78d6e866abc9c3db2ae8631fa656bfe5cb53668255367afba052f8f61201b2b11a78d6e866abc9c3db2ae8631fa656bfe5cb53668255367afbf901fcf901f9a00000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000000940000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000000b90100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008208ae820d0582115c8215b3821a0a827788a00000000000000000000000000000000000000000000000000000000000000000880000000000000000"), }, { - GetNodeDataPacket66{1111, GetNodeDataPacket(hashes)}, + GetReceiptsPacket{1111, GetReceiptsRequest(hashes)}, common.FromHex("f847820457f842a000000000000000000000000000000000000000000000000000000000deadc0dea000000000000000000000000000000000000000000000000000000000feedbeef"), }, { - NodeDataPacket66{1111, NodeDataPacket(byteSlices)}, - common.FromHex("ce820457ca84deadc0de84feedbeef"), - }, - { - GetReceiptsPacket66{1111, GetReceiptsPacket(hashes)}, - common.FromHex("f847820457f842a000000000000000000000000000000000000000000000000000000000deadc0dea000000000000000000000000000000000000000000000000000000000feedbeef"), - }, - { - ReceiptsPacket66{1111, ReceiptsPacket([][]*types.Receipt{receipts})}, + ReceiptsPacket{1111, ReceiptsResponse([][]*types.Receipt{receipts})}, common.FromHex("f90172820457f9016cf90169f901668001b9010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000f85ff85d940000000000000000000000000000000000000011f842a0000000000000000000000000000000000000000000000000000000000000deada0000000000000000000000000000000000000000000000000000000000000beef830100ff"), }, { - ReceiptsRLPPacket66{1111, ReceiptsRLPPacket([]rlp.RawValue{receiptsRlp})}, + ReceiptsRLPPacket{1111, ReceiptsRLPResponse([]rlp.RawValue{receiptsRlp})}, common.FromHex("f90172820457f9016cf90169f901668001b9010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000f85ff85d940000000000000000000000000000000000000011f842a0000000000000000000000000000000000000000000000000000000000000deada0000000000000000000000000000000000000000000000000000000000000beef830100ff"), }, { - GetPooledTransactionsPacket66{1111, GetPooledTransactionsPacket(hashes)}, + GetPooledTransactionsPacket{1111, GetPooledTransactionsRequest(hashes)}, common.FromHex("f847820457f842a000000000000000000000000000000000000000000000000000000000deadc0dea000000000000000000000000000000000000000000000000000000000feedbeef"), }, { - PooledTransactionsPacket66{1111, PooledTransactionsPacket(txs)}, + PooledTransactionsPacket{1111, PooledTransactionsResponse(txs)}, common.FromHex("f8d7820457f8d2f867088504a817c8088302e2489435353535353535353535353535353535353535358202008025a064b1702d9298fee62dfeccc57d322a463ad55ca201256d01f62b45b2e1c21c12a064b1702d9298fee62dfeccc57d322a463ad55ca201256d01f62b45b2e1c21c10f867098504a817c809830334509435353535353535353535353535353535353535358202d98025a052f8f61201b2b11a78d6e866abc9c3db2ae8631fa656bfe5cb53668255367afba052f8f61201b2b11a78d6e866abc9c3db2ae8631fa656bfe5cb53668255367afb"), }, { - PooledTransactionsRLPPacket66{1111, PooledTransactionsRLPPacket(txRlps)}, + PooledTransactionsRLPPacket{1111, PooledTransactionsRLPResponse(txRlps)}, common.FromHex("f8d7820457f8d2f867088504a817c8088302e2489435353535353535353535353535353535353535358202008025a064b1702d9298fee62dfeccc57d322a463ad55ca201256d01f62b45b2e1c21c12a064b1702d9298fee62dfeccc57d322a463ad55ca201256d01f62b45b2e1c21c10f867098504a817c809830334509435353535353535353535353535353535353535358202d98025a052f8f61201b2b11a78d6e866abc9c3db2ae8631fa656bfe5cb53668255367afba052f8f61201b2b11a78d6e866abc9c3db2ae8631fa656bfe5cb53668255367afb"), }, } {
diff --git ethereum/go-ethereum/eth/protocols/snap/handler.go taikoxyz/taiko-geth/eth/protocols/snap/handler.go index 1c6d80d354ce23027977070b90d42e4839e535a1..bd7ce9e71543c944c1a8e1ff2dd2dfcaa95d236f 100644 --- ethereum/go-ethereum/eth/protocols/snap/handler.go +++ taikoxyz/taiko-geth/eth/protocols/snap/handler.go @@ -24,13 +24,13 @@ "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/core" "github.com/ethereum/go-ethereum/core/types" - "github.com/ethereum/go-ethereum/light" "github.com/ethereum/go-ethereum/log" "github.com/ethereum/go-ethereum/metrics" "github.com/ethereum/go-ethereum/p2p" "github.com/ethereum/go-ethereum/p2p/enode" "github.com/ethereum/go-ethereum/p2p/enr" "github.com/ethereum/go-ethereum/trie" + "github.com/ethereum/go-ethereum/trie/trienode" )   const ( @@ -284,7 +284,7 @@ if req.Bytes > softResponseLimit { req.Bytes = softResponseLimit } // Retrieve the requested state and bail out if non existent - tr, err := trie.New(trie.StateTrieID(req.Root), chain.StateCache().TrieDB()) + tr, err := trie.New(trie.StateTrieID(req.Root), chain.TrieDB()) if err != nil { return nil, nil } @@ -321,7 +321,7 @@ } it.Release()   // Generate the Merkle proofs for the first and last account - proof := light.NewNodeSet() + proof := trienode.NewProofSet() if err := tr.Prove(req.Origin[:], proof); err != nil { log.Warn("Failed to prove account range", "origin", req.Origin, "err", err) return nil, nil @@ -333,7 +333,7 @@ return nil, nil } } var proofs [][]byte - for _, blob := range proof.NodeList() { + for _, blob := range proof.List() { proofs = append(proofs, blob) } return accounts, proofs @@ -367,7 +367,7 @@ var origin common.Hash if len(req.Origin) > 0 { origin, req.Origin = common.BytesToHash(req.Origin), nil } - var limit = common.HexToHash("0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff") + var limit = common.MaxHash if len(req.Limit) > 0 { limit, req.Limit = common.BytesToHash(req.Limit), nil } @@ -414,7 +414,7 @@ // in the response, no need for any proofs. if origin != (common.Hash{}) || (abort && len(storage) > 0) { // Request started at a non-zero hash or was capped prematurely, add // the endpoint Merkle proofs - accTrie, err := trie.NewStateTrie(trie.StateTrieID(req.Root), chain.StateCache().TrieDB()) + accTrie, err := trie.NewStateTrie(trie.StateTrieID(req.Root), chain.TrieDB()) if err != nil { return nil, nil } @@ -423,11 +423,11 @@ if err != nil || acc == nil { return nil, nil } id := trie.StorageTrieID(req.Root, account, acc.Root) - stTrie, err := trie.NewStateTrie(id, chain.StateCache().TrieDB()) + stTrie, err := trie.NewStateTrie(id, chain.TrieDB()) if err != nil { return nil, nil } - proof := light.NewNodeSet() + proof := trienode.NewProofSet() if err := stTrie.Prove(origin[:], proof); err != nil { log.Warn("Failed to prove storage range", "origin", req.Origin, "err", err) return nil, nil @@ -438,7 +438,7 @@ log.Warn("Failed to prove storage range", "last", last, "err", err) return nil, nil } } - for _, blob := range proof.NodeList() { + for _, blob := range proof.List() { proofs = append(proofs, blob) } // Proof terminates the reply as proofs are only added if a node @@ -487,7 +487,7 @@ if req.Bytes > softResponseLimit { req.Bytes = softResponseLimit } // Make sure we have the state associated with the request - triedb := chain.StateCache().TrieDB() + triedb := chain.TrieDB()   accTrie, err := trie.NewStateTrie(trie.StateTrieID(req.Root), triedb) if err != nil {
diff --git ethereum/go-ethereum/eth/protocols/snap/range.go taikoxyz/taiko-geth/eth/protocols/snap/range.go index 2627cb954b8fb69442a00058ed2707e66c747f0d..8c98c71d5064207a313053b8ff101b8709e494f5 100644 --- ethereum/go-ethereum/eth/protocols/snap/range.go +++ taikoxyz/taiko-geth/eth/protocols/snap/range.go @@ -67,7 +67,7 @@ func (r *hashRange) End() common.Hash { // If the end overflows (non divisible range), return a shorter interval next, overflow := new(uint256.Int).AddOverflow(r.current, r.step) if overflow { - return common.HexToHash("0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff") + return common.MaxHash } return next.SubUint64(next, 1).Bytes32() }
diff --git ethereum/go-ethereum/eth/protocols/snap/range_test.go taikoxyz/taiko-geth/eth/protocols/snap/range_test.go index 3461439e54bdf85e2572227da632d7131c551408..ea643f13612f9e3e577bffd4d7185bd13ca36bc8 100644 --- ethereum/go-ethereum/eth/protocols/snap/range_test.go +++ taikoxyz/taiko-geth/eth/protocols/snap/range_test.go @@ -45,7 +45,7 @@ ends: []common.Hash{ common.HexToHash("0x3fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"), common.HexToHash("0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"), common.HexToHash("0xbfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"), - common.HexToHash("0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"), + common.MaxHash, }, }, // Split a divisible part of the hash range up into 2 chunks @@ -58,7 +58,7 @@ common.HexToHash("0x9000000000000000000000000000000000000000000000000000000000000000"), }, ends: []common.Hash{ common.HexToHash("0x8fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"), - common.HexToHash("0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"), + common.MaxHash, }, }, // Split the entire hash range into a non divisible 3 chunks @@ -73,7 +73,7 @@ }, ends: []common.Hash{ common.HexToHash("0x5555555555555555555555555555555555555555555555555555555555555555"), common.HexToHash("0xaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaab"), - common.HexToHash("0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"), + common.MaxHash, }, }, // Split a part of hash range into a non divisible 3 chunks @@ -88,7 +88,7 @@ }, ends: []common.Hash{ common.HexToHash("0x6aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"), common.HexToHash("0xb555555555555555555555555555555555555555555555555555555555555555"), - common.HexToHash("0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"), + common.MaxHash, }, }, // Split a part of hash range into a non divisible 3 chunks, but with a @@ -108,7 +108,7 @@ }, ends: []common.Hash{ common.HexToHash("0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff5"), common.HexToHash("0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb"), - common.HexToHash("0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"), + common.MaxHash, }, }, }
diff --git ethereum/go-ethereum/eth/protocols/snap/sync.go taikoxyz/taiko-geth/eth/protocols/snap/sync.go index 0f5f2ccdfeb97d18b6e9bb1c7a2f7584f2db5b6e..22638d04735fcde1e772d2914467ed28c6a50bbd 100644 --- ethereum/go-ethereum/eth/protocols/snap/sync.go +++ taikoxyz/taiko-geth/eth/protocols/snap/sync.go @@ -37,11 +37,11 @@ "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/crypto" "github.com/ethereum/go-ethereum/ethdb" "github.com/ethereum/go-ethereum/event" - "github.com/ethereum/go-ethereum/light" "github.com/ethereum/go-ethereum/log" "github.com/ethereum/go-ethereum/p2p/msgrate" "github.com/ethereum/go-ethereum/rlp" "github.com/ethereum/go-ethereum/trie" + "github.com/ethereum/go-ethereum/trie/trienode" "golang.org/x/crypto/sha3" )   @@ -738,8 +738,8 @@ OnPut: func(key []byte, value []byte) { s.accountBytes += common.StorageSize(len(key) + len(value)) }, } - task.genTrie = trie.NewStackTrie(func(owner common.Hash, path []byte, hash common.Hash, val []byte) { - rawdb.WriteTrieNode(task.genBatch, owner, path, hash, val, s.scheme) + task.genTrie = trie.NewStackTrie(func(path []byte, hash common.Hash, val []byte) { + rawdb.WriteTrieNode(task.genBatch, common.Hash{}, path, hash, val, s.scheme) }) for accountHash, subtasks := range task.SubTasks { for _, subtask := range subtasks { @@ -751,9 +751,10 @@ OnPut: func(key []byte, value []byte) { s.storageBytes += common.StorageSize(len(key) + len(value)) }, } - subtask.genTrie = trie.NewStackTrieWithOwner(func(owner common.Hash, path []byte, hash common.Hash, val []byte) { + owner := accountHash // local assignment for stacktrie writer closure + subtask.genTrie = trie.NewStackTrie(func(path []byte, hash common.Hash, val []byte) { rawdb.WriteTrieNode(subtask.genBatch, owner, path, hash, val, s.scheme) - }, accountHash) + }) } } } @@ -797,7 +798,7 @@ for i := 0; i < accountConcurrency; i++ { last := common.BigToHash(new(big.Int).Add(next.Big(), step)) if i == accountConcurrency-1 { // Make sure we don't overflow if the step is not a proper divisor - last = common.HexToHash("0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff") + last = common.MaxHash } batch := ethdb.HookedBatch{ Batch: s.db.NewBatch(), @@ -810,8 +811,8 @@ Next: next, Last: last, SubTasks: make(map[common.Hash][]*storageTask), genBatch: batch, - genTrie: trie.NewStackTrie(func(owner common.Hash, path []byte, hash common.Hash, val []byte) { - rawdb.WriteTrieNode(batch, owner, path, hash, val, s.scheme) + genTrie: trie.NewStackTrie(func(path []byte, hash common.Hash, val []byte) { + rawdb.WriteTrieNode(batch, common.Hash{}, path, hash, val, s.scheme) }), }) log.Debug("Created account sync task", "from", next, "last", last) @@ -1873,7 +1874,7 @@ s.forwardAccountTask(res.task) return } // Some accounts are incomplete, leave as is for the storage and contract - // task assigners to pick up and fill. + // task assigners to pick up and fill }   // processBytecodeResponse integrates an already validated bytecode response @@ -2004,14 +2005,15 @@ OnPut: func(key []byte, value []byte) { s.storageBytes += common.StorageSize(len(key) + len(value)) }, } + owner := account // local assignment for stacktrie writer closure tasks = append(tasks, &storageTask{ Next: common.Hash{}, Last: r.End(), root: acc.Root, genBatch: batch, - genTrie: trie.NewStackTrieWithOwner(func(owner common.Hash, path []byte, hash common.Hash, val []byte) { + genTrie: trie.NewStackTrie(func(path []byte, hash common.Hash, val []byte) { rawdb.WriteTrieNode(batch, owner, path, hash, val, s.scheme) - }, account), + }), }) for r.Next() { batch := ethdb.HookedBatch{ @@ -2025,9 +2027,9 @@ Next: r.Start(), Last: r.End(), root: acc.Root, genBatch: batch, - genTrie: trie.NewStackTrieWithOwner(func(owner common.Hash, path []byte, hash common.Hash, val []byte) { + genTrie: trie.NewStackTrie(func(path []byte, hash common.Hash, val []byte) { rawdb.WriteTrieNode(batch, owner, path, hash, val, s.scheme) - }, account), + }), }) } for _, task := range tasks { @@ -2072,9 +2074,10 @@ // reconstructed later. slots += len(res.hashes[i])   if i < len(res.hashes)-1 || res.subTask == nil { - tr := trie.NewStackTrieWithOwner(func(owner common.Hash, path []byte, hash common.Hash, val []byte) { - rawdb.WriteTrieNode(batch, owner, path, hash, val, s.scheme) - }, account) + // no need to make local reassignment of account: this closure does not outlive the loop + tr := trie.NewStackTrie(func(path []byte, hash common.Hash, val []byte) { + rawdb.WriteTrieNode(batch, account, path, hash, val, s.scheme) + }) for j := 0; j < len(res.hashes[i]); j++ { tr.Update(res.hashes[i][j][:], res.slots[i][j]) } @@ -2394,17 +2397,11 @@ keys := make([][]byte, len(hashes)) for i, key := range hashes { keys[i] = common.CopyBytes(key[:]) } - nodes := make(light.NodeList, len(proof)) + nodes := make(trienode.ProofList, len(proof)) for i, node := range proof { nodes[i] = node } - proofdb := nodes.NodeSet() - - var end []byte - if len(keys) > 0 { - end = keys[len(keys)-1] - } - cont, err := trie.VerifyRangeProof(root, req.origin[:], end, keys, accounts, proofdb) + cont, err := trie.VerifyRangeProof(root, req.origin[:], keys, accounts, nodes.Set()) if err != nil { logger.Warn("Account range failed proof", "err", err) // Signal this request as failed, and ready for rescheduling @@ -2621,7 +2618,7 @@ // Response is valid, but check if peer is signalling that it does not have // the requested data. For storage range queries that means the state being // retrieved was either already pruned remotely, or the peer is not yet // synced to our head. - if len(hashes) == 0 { + if len(hashes) == 0 && len(proof) == 0 { logger.Debug("Peer rejected storage request") s.statelessPeers[peer.ID()] = struct{}{} s.lock.Unlock() @@ -2633,13 +2630,20 @@ // Reconstruct the partial tries from the response and verify them var cont bool   + // If a proof was attached while the response is empty, it indicates that the + // requested range specified with 'origin' is empty. Construct an empty state + // response locally to finalize the range. + if len(hashes) == 0 && len(proof) > 0 { + hashes = append(hashes, []common.Hash{}) + slots = append(slots, [][]byte{}) + } for i := 0; i < len(hashes); i++ { // Convert the keys and proofs into an internal format keys := make([][]byte, len(hashes[i])) for j, key := range hashes[i] { keys[j] = common.CopyBytes(key[:]) } - nodes := make(light.NodeList, 0, len(proof)) + nodes := make(trienode.ProofList, 0, len(proof)) if i == len(hashes)-1 { for _, node := range proof { nodes = append(nodes, node) @@ -2649,7 +2653,7 @@ var err error if len(nodes) == 0 { // No proof has been attached, the response must cover the entire key // space and hash to the origin root. - _, err = trie.VerifyRangeProof(req.roots[i], nil, nil, keys, slots[i], nil) + _, err = trie.VerifyRangeProof(req.roots[i], nil, keys, slots[i], nil) if err != nil { s.scheduleRevertStorageRequest(req) // reschedule request logger.Warn("Storage slots failed proof", "err", err) @@ -2658,13 +2662,9 @@ } } else { // A proof was attached, the response is only partial, check that the // returned data is indeed part of the storage trie - proofdb := nodes.NodeSet() + proofdb := nodes.Set()   - var end []byte - if len(keys) > 0 { - end = keys[len(keys)-1] - } - cont, err = trie.VerifyRangeProof(req.roots[i], req.origin[:], end, keys, slots[i], proofdb) + cont, err = trie.VerifyRangeProof(req.roots[i], req.origin[:], keys, slots[i], proofdb) if err != nil { s.scheduleRevertStorageRequest(req) // reschedule request logger.Warn("Storage range failed proof", "err", err)
diff --git ethereum/go-ethereum/eth/protocols/snap/sync_test.go taikoxyz/taiko-geth/eth/protocols/snap/sync_test.go index 0aa6fd8730dd8090e2e0e3eece709a9e544e0659..5d4099a8140ef229243fdf82951bae77052446a0 100644 --- ethereum/go-ethereum/eth/protocols/snap/sync_test.go +++ taikoxyz/taiko-geth/eth/protocols/snap/sync_test.go @@ -22,6 +22,7 @@ "crypto/rand" "encoding/binary" "fmt" "math/big" + mrand "math/rand" "sync" "testing" "time" @@ -31,10 +32,11 @@ "github.com/ethereum/go-ethereum/core/rawdb" "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/crypto" "github.com/ethereum/go-ethereum/ethdb" - "github.com/ethereum/go-ethereum/light" "github.com/ethereum/go-ethereum/log" "github.com/ethereum/go-ethereum/rlp" "github.com/ethereum/go-ethereum/trie" + "github.com/ethereum/go-ethereum/trie/testutil" + "github.com/ethereum/go-ethereum/trie/triedb/pathdb" "github.com/ethereum/go-ethereum/trie/trienode" "golang.org/x/crypto/sha3" "golang.org/x/exp/slices" @@ -253,7 +255,7 @@ func createAccountRequestResponse(t *testPeer, root common.Hash, origin common.Hash, limit common.Hash, cap uint64) (keys []common.Hash, vals [][]byte, proofs [][]byte) { var size uint64 if limit == (common.Hash{}) { - limit = common.HexToHash("0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff") + limit = common.MaxHash } for _, entry := range t.accountValues { if size > cap { @@ -272,7 +274,7 @@ } // Unless we send the entire trie, we need to supply proofs // Actually, we need to supply proofs either way! This seems to be an implementation // quirk in go-ethereum - proof := light.NewNodeSet() + proof := trienode.NewProofSet() if err := t.accountTrie.Prove(origin[:], proof); err != nil { t.logger.Error("Could not prove inexistence of origin", "origin", origin, "error", err) } @@ -282,7 +284,7 @@ if err := t.accountTrie.Prove(lastK, proof); err != nil { t.logger.Error("Could not prove last item", "error", err) } } - for _, blob := range proof.NodeList() { + for _, blob := range proof.List() { proofs = append(proofs, blob) } return keys, vals, proofs @@ -318,7 +320,7 @@ var originHash common.Hash if len(origin) > 0 { originHash = common.BytesToHash(origin) } - var limitHash = common.HexToHash("0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff") + var limitHash = common.MaxHash if len(limit) > 0 { limitHash = common.BytesToHash(limit) } @@ -352,7 +354,7 @@ // in the response, no need for any proofs. if originHash != (common.Hash{}) || (abort && len(keys) > 0) { // If we're aborting, we need to prove the first and last item // This terminates the response (and thus the loop) - proof := light.NewNodeSet() + proof := trienode.NewProofSet() stTrie := t.storageTries[account]   // Here's a potential gotcha: when constructing the proof, we cannot @@ -367,7 +369,7 @@ if err := stTrie.Prove(lastK, proof); err != nil { t.logger.Error("Could not prove last item", "error", err) } } - for _, blob := range proof.NodeList() { + for _, blob := range proof.List() { proofs = append(proofs, blob) } break @@ -410,7 +412,7 @@ if exit { // If we're aborting, we need to prove the first and last item // This terminates the response (and thus the loop) - proof := light.NewNodeSet() + proof := trienode.NewProofSet() stTrie := t.storageTries[account]   // Here's a potential gotcha: when constructing the proof, we cannot @@ -426,7 +428,7 @@ if err := stTrie.Prove(lastK, proof); err != nil { t.logger.Error("Could not prove last item", "error", err) } } - for _, blob := range proof.NodeList() { + for _, blob := range proof.List() { proofs = append(proofs, blob) } break @@ -561,6 +563,11 @@ // the remote side does not do any follow-up requests func TestSyncBloatedProof(t *testing.T) { t.Parallel()   + testSyncBloatedProof(t, rawdb.HashScheme) + testSyncBloatedProof(t, rawdb.PathScheme) +} + +func testSyncBloatedProof(t *testing.T, scheme string) { var ( once sync.Once cancel = make(chan struct{}) @@ -570,7 +577,7 @@ close(cancel) }) } ) - nodeScheme, sourceAccountTrie, elems := makeAccountTrieNoStorage(100) + nodeScheme, sourceAccountTrie, elems := makeAccountTrieNoStorage(100, scheme) source := newTestPeer("source", t, term) source.accountTrie = sourceAccountTrie.Copy() source.accountValues = elems @@ -593,8 +600,9 @@ keys = append(keys, common.BytesToHash(entry.k)) vals = append(vals, entry.v) } // The proofs - proof := light.NewNodeSet() + proof := trienode.NewProofSet() if err := t.accountTrie.Prove(origin[:], proof); err != nil { + t.logger.Error("Could not prove origin", "origin", origin, "error", err) t.logger.Error("Could not prove origin", "origin", origin, "error", err) } // The bloat: add proof of every single element @@ -608,7 +616,7 @@ if len(keys) > 2 { keys = append(keys[:1], keys[2:]...) vals = append(vals[:1], vals[2:]...) } - for _, blob := range proof.NodeList() { + for _, blob := range proof.List() { proofs = append(proofs, blob) } if err := t.remote.OnAccounts(t, requestId, keys, vals, proofs); err != nil { @@ -638,6 +646,11 @@ // TestSync tests a basic sync with one peer func TestSync(t *testing.T) { t.Parallel()   + testSync(t, rawdb.HashScheme) + testSync(t, rawdb.PathScheme) +} + +func testSync(t *testing.T, scheme string) { var ( once sync.Once cancel = make(chan struct{}) @@ -647,7 +660,7 @@ close(cancel) }) } ) - nodeScheme, sourceAccountTrie, elems := makeAccountTrieNoStorage(100) + nodeScheme, sourceAccountTrie, elems := makeAccountTrieNoStorage(100, scheme)   mkSource := func(name string) *testPeer { source := newTestPeer(name, t, term) @@ -659,7 +672,7 @@ syncer := setupSyncer(nodeScheme, mkSource("source")) if err := syncer.Sync(sourceAccountTrie.Hash(), cancel); err != nil { t.Fatalf("sync failed: %v", err) } - verifyTrie(syncer.db, sourceAccountTrie.Hash(), t) + verifyTrie(scheme, syncer.db, sourceAccountTrie.Hash(), t) }   // TestSyncTinyTriePanic tests a basic sync with one peer, and a tiny trie. This caused a @@ -667,6 +680,11 @@ // panic within the prover func TestSyncTinyTriePanic(t *testing.T) { t.Parallel()   + testSyncTinyTriePanic(t, rawdb.HashScheme) + testSyncTinyTriePanic(t, rawdb.PathScheme) +} + +func testSyncTinyTriePanic(t *testing.T, scheme string) { var ( once sync.Once cancel = make(chan struct{}) @@ -676,7 +694,7 @@ close(cancel) }) } ) - nodeScheme, sourceAccountTrie, elems := makeAccountTrieNoStorage(1) + nodeScheme, sourceAccountTrie, elems := makeAccountTrieNoStorage(1, scheme)   mkSource := func(name string) *testPeer { source := newTestPeer(name, t, term) @@ -690,13 +708,18 @@ if err := syncer.Sync(sourceAccountTrie.Hash(), cancel); err != nil { t.Fatalf("sync failed: %v", err) } close(done) - verifyTrie(syncer.db, sourceAccountTrie.Hash(), t) + verifyTrie(scheme, syncer.db, sourceAccountTrie.Hash(), t) }   // TestMultiSync tests a basic sync with multiple peers func TestMultiSync(t *testing.T) { t.Parallel()   + testMultiSync(t, rawdb.HashScheme) + testMultiSync(t, rawdb.PathScheme) +} + +func testMultiSync(t *testing.T, scheme string) { var ( once sync.Once cancel = make(chan struct{}) @@ -706,7 +729,7 @@ close(cancel) }) } ) - nodeScheme, sourceAccountTrie, elems := makeAccountTrieNoStorage(100) + nodeScheme, sourceAccountTrie, elems := makeAccountTrieNoStorage(100, scheme)   mkSource := func(name string) *testPeer { source := newTestPeer(name, t, term) @@ -720,13 +743,18 @@ if err := syncer.Sync(sourceAccountTrie.Hash(), cancel); err != nil { t.Fatalf("sync failed: %v", err) } close(done) - verifyTrie(syncer.db, sourceAccountTrie.Hash(), t) + verifyTrie(scheme, syncer.db, sourceAccountTrie.Hash(), t) }   // TestSyncWithStorage tests basic sync using accounts + storage + code func TestSyncWithStorage(t *testing.T) { t.Parallel()   + testSyncWithStorage(t, rawdb.HashScheme) + testSyncWithStorage(t, rawdb.PathScheme) +} + +func testSyncWithStorage(t *testing.T, scheme string) { var ( once sync.Once cancel = make(chan struct{}) @@ -736,7 +764,7 @@ close(cancel) }) } ) - nodeScheme, sourceAccountTrie, elems, storageTries, storageElems := makeAccountTrieWithStorage(3, 3000, true, false) + sourceAccountTrie, elems, storageTries, storageElems := makeAccountTrieWithStorage(scheme, 3, 3000, true, false, false)   mkSource := func(name string) *testPeer { source := newTestPeer(name, t, term) @@ -746,19 +774,24 @@ source.setStorageTries(storageTries) source.storageValues = storageElems return source } - syncer := setupSyncer(nodeScheme, mkSource("sourceA")) + syncer := setupSyncer(scheme, mkSource("sourceA")) done := checkStall(t, term) if err := syncer.Sync(sourceAccountTrie.Hash(), cancel); err != nil { t.Fatalf("sync failed: %v", err) } close(done) - verifyTrie(syncer.db, sourceAccountTrie.Hash(), t) + verifyTrie(scheme, syncer.db, sourceAccountTrie.Hash(), t) }   // TestMultiSyncManyUseless contains one good peer, and many which doesn't return anything valuable at all func TestMultiSyncManyUseless(t *testing.T) { t.Parallel()   + testMultiSyncManyUseless(t, rawdb.HashScheme) + testMultiSyncManyUseless(t, rawdb.PathScheme) +} + +func testMultiSyncManyUseless(t *testing.T, scheme string) { var ( once sync.Once cancel = make(chan struct{}) @@ -768,7 +801,7 @@ close(cancel) }) } ) - nodeScheme, sourceAccountTrie, elems, storageTries, storageElems := makeAccountTrieWithStorage(100, 3000, true, false) + sourceAccountTrie, elems, storageTries, storageElems := makeAccountTrieWithStorage(scheme, 100, 3000, true, false, false)   mkSource := func(name string, noAccount, noStorage, noTrieNode bool) *testPeer { source := newTestPeer(name, t, term) @@ -790,7 +823,7 @@ return source }   syncer := setupSyncer( - nodeScheme, + scheme, mkSource("full", true, true, true), mkSource("noAccounts", false, true, true), mkSource("noStorage", true, false, true), @@ -801,11 +834,18 @@ if err := syncer.Sync(sourceAccountTrie.Hash(), cancel); err != nil { t.Fatalf("sync failed: %v", err) } close(done) - verifyTrie(syncer.db, sourceAccountTrie.Hash(), t) + verifyTrie(scheme, syncer.db, sourceAccountTrie.Hash(), t) }   // TestMultiSyncManyUseless contains one good peer, and many which doesn't return anything valuable at all func TestMultiSyncManyUselessWithLowTimeout(t *testing.T) { + t.Parallel() + + testMultiSyncManyUselessWithLowTimeout(t, rawdb.HashScheme) + testMultiSyncManyUselessWithLowTimeout(t, rawdb.PathScheme) +} + +func testMultiSyncManyUselessWithLowTimeout(t *testing.T, scheme string) { var ( once sync.Once cancel = make(chan struct{}) @@ -815,7 +855,7 @@ close(cancel) }) } ) - nodeScheme, sourceAccountTrie, elems, storageTries, storageElems := makeAccountTrieWithStorage(100, 3000, true, false) + sourceAccountTrie, elems, storageTries, storageElems := makeAccountTrieWithStorage(scheme, 100, 3000, true, false, false)   mkSource := func(name string, noAccount, noStorage, noTrieNode bool) *testPeer { source := newTestPeer(name, t, term) @@ -837,7 +877,7 @@ return source }   syncer := setupSyncer( - nodeScheme, + scheme, mkSource("full", true, true, true), mkSource("noAccounts", false, true, true), mkSource("noStorage", true, false, true), @@ -853,11 +893,18 @@ if err := syncer.Sync(sourceAccountTrie.Hash(), cancel); err != nil { t.Fatalf("sync failed: %v", err) } close(done) - verifyTrie(syncer.db, sourceAccountTrie.Hash(), t) + verifyTrie(scheme, syncer.db, sourceAccountTrie.Hash(), t) }   // TestMultiSyncManyUnresponsive contains one good peer, and many which doesn't respond at all func TestMultiSyncManyUnresponsive(t *testing.T) { + t.Parallel() + + testMultiSyncManyUnresponsive(t, rawdb.HashScheme) + testMultiSyncManyUnresponsive(t, rawdb.PathScheme) +} + +func testMultiSyncManyUnresponsive(t *testing.T, scheme string) { var ( once sync.Once cancel = make(chan struct{}) @@ -867,7 +914,7 @@ close(cancel) }) } ) - nodeScheme, sourceAccountTrie, elems, storageTries, storageElems := makeAccountTrieWithStorage(100, 3000, true, false) + sourceAccountTrie, elems, storageTries, storageElems := makeAccountTrieWithStorage(scheme, 100, 3000, true, false, false)   mkSource := func(name string, noAccount, noStorage, noTrieNode bool) *testPeer { source := newTestPeer(name, t, term) @@ -889,7 +936,7 @@ return source }   syncer := setupSyncer( - nodeScheme, + scheme, mkSource("full", true, true, true), mkSource("noAccounts", false, true, true), mkSource("noStorage", true, false, true), @@ -903,7 +950,7 @@ if err := syncer.Sync(sourceAccountTrie.Hash(), cancel); err != nil { t.Fatalf("sync failed: %v", err) } close(done) - verifyTrie(syncer.db, sourceAccountTrie.Hash(), t) + verifyTrie(scheme, syncer.db, sourceAccountTrie.Hash(), t) }   func checkStall(t *testing.T, term func()) chan struct{} { @@ -925,6 +972,11 @@ // account trie has a few boundary elements. func TestSyncBoundaryAccountTrie(t *testing.T) { t.Parallel()   + testSyncBoundaryAccountTrie(t, rawdb.HashScheme) + testSyncBoundaryAccountTrie(t, rawdb.PathScheme) +} + +func testSyncBoundaryAccountTrie(t *testing.T, scheme string) { var ( once sync.Once cancel = make(chan struct{}) @@ -934,7 +986,7 @@ close(cancel) }) } ) - nodeScheme, sourceAccountTrie, elems := makeBoundaryAccountTrie(3000) + nodeScheme, sourceAccountTrie, elems := makeBoundaryAccountTrie(scheme, 3000)   mkSource := func(name string) *testPeer { source := newTestPeer(name, t, term) @@ -952,7 +1004,7 @@ if err := syncer.Sync(sourceAccountTrie.Hash(), cancel); err != nil { t.Fatalf("sync failed: %v", err) } close(done) - verifyTrie(syncer.db, sourceAccountTrie.Hash(), t) + verifyTrie(scheme, syncer.db, sourceAccountTrie.Hash(), t) }   // TestSyncNoStorageAndOneCappedPeer tests sync using accounts and no storage, where one peer is @@ -960,6 +1012,11 @@ // consistently returning very small results func TestSyncNoStorageAndOneCappedPeer(t *testing.T) { t.Parallel()   + testSyncNoStorageAndOneCappedPeer(t, rawdb.HashScheme) + testSyncNoStorageAndOneCappedPeer(t, rawdb.PathScheme) +} + +func testSyncNoStorageAndOneCappedPeer(t *testing.T, scheme string) { var ( once sync.Once cancel = make(chan struct{}) @@ -969,7 +1026,7 @@ close(cancel) }) } ) - nodeScheme, sourceAccountTrie, elems := makeAccountTrieNoStorage(3000) + nodeScheme, sourceAccountTrie, elems := makeAccountTrieNoStorage(3000, scheme)   mkSource := func(name string, slow bool) *testPeer { source := newTestPeer(name, t, term) @@ -994,7 +1051,7 @@ if err := syncer.Sync(sourceAccountTrie.Hash(), cancel); err != nil { t.Fatalf("sync failed: %v", err) } close(done) - verifyTrie(syncer.db, sourceAccountTrie.Hash(), t) + verifyTrie(scheme, syncer.db, sourceAccountTrie.Hash(), t) }   // TestSyncNoStorageAndOneCodeCorruptPeer has one peer which doesn't deliver @@ -1002,6 +1059,11 @@ // code requests properly. func TestSyncNoStorageAndOneCodeCorruptPeer(t *testing.T) { t.Parallel()   + testSyncNoStorageAndOneCodeCorruptPeer(t, rawdb.HashScheme) + testSyncNoStorageAndOneCodeCorruptPeer(t, rawdb.PathScheme) +} + +func testSyncNoStorageAndOneCodeCorruptPeer(t *testing.T, scheme string) { var ( once sync.Once cancel = make(chan struct{}) @@ -1011,7 +1073,7 @@ close(cancel) }) } ) - nodeScheme, sourceAccountTrie, elems := makeAccountTrieNoStorage(3000) + nodeScheme, sourceAccountTrie, elems := makeAccountTrieNoStorage(3000, scheme)   mkSource := func(name string, codeFn codeHandlerFunc) *testPeer { source := newTestPeer(name, t, term) @@ -1034,12 +1096,17 @@ if err := syncer.Sync(sourceAccountTrie.Hash(), cancel); err != nil { t.Fatalf("sync failed: %v", err) } close(done) - verifyTrie(syncer.db, sourceAccountTrie.Hash(), t) + verifyTrie(scheme, syncer.db, sourceAccountTrie.Hash(), t) }   func TestSyncNoStorageAndOneAccountCorruptPeer(t *testing.T) { t.Parallel()   + testSyncNoStorageAndOneAccountCorruptPeer(t, rawdb.HashScheme) + testSyncNoStorageAndOneAccountCorruptPeer(t, rawdb.PathScheme) +} + +func testSyncNoStorageAndOneAccountCorruptPeer(t *testing.T, scheme string) { var ( once sync.Once cancel = make(chan struct{}) @@ -1049,7 +1116,7 @@ close(cancel) }) } ) - nodeScheme, sourceAccountTrie, elems := makeAccountTrieNoStorage(3000) + nodeScheme, sourceAccountTrie, elems := makeAccountTrieNoStorage(3000, scheme)   mkSource := func(name string, accFn accountHandlerFunc) *testPeer { source := newTestPeer(name, t, term) @@ -1072,7 +1139,7 @@ if err := syncer.Sync(sourceAccountTrie.Hash(), cancel); err != nil { t.Fatalf("sync failed: %v", err) } close(done) - verifyTrie(syncer.db, sourceAccountTrie.Hash(), t) + verifyTrie(scheme, syncer.db, sourceAccountTrie.Hash(), t) }   // TestSyncNoStorageAndOneCodeCappedPeer has one peer which delivers code hashes @@ -1080,6 +1147,11 @@ // one by one func TestSyncNoStorageAndOneCodeCappedPeer(t *testing.T) { t.Parallel()   + testSyncNoStorageAndOneCodeCappedPeer(t, rawdb.HashScheme) + testSyncNoStorageAndOneCodeCappedPeer(t, rawdb.PathScheme) +} + +func testSyncNoStorageAndOneCodeCappedPeer(t *testing.T, scheme string) { var ( once sync.Once cancel = make(chan struct{}) @@ -1089,7 +1161,7 @@ close(cancel) }) } ) - nodeScheme, sourceAccountTrie, elems := makeAccountTrieNoStorage(3000) + nodeScheme, sourceAccountTrie, elems := makeAccountTrieNoStorage(3000, scheme)   mkSource := func(name string, codeFn codeHandlerFunc) *testPeer { source := newTestPeer(name, t, term) @@ -1123,7 +1195,7 @@ // the number can be flaky, so don't limit it so strictly. if threshold := 100; counter > threshold { t.Logf("Error, expected < %d invocations, got %d", threshold, counter) } - verifyTrie(syncer.db, sourceAccountTrie.Hash(), t) + verifyTrie(scheme, syncer.db, sourceAccountTrie.Hash(), t) }   // TestSyncBoundaryStorageTrie tests sync against a few normal peers, but the @@ -1131,6 +1203,11 @@ // storage trie has a few boundary elements. func TestSyncBoundaryStorageTrie(t *testing.T) { t.Parallel()   + testSyncBoundaryStorageTrie(t, rawdb.HashScheme) + testSyncBoundaryStorageTrie(t, rawdb.PathScheme) +} + +func testSyncBoundaryStorageTrie(t *testing.T, scheme string) { var ( once sync.Once cancel = make(chan struct{}) @@ -1140,7 +1217,7 @@ close(cancel) }) } ) - nodeScheme, sourceAccountTrie, elems, storageTries, storageElems := makeAccountTrieWithStorage(10, 1000, false, true) + sourceAccountTrie, elems, storageTries, storageElems := makeAccountTrieWithStorage(scheme, 10, 1000, false, true, false)   mkSource := func(name string) *testPeer { source := newTestPeer(name, t, term) @@ -1151,7 +1228,7 @@ source.storageValues = storageElems return source } syncer := setupSyncer( - nodeScheme, + scheme, mkSource("peer-a"), mkSource("peer-b"), ) @@ -1160,7 +1237,7 @@ if err := syncer.Sync(sourceAccountTrie.Hash(), cancel); err != nil { t.Fatalf("sync failed: %v", err) } close(done) - verifyTrie(syncer.db, sourceAccountTrie.Hash(), t) + verifyTrie(scheme, syncer.db, sourceAccountTrie.Hash(), t) }   // TestSyncWithStorageAndOneCappedPeer tests sync using accounts + storage, where one peer is @@ -1168,6 +1245,11 @@ // consistently returning very small results func TestSyncWithStorageAndOneCappedPeer(t *testing.T) { t.Parallel()   + testSyncWithStorageAndOneCappedPeer(t, rawdb.HashScheme) + testSyncWithStorageAndOneCappedPeer(t, rawdb.PathScheme) +} + +func testSyncWithStorageAndOneCappedPeer(t *testing.T, scheme string) { var ( once sync.Once cancel = make(chan struct{}) @@ -1177,7 +1259,7 @@ close(cancel) }) } ) - nodeScheme, sourceAccountTrie, elems, storageTries, storageElems := makeAccountTrieWithStorage(300, 1000, false, false) + sourceAccountTrie, elems, storageTries, storageElems := makeAccountTrieWithStorage(scheme, 300, 1000, false, false, false)   mkSource := func(name string, slow bool) *testPeer { source := newTestPeer(name, t, term) @@ -1193,7 +1275,7 @@ return source }   syncer := setupSyncer( - nodeScheme, + scheme, mkSource("nice-a", false), mkSource("slow", true), ) @@ -1202,7 +1284,7 @@ if err := syncer.Sync(sourceAccountTrie.Hash(), cancel); err != nil { t.Fatalf("sync failed: %v", err) } close(done) - verifyTrie(syncer.db, sourceAccountTrie.Hash(), t) + verifyTrie(scheme, syncer.db, sourceAccountTrie.Hash(), t) }   // TestSyncWithStorageAndCorruptPeer tests sync using accounts + storage, where one peer is @@ -1210,6 +1292,11 @@ // sometimes sending bad proofs func TestSyncWithStorageAndCorruptPeer(t *testing.T) { t.Parallel()   + testSyncWithStorageAndCorruptPeer(t, rawdb.HashScheme) + testSyncWithStorageAndCorruptPeer(t, rawdb.PathScheme) +} + +func testSyncWithStorageAndCorruptPeer(t *testing.T, scheme string) { var ( once sync.Once cancel = make(chan struct{}) @@ -1219,7 +1306,7 @@ close(cancel) }) } ) - nodeScheme, sourceAccountTrie, elems, storageTries, storageElems := makeAccountTrieWithStorage(100, 3000, true, false) + sourceAccountTrie, elems, storageTries, storageElems := makeAccountTrieWithStorage(scheme, 100, 3000, true, false, false)   mkSource := func(name string, handler storageHandlerFunc) *testPeer { source := newTestPeer(name, t, term) @@ -1232,7 +1319,7 @@ return source }   syncer := setupSyncer( - nodeScheme, + scheme, mkSource("nice-a", defaultStorageRequestHandler), mkSource("nice-b", defaultStorageRequestHandler), mkSource("nice-c", defaultStorageRequestHandler), @@ -1243,12 +1330,17 @@ if err := syncer.Sync(sourceAccountTrie.Hash(), cancel); err != nil { t.Fatalf("sync failed: %v", err) } close(done) - verifyTrie(syncer.db, sourceAccountTrie.Hash(), t) + verifyTrie(scheme, syncer.db, sourceAccountTrie.Hash(), t) }   func TestSyncWithStorageAndNonProvingPeer(t *testing.T) { t.Parallel()   + testSyncWithStorageAndNonProvingPeer(t, rawdb.HashScheme) + testSyncWithStorageAndNonProvingPeer(t, rawdb.PathScheme) +} + +func testSyncWithStorageAndNonProvingPeer(t *testing.T, scheme string) { var ( once sync.Once cancel = make(chan struct{}) @@ -1258,7 +1350,7 @@ close(cancel) }) } ) - nodeScheme, sourceAccountTrie, elems, storageTries, storageElems := makeAccountTrieWithStorage(100, 3000, true, false) + sourceAccountTrie, elems, storageTries, storageElems := makeAccountTrieWithStorage(scheme, 100, 3000, true, false, false)   mkSource := func(name string, handler storageHandlerFunc) *testPeer { source := newTestPeer(name, t, term) @@ -1270,7 +1362,7 @@ source.storageRequestHandler = handler return source } syncer := setupSyncer( - nodeScheme, + scheme, mkSource("nice-a", defaultStorageRequestHandler), mkSource("nice-b", defaultStorageRequestHandler), mkSource("nice-c", defaultStorageRequestHandler), @@ -1281,7 +1373,7 @@ if err := syncer.Sync(sourceAccountTrie.Hash(), cancel); err != nil { t.Fatalf("sync failed: %v", err) } close(done) - verifyTrie(syncer.db, sourceAccountTrie.Hash(), t) + verifyTrie(scheme, syncer.db, sourceAccountTrie.Hash(), t) }   // TestSyncWithStorage tests basic sync using accounts + storage + code, against @@ -1290,6 +1382,12 @@ // an error, where the recipient erroneously clipped the boundary nodes, but // did not mark the account for healing. func TestSyncWithStorageMisbehavingProve(t *testing.T) { t.Parallel() + + testSyncWithStorageMisbehavingProve(t, rawdb.HashScheme) + testSyncWithStorageMisbehavingProve(t, rawdb.PathScheme) +} + +func testSyncWithStorageMisbehavingProve(t *testing.T, scheme string) { var ( once sync.Once cancel = make(chan struct{}) @@ -1299,7 +1397,7 @@ close(cancel) }) } ) - nodeScheme, sourceAccountTrie, elems, storageTries, storageElems := makeAccountTrieWithStorageWithUniqueStorage(10, 30, false) + nodeScheme, sourceAccountTrie, elems, storageTries, storageElems := makeAccountTrieWithStorageWithUniqueStorage(scheme, 10, 30, false)   mkSource := func(name string) *testPeer { source := newTestPeer(name, t, term) @@ -1314,7 +1412,46 @@ syncer := setupSyncer(nodeScheme, mkSource("sourceA")) if err := syncer.Sync(sourceAccountTrie.Hash(), cancel); err != nil { t.Fatalf("sync failed: %v", err) } - verifyTrie(syncer.db, sourceAccountTrie.Hash(), t) + verifyTrie(scheme, syncer.db, sourceAccountTrie.Hash(), t) +} + +// TestSyncWithUnevenStorage tests sync where the storage trie is not even +// and with a few empty ranges. +func TestSyncWithUnevenStorage(t *testing.T) { + t.Parallel() + + testSyncWithUnevenStorage(t, rawdb.HashScheme) + testSyncWithUnevenStorage(t, rawdb.PathScheme) +} + +func testSyncWithUnevenStorage(t *testing.T, scheme string) { + var ( + once sync.Once + cancel = make(chan struct{}) + term = func() { + once.Do(func() { + close(cancel) + }) + } + ) + accountTrie, accounts, storageTries, storageElems := makeAccountTrieWithStorage(scheme, 3, 256, false, false, true) + + mkSource := func(name string) *testPeer { + source := newTestPeer(name, t, term) + source.accountTrie = accountTrie.Copy() + source.accountValues = accounts + source.setStorageTries(storageTries) + source.storageValues = storageElems + source.storageRequestHandler = func(t *testPeer, reqId uint64, root common.Hash, accounts []common.Hash, origin, limit []byte, max uint64) error { + return defaultStorageRequestHandler(t, reqId, root, accounts, origin, limit, 128) // retrieve storage in large mode + } + return source + } + syncer := setupSyncer(scheme, mkSource("source")) + if err := syncer.Sync(accountTrie.Hash(), cancel); err != nil { + t.Fatalf("sync failed: %v", err) + } + verifyTrie(scheme, syncer.db, accountTrie.Hash(), t) }   type kv struct { @@ -1364,9 +1501,9 @@ return nil }   // makeAccountTrieNoStorage spits out a trie, along with the leafs -func makeAccountTrieNoStorage(n int) (string, *trie.Trie, []*kv) { +func makeAccountTrieNoStorage(n int, scheme string) (string, *trie.Trie, []*kv) { var ( - db = trie.NewDatabase(rawdb.NewMemoryDatabase()) + db = trie.NewDatabase(rawdb.NewMemoryDatabase(), newDbConfig(scheme)) accTrie = trie.NewEmpty(db) entries []*kv ) @@ -1396,12 +1533,12 @@ // makeBoundaryAccountTrie constructs an account trie. Instead of filling // accounts normally, this function will fill a few accounts which have // boundary hash. -func makeBoundaryAccountTrie(n int) (string, *trie.Trie, []*kv) { +func makeBoundaryAccountTrie(scheme string, n int) (string, *trie.Trie, []*kv) { var ( entries []*kv boundaries []common.Hash   - db = trie.NewDatabase(rawdb.NewMemoryDatabase()) + db = trie.NewDatabase(rawdb.NewMemoryDatabase(), newDbConfig(scheme)) accTrie = trie.NewEmpty(db) ) // Initialize boundaries @@ -1415,7 +1552,7 @@ ) for i := 0; i < accountConcurrency; i++ { last := common.BigToHash(new(big.Int).Add(next.Big(), step)) if i == accountConcurrency-1 { - last = common.HexToHash("0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff") + last = common.MaxHash } boundaries = append(boundaries, last) next = common.BigToHash(new(big.Int).Add(last.Big(), common.Big1)) @@ -1457,9 +1594,9 @@ }   // makeAccountTrieWithStorageWithUniqueStorage creates an account trie where each accounts // has a unique storage set. -func makeAccountTrieWithStorageWithUniqueStorage(accounts, slots int, code bool) (string, *trie.Trie, []*kv, map[common.Hash]*trie.Trie, map[common.Hash][]*kv) { +func makeAccountTrieWithStorageWithUniqueStorage(scheme string, accounts, slots int, code bool) (string, *trie.Trie, []*kv, map[common.Hash]*trie.Trie, map[common.Hash][]*kv) { var ( - db = trie.NewDatabase(rawdb.NewMemoryDatabase()) + db = trie.NewDatabase(rawdb.NewMemoryDatabase(), newDbConfig(scheme)) accTrie = trie.NewEmpty(db) entries []*kv storageRoots = make(map[common.Hash]common.Hash) @@ -1512,9 +1649,9 @@ return db.Scheme(), accTrie, entries, storageTries, storageEntries }   // makeAccountTrieWithStorage spits out a trie, along with the leafs -func makeAccountTrieWithStorage(accounts, slots int, code, boundary bool) (string, *trie.Trie, []*kv, map[common.Hash]*trie.Trie, map[common.Hash][]*kv) { +func makeAccountTrieWithStorage(scheme string, accounts, slots int, code, boundary bool, uneven bool) (*trie.Trie, []*kv, map[common.Hash]*trie.Trie, map[common.Hash][]*kv) { var ( - db = trie.NewDatabase(rawdb.NewMemoryDatabase()) + db = trie.NewDatabase(rawdb.NewMemoryDatabase(), newDbConfig(scheme)) accTrie = trie.NewEmpty(db) entries []*kv storageRoots = make(map[common.Hash]common.Hash) @@ -1537,6 +1674,8 @@ stEntries []*kv ) if boundary { stRoot, stNodes, stEntries = makeBoundaryStorageTrie(common.BytesToHash(key), slots, db) + } else if uneven { + stRoot, stNodes, stEntries = makeUnevenStorageTrie(common.BytesToHash(key), slots, db) } else { stRoot, stNodes, stEntries = makeStorageTrieWithSeed(common.BytesToHash(key), uint64(slots), 0, db) } @@ -1579,7 +1718,7 @@ panic(err) } storageTries[common.BytesToHash(key)] = trie } - return db.Scheme(), accTrie, entries, storageTries, storageEntries + return accTrie, entries, storageTries, storageEntries }   // makeStorageTrieWithSeed fills a storage trie with n items, returning the @@ -1625,7 +1764,7 @@ ) for i := 0; i < accountConcurrency; i++ { last := common.BigToHash(new(big.Int).Add(next.Big(), step)) if i == accountConcurrency-1 { - last = common.HexToHash("0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff") + last = common.MaxHash } boundaries = append(boundaries, last) next = common.BigToHash(new(big.Int).Add(last.Big(), common.Big1)) @@ -1656,9 +1795,41 @@ root, nodes, _ := trie.Commit(false) return root, nodes, entries }   -func verifyTrie(db ethdb.KeyValueStore, root common.Hash, t *testing.T) { +// makeUnevenStorageTrie constructs a storage tries will states distributed in +// different range unevenly. +func makeUnevenStorageTrie(owner common.Hash, slots int, db *trie.Database) (common.Hash, *trienode.NodeSet, []*kv) { + var ( + entries []*kv + tr, _ = trie.New(trie.StorageTrieID(types.EmptyRootHash, owner, types.EmptyRootHash), db) + chosen = make(map[byte]struct{}) + ) + for i := 0; i < 3; i++ { + var n int + for { + n = mrand.Intn(15) // the last range is set empty deliberately + if _, ok := chosen[byte(n)]; ok { + continue + } + chosen[byte(n)] = struct{}{} + break + } + for j := 0; j < slots/3; j++ { + key := append([]byte{byte(n)}, testutil.RandBytes(31)...) + val, _ := rlp.EncodeToBytes(testutil.RandBytes(32)) + + elem := &kv{key, val} + tr.MustUpdate(elem.k, elem.v) + entries = append(entries, elem) + } + } + slices.SortFunc(entries, (*kv).cmp) + root, nodes, _ := tr.Commit(false) + return root, nodes, entries +} + +func verifyTrie(scheme string, db ethdb.KeyValueStore, root common.Hash, t *testing.T) { t.Helper() - triedb := trie.NewDatabase(rawdb.NewDatabase(db)) + triedb := trie.NewDatabase(rawdb.NewDatabase(db), newDbConfig(scheme)) accTrie, err := trie.New(trie.StateTrieID(root), triedb) if err != nil { t.Fatal(err) @@ -1700,6 +1871,13 @@ // TestSyncAccountPerformance tests how efficient the snap algo is at minimizing // state healing func TestSyncAccountPerformance(t *testing.T) { + t.Parallel() + + testSyncAccountPerformance(t, rawdb.HashScheme) + testSyncAccountPerformance(t, rawdb.PathScheme) +} + +func testSyncAccountPerformance(t *testing.T, scheme string) { // Set the account concurrency to 1. This _should_ result in the // range root to become correct, and there should be no healing needed defer func(old int) { accountConcurrency = old }(accountConcurrency) @@ -1714,7 +1892,7 @@ close(cancel) }) } ) - nodeScheme, sourceAccountTrie, elems := makeAccountTrieNoStorage(100) + nodeScheme, sourceAccountTrie, elems := makeAccountTrieNoStorage(100, scheme)   mkSource := func(name string) *testPeer { source := newTestPeer(name, t, term) @@ -1727,7 +1905,7 @@ syncer := setupSyncer(nodeScheme, src) if err := syncer.Sync(sourceAccountTrie.Hash(), cancel); err != nil { t.Fatalf("sync failed: %v", err) } - verifyTrie(syncer.db, sourceAccountTrie.Hash(), t) + verifyTrie(scheme, syncer.db, sourceAccountTrie.Hash(), t) // The trie root will always be requested, since it is added when the snap // sync cycle starts. When popping the queue, we do not look it up again. // Doing so would bring this number down to zero in this artificial testcase, @@ -1787,3 +1965,10 @@ t.Errorf("test %d: have %d want %d", i, have, want) } } } + +func newDbConfig(scheme string) *trie.Config { + if scheme == rawdb.HashScheme { + return &trie.Config{} + } + return &trie.Config{PathDB: pathdb.Defaults} +}
diff --git ethereum/go-ethereum/eth/tracers/internal/tracetest/calltrace_test.go taikoxyz/taiko-geth/eth/tracers/internal/tracetest/calltrace_test.go index 26c4455e301f8c10bf65c138e0db83801515dda0..6df49a90c1d00cb275101652fbcc4fcd29b3fb0c 100644 --- ethereum/go-ethereum/eth/tracers/internal/tracetest/calltrace_test.go +++ taikoxyz/taiko-geth/eth/tracers/internal/tracetest/calltrace_test.go @@ -137,8 +137,10 @@ Difficulty: (*big.Int)(test.Context.Difficulty), GasLimit: uint64(test.Context.GasLimit), BaseFee: test.Genesis.BaseFee, } - _, statedb = tests.MakePreState(rawdb.NewMemoryDatabase(), test.Genesis.Alloc, false) + triedb, _, statedb = tests.MakePreState(rawdb.NewMemoryDatabase(), test.Genesis.Alloc, false, rawdb.HashScheme) ) + triedb.Close() + tracer, err := tracers.DefaultDirectory.New(tracerName, new(tracers.Context), test.TracerConfig) if err != nil { t.Fatalf("failed to create call tracer: %v", err) @@ -237,7 +239,8 @@ Time: uint64(test.Context.Time), Difficulty: (*big.Int)(test.Context.Difficulty), GasLimit: uint64(test.Context.GasLimit), } - _, statedb := tests.MakePreState(rawdb.NewMemoryDatabase(), test.Genesis.Alloc, false) + triedb, _, statedb := tests.MakePreState(rawdb.NewMemoryDatabase(), test.Genesis.Alloc, false, rawdb.HashScheme) + defer triedb.Close()   b.ReportAllocs() b.ResetTimer() @@ -363,7 +366,7 @@ want: `{"0x0000000000000000000000000000000000000000":{"balance":"0x0"},"0x000000000000000000000000000000000000feed":{"balance":"0x1c6bf52647880"},"0x00000000000000000000000000000000deadbeef":{"balance":"0x0","code":"0x6001600052600160ff60016000f560ff6000a0"},"0x91ff9a805d36f54e3e272e230f3e3f5c1b330804":{"balance":"0x0"}}`, }, } { t.Run(tc.name, func(t *testing.T) { - _, statedb := tests.MakePreState(rawdb.NewMemoryDatabase(), + triedb, _, statedb := tests.MakePreState(rawdb.NewMemoryDatabase(), core.GenesisAlloc{ to: core.GenesisAccount{ Code: tc.code, @@ -371,7 +374,9 @@ }, origin: core.GenesisAccount{ Balance: big.NewInt(500000000000000), }, - }, false) + }, false, rawdb.HashScheme) + defer triedb.Close() + evm := vm.NewEVM(context, txContext, statedb, params.MainnetChainConfig, vm.Config{Tracer: tc.tracer}) msg := &core.Message{ To: &to,
diff --git ethereum/go-ethereum/eth/tracers/internal/tracetest/flat_calltrace_test.go taikoxyz/taiko-geth/eth/tracers/internal/tracetest/flat_calltrace_test.go index 85e95401a21557a97cffab48f772d7e79ca3db0a..423167b13ccd58cfb3d7c04be73c40430ba8f273 100644 --- ethereum/go-ethereum/eth/tracers/internal/tracetest/flat_calltrace_test.go +++ taikoxyz/taiko-geth/eth/tracers/internal/tracetest/flat_calltrace_test.go @@ -100,7 +100,8 @@ Time: uint64(test.Context.Time), Difficulty: (*big.Int)(test.Context.Difficulty), GasLimit: uint64(test.Context.GasLimit), } - _, statedb := tests.MakePreState(rawdb.NewMemoryDatabase(), test.Genesis.Alloc, false) + triedb, _, statedb := tests.MakePreState(rawdb.NewMemoryDatabase(), test.Genesis.Alloc, false, rawdb.HashScheme) + defer triedb.Close()   // Create the tracer, the EVM environment and run it tracer, err := tracers.DefaultDirectory.New(tracerName, new(tracers.Context), test.TracerConfig)
diff --git ethereum/go-ethereum/eth/tracers/internal/tracetest/prestate_test.go taikoxyz/taiko-geth/eth/tracers/internal/tracetest/prestate_test.go index 991da10b3ab108077b70a99426270c4f844bd796..b4fa5b627269b778a88253fb08a5425fe5e6a12d 100644 --- ethereum/go-ethereum/eth/tracers/internal/tracetest/prestate_test.go +++ taikoxyz/taiko-geth/eth/tracers/internal/tracetest/prestate_test.go @@ -108,8 +108,10 @@ Difficulty: (*big.Int)(test.Context.Difficulty), GasLimit: uint64(test.Context.GasLimit), BaseFee: test.Genesis.BaseFee, } - _, statedb = tests.MakePreState(rawdb.NewMemoryDatabase(), test.Genesis.Alloc, false) + triedb, _, statedb = tests.MakePreState(rawdb.NewMemoryDatabase(), test.Genesis.Alloc, false, rawdb.HashScheme) ) + defer triedb.Close() + tracer, err := tracers.DefaultDirectory.New(tracerName, new(tracers.Context), test.TracerConfig) if err != nil { t.Fatalf("failed to create call tracer: %v", err)
diff --git ethereum/go-ethereum/eth/tracers/js/goja.go taikoxyz/taiko-geth/eth/tracers/js/goja.go index f3d63df8ed5d87f1dc3e5823c68ea532e155aee3..d22d140988fe16cf2132e6b0fed79154751fb92e 100644 --- ethereum/go-ethereum/eth/tracers/js/goja.go +++ taikoxyz/taiko-geth/eth/tracers/js/goja.go @@ -236,7 +236,12 @@ t.ctx["from"] = t.vm.ToValue(from.Bytes()) t.ctx["to"] = t.vm.ToValue(to.Bytes()) t.ctx["input"] = t.vm.ToValue(input) t.ctx["gas"] = t.vm.ToValue(t.gasLimit) - t.ctx["gasPrice"] = t.vm.ToValue(env.TxContext.GasPrice) + gasPriceBig, err := t.toBig(t.vm, env.TxContext.GasPrice.String()) + if err != nil { + t.err = err + return + } + t.ctx["gasPrice"] = gasPriceBig valueBig, err := t.toBig(t.vm, value.String()) if err != nil { t.err = err
diff --git ethereum/go-ethereum/ethclient/gethclient/gethclient.go taikoxyz/taiko-geth/ethclient/gethclient/gethclient.go index c029611678f0eda620e81c27f10680fd2fae2392..e2c0ef3ed02ea7b1a575f85959203d63b173b3ed 100644 --- ethereum/go-ethereum/ethclient/gethclient/gethclient.go +++ taikoxyz/taiko-geth/ethclient/gethclient/gethclient.go @@ -225,7 +225,7 @@ "from": msg.From, "to": msg.To, } if len(msg.Data) > 0 { - arg["data"] = hexutil.Bytes(msg.Data) + arg["input"] = hexutil.Bytes(msg.Data) } if msg.Value != nil { arg["value"] = (*hexutil.Big)(msg.Value)
diff --git ethereum/go-ethereum/ethclient/gethclient/gethclient_test.go taikoxyz/taiko-geth/ethclient/gethclient/gethclient_test.go index 5a0f4d2534e32d7a2e66a52d53f80f2fc56ed127..de45b106957afd3f65d81d7272f4ef8aba012deb 100644 --- ethereum/go-ethereum/ethclient/gethclient/gethclient_test.go +++ taikoxyz/taiko-geth/ethclient/gethclient/gethclient_test.go @@ -39,11 +39,12 @@ "github.com/ethereum/go-ethereum/rpc" )   var ( - testKey, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291") - testAddr = crypto.PubkeyToAddress(testKey.PublicKey) - testSlot = common.HexToHash("0xdeadbeef") - testValue = crypto.Keccak256Hash(testSlot[:]) - testBalance = big.NewInt(2e15) + testKey, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291") + testAddr = crypto.PubkeyToAddress(testKey.PublicKey) + testContract = common.HexToAddress("0xbeef") + testSlot = common.HexToHash("0xdeadbeef") + testValue = crypto.Keccak256Hash(testSlot[:]) + testBalance = big.NewInt(2e15) )   func newTestBackend(t *testing.T) (*node.Node, []*types.Block) { @@ -78,8 +79,9 @@ }   func generateTestChain() (*core.Genesis, []*types.Block) { genesis := &core.Genesis{ - Config: params.AllEthashProtocolChanges, - Alloc: core.GenesisAlloc{testAddr: {Balance: testBalance, Storage: map[common.Hash]common.Hash{testSlot: testValue}}}, + Config: params.AllEthashProtocolChanges, + Alloc: core.GenesisAlloc{testAddr: {Balance: testBalance, Storage: map[common.Hash]common.Hash{testSlot: testValue}}, + testContract: {Nonce: 1, Code: []byte{0x13, 0x37}}}, ExtraData: []byte("test genesis"), Timestamp: 9000, } @@ -103,8 +105,11 @@ name string test func(t *testing.T) }{ { - "TestGetProof", - func(t *testing.T) { testGetProof(t, client) }, + "TestGetProof1", + func(t *testing.T) { testGetProof(t, client, testAddr) }, + }, { + "TestGetProof2", + func(t *testing.T) { testGetProof(t, client, testContract) }, }, { "TestGetProofCanonicalizeKeys", func(t *testing.T) { testGetProofCanonicalizeKeys(t, client) }, @@ -201,38 +206,41 @@ t.Fatalf("unexpected storage key: %v", (*al)[0].StorageKeys[0]) } }   -func testGetProof(t *testing.T, client *rpc.Client) { +func testGetProof(t *testing.T, client *rpc.Client, addr common.Address) { ec := New(client) ethcl := ethclient.NewClient(client) - result, err := ec.GetProof(context.Background(), testAddr, []string{testSlot.String()}, nil) + result, err := ec.GetProof(context.Background(), addr, []string{testSlot.String()}, nil) if err != nil { t.Fatal(err) } - if !bytes.Equal(result.Address[:], testAddr[:]) { - t.Fatalf("unexpected address, want: %v got: %v", testAddr, result.Address) + if result.Address != addr { + t.Fatalf("unexpected address, have: %v want: %v", result.Address, addr) } // test nonce - nonce, _ := ethcl.NonceAt(context.Background(), result.Address, nil) - if result.Nonce != nonce { + if nonce, _ := ethcl.NonceAt(context.Background(), addr, nil); result.Nonce != nonce { t.Fatalf("invalid nonce, want: %v got: %v", nonce, result.Nonce) } // test balance - balance, _ := ethcl.BalanceAt(context.Background(), result.Address, nil) - if result.Balance.Cmp(balance) != 0 { + if balance, _ := ethcl.BalanceAt(context.Background(), addr, nil); result.Balance.Cmp(balance) != 0 { t.Fatalf("invalid balance, want: %v got: %v", balance, result.Balance) } - // test storage if len(result.StorageProof) != 1 { t.Fatalf("invalid storage proof, want 1 proof, got %v proof(s)", len(result.StorageProof)) } - proof := result.StorageProof[0] - slotValue, _ := ethcl.StorageAt(context.Background(), testAddr, testSlot, nil) - if !bytes.Equal(slotValue, proof.Value.Bytes()) { - t.Fatalf("invalid storage proof value, want: %v, got: %v", slotValue, proof.Value.Bytes()) + for _, proof := range result.StorageProof { + if proof.Key != testSlot.String() { + t.Fatalf("invalid storage proof key, want: %q, got: %q", testSlot.String(), proof.Key) + } + slotValue, _ := ethcl.StorageAt(context.Background(), addr, common.HexToHash(proof.Key), nil) + if have, want := common.BigToHash(proof.Value), common.BytesToHash(slotValue); have != want { + t.Fatalf("addr %x, invalid storage proof value: have: %v, want: %v", addr, have, want) + } } - if proof.Key != testSlot.String() { - t.Fatalf("invalid storage proof key, want: %q, got: %q", testSlot.String(), proof.Key) + // test code + code, _ := ethcl.CodeAt(context.Background(), addr, nil) + if have, want := result.CodeHash, crypto.Keccak256Hash(code); have != want { + t.Fatalf("codehash wrong, have %v want %v ", have, want) } }
diff --git ethereum/go-ethereum/ethdb/leveldb/leveldb.go taikoxyz/taiko-geth/ethdb/leveldb/leveldb.go index c0e0eb250a75811dabb804fd5800ce27a7812810..e58efbddbe80eb271c706db78f52672db4411cf8 100644 --- ethereum/go-ethereum/ethdb/leveldb/leveldb.go +++ taikoxyz/taiko-geth/ethdb/leveldb/leveldb.go @@ -22,6 +22,7 @@ package leveldb   import ( "fmt" + "strings" "sync" "time"   @@ -245,6 +246,11 @@ }   // Stat returns a particular internal stat of the database. func (db *Database) Stat(property string) (string, error) { + if property == "" { + property = "leveldb.stats" + } else if !strings.HasPrefix(property, "leveldb.") { + property = "leveldb." + property + } return db.db.GetProperty(property) }
diff --git ethereum/go-ethereum/ethdb/pebble/pebble.go taikoxyz/taiko-geth/ethdb/pebble/pebble.go index a06f59bcfae4e555a634a2cbfe1d6ed1e4921c7d..691aa732998642631bd646e4ef2070310a18c48e 100644 --- ethereum/go-ethereum/ethdb/pebble/pebble.go +++ taikoxyz/taiko-geth/ethdb/pebble/pebble.go @@ -14,8 +14,6 @@ // // You should have received a copy of the GNU Lesser General Public License // along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.   -//go:build (arm64 || amd64) && !openbsd - // Package pebble implements the key-value database layer based on pebble. package pebble   @@ -27,6 +25,7 @@ "sync" "sync/atomic" "time"   + "github.com/cockroachdb/errors" "github.com/cockroachdb/pebble" "github.com/cockroachdb/pebble/bloom" "github.com/ethereum/go-ethereum/common" @@ -70,6 +69,8 @@ nonlevel0CompGauge metrics.Gauge // Gauge for tracking the number of table compaction in non0 level seekCompGauge metrics.Gauge // Gauge for tracking the number of table compaction caused by read opt manualMemAllocGauge metrics.Gauge // Gauge for tracking amount of non-managed memory currently allocated   + levelsGauge []metrics.Gauge // Gauge for tracking the number of tables in levels + quitLock sync.RWMutex // Mutex protecting the quit channel and the closed flag quitChan chan chan error // Quit channel to stop the metrics collection before closing the database closed bool // keep track of whether we're Closed @@ -84,6 +85,8 @@ nonLevel0Comp atomic.Uint32 // Total number of non level-zero compactions writeDelayStartTime time.Time // The start time of the latest write stall writeDelayCount atomic.Int64 // Total number of write stall counts writeDelayTime atomic.Int64 // Total time spent in write stalls + + writeOptions *pebble.WriteOptions }   func (d *Database) onCompactionBegin(info pebble.CompactionInfo) { @@ -116,9 +119,21 @@ func (d *Database) onWriteStallEnd() { d.writeDelayTime.Add(int64(time.Since(d.writeDelayStartTime))) }   +// panicLogger is just a noop logger to disable Pebble's internal logger. +// +// TODO(karalabe): Remove when Pebble sets this as the default. +type panicLogger struct{} + +func (l panicLogger) Infof(format string, args ...interface{}) { +} + +func (l panicLogger) Fatalf(format string, args ...interface{}) { + panic(errors.Errorf("fatal: "+format, args...)) +} + // New returns a wrapped pebble DB object. The namespace is the prefix that the // metrics reporting should use for surfacing internal stats. -func New(file string, cache int, handles int, namespace string, readonly bool) (*Database, error) { +func New(file string, cache int, handles int, namespace string, readonly bool, ephemeral bool) (*Database, error) { // Ensure we have some minimal caching and file guarantees if cache < minCache { cache = minCache @@ -131,8 +146,15 @@ logger.Info("Allocated cache and file handles", "cache", common.StorageSize(cache*1024*1024), "handles", handles)   // The max memtable size is limited by the uint32 offsets stored in // internal/arenaskl.node, DeferredBatchOp, and flushableBatchEntry. - // Taken from https://github.com/cockroachdb/pebble/blob/master/open.go#L38 - maxMemTableSize := 4<<30 - 1 // Capped by 4 GB + // + // - MaxUint32 on 64-bit platforms; + // - MaxInt on 32-bit platforms. + // + // It is used when slices are limited to Uint32 on 64-bit platforms (the + // length limit for slices is naturally MaxInt on 32-bit platforms). + // + // Taken from https://github.com/cockroachdb/pebble/blob/master/internal/constants/constants.go + maxMemTableSize := (1<<31)<<(^uint(0)>>63) - 1   // Two memory tables is configured which is identical to leveldb, // including a frozen memory table and another live one. @@ -142,9 +164,10 @@ if memTableSize > maxMemTableSize { memTableSize = maxMemTableSize } db := &Database{ - fn: file, - log: logger, - quitChan: make(chan chan error), + fn: file, + log: logger, + quitChan: make(chan chan error), + writeOptions: &pebble.WriteOptions{Sync: !ephemeral}, } opt := &pebble.Options{ // Pebble has a single combined cache area and the write @@ -155,7 +178,7 @@ MaxOpenFiles: handles,   // The size of memory table(as well as the write buffer). // Note, there may have more than two memory tables in the system. - MemTableSize: memTableSize, + MemTableSize: uint64(memTableSize),   // MemTableStopWritesThreshold places a hard limit on the size // of the existent MemTables(including the frozen one). @@ -186,6 +209,7 @@ CompactionEnd: db.onCompactionEnd, WriteStallBegin: db.onWriteStallBegin, WriteStallEnd: db.onWriteStallEnd, }, + Logger: panicLogger{}, // TODO(karalabe): Delete when this is upstreamed in Pebble } // Disable seek compaction explicitly. Check https://github.com/ethereum/go-ethereum/pull/20130 // for more details. @@ -213,7 +237,7 @@ db.seekCompGauge = metrics.NewRegisteredGauge(namespace+"compact/seek", nil) db.manualMemAllocGauge = metrics.NewRegisteredGauge(namespace+"memory/manualalloc", nil)   // Start up the metrics gathering and return - go db.meter(metricsGatheringInterval) + go db.meter(metricsGatheringInterval, namespace) return db, nil }   @@ -279,7 +303,7 @@ defer d.quitLock.RUnlock() if d.closed { return pebble.ErrClosed } - return d.db.Set(key, value, pebble.Sync) + return d.db.Set(key, value, d.writeOptions) }   // Delete removes the key from the key-value store. @@ -302,12 +326,9 @@ } }   // NewBatchWithSize creates a write-only database batch with pre-allocated buffer. -// It's not supported by pebble, but pebble has better memory allocation strategy -// which turns out a lot faster than leveldb. It's performant enough to construct -// batch object without any pre-allocated space. -func (d *Database) NewBatchWithSize(_ int) ethdb.Batch { +func (d *Database) NewBatchWithSize(size int) ethdb.Batch { return &batch{ - b: d.db.NewBatch(), + b: d.db.NewBatchWithSize(size), db: d, } } @@ -376,9 +397,12 @@ } return limit }   -// Stat returns a particular internal stat of the database. +// Stat returns the internal metrics of Pebble in a text format. It's a developer +// method to read everything there is to read independent of Pebble version. +// +// The property is unused in Pebble as there's only one thing to retrieve. func (d *Database) Stat(property string) (string, error) { - return "", nil + return d.db.Metrics().String(), nil }   // Compact flattens the underlying data store for the given key range. In essence, @@ -410,7 +434,7 @@ }   // meter periodically retrieves internal pebble counters and reports them to // the metrics subsystem. -func (d *Database) meter(refresh time.Duration) { +func (d *Database) meter(refresh time.Duration, namespace string) { var errc chan error timer := time.NewTimer(refresh) defer timer.Stop() @@ -433,7 +457,7 @@ compWrite int64 compRead int64 nWrite int64   - metrics = d.db.Metrics() + stats = d.db.Metrics() compTime = d.compTime.Load() writeDelayCount = d.writeDelayCount.Load() writeDelayTime = d.writeDelayTime.Load() @@ -444,14 +468,14 @@ writeDelayTimes[i%2] = writeDelayTime writeDelayCounts[i%2] = writeDelayCount compTimes[i%2] = compTime   - for _, levelMetrics := range metrics.Levels { + for _, levelMetrics := range stats.Levels { nWrite += int64(levelMetrics.BytesCompacted) nWrite += int64(levelMetrics.BytesFlushed) compWrite += int64(levelMetrics.BytesCompacted) compRead += int64(levelMetrics.BytesRead) }   - nWrite += int64(metrics.WAL.BytesWritten) + nWrite += int64(stats.WAL.BytesWritten)   compWrites[i%2] = compWrite compReads[i%2] = compRead @@ -473,7 +497,7 @@ if d.compWriteMeter != nil { d.compWriteMeter.Mark(compWrites[i%2] - compWrites[(i-1)%2]) } if d.diskSizeGauge != nil { - d.diskSizeGauge.Update(int64(metrics.DiskSpaceUsage())) + d.diskSizeGauge.Update(int64(stats.DiskSpaceUsage())) } if d.diskReadMeter != nil { d.diskReadMeter.Mark(0) // pebble doesn't track non-compaction reads @@ -482,12 +506,20 @@ if d.diskWriteMeter != nil { d.diskWriteMeter.Mark(nWrites[i%2] - nWrites[(i-1)%2]) } // See https://github.com/cockroachdb/pebble/pull/1628#pullrequestreview-1026664054 - manuallyAllocated := metrics.BlockCache.Size + int64(metrics.MemTable.Size) + int64(metrics.MemTable.ZombieSize) + manuallyAllocated := stats.BlockCache.Size + int64(stats.MemTable.Size) + int64(stats.MemTable.ZombieSize) d.manualMemAllocGauge.Update(manuallyAllocated) - d.memCompGauge.Update(metrics.Flush.Count) + d.memCompGauge.Update(stats.Flush.Count) d.nonlevel0CompGauge.Update(nonLevel0CompCount) d.level0CompGauge.Update(level0CompCount) - d.seekCompGauge.Update(metrics.Compact.ReadCount) + d.seekCompGauge.Update(stats.Compact.ReadCount) + + for i, level := range stats.Levels { + // Append metrics for additional layers + if i >= len(d.levelsGauge) { + d.levelsGauge = append(d.levelsGauge, metrics.NewRegisteredGauge(namespace+fmt.Sprintf("tables/level%v", i), nil)) + } + d.levelsGauge[i].Update(level.NumFiles) + }   // Sleep a bit, then repeat the stats collection select { @@ -535,7 +567,7 @@ defer b.db.quitLock.RUnlock() if b.db.closed { return pebble.ErrClosed } - return b.b.Commit(pebble.Sync) + return b.b.Commit(b.db.writeOptions) }   // Reset resets the batch for reuse. @@ -576,7 +608,7 @@ // NewIterator creates a binary-alphabetical iterator over a subset // of database content with a particular key prefix, starting at a particular // initial key (or after, if it does not exist). func (d *Database) NewIterator(prefix []byte, start []byte) ethdb.Iterator { - iter := d.db.NewIter(&pebble.IterOptions{ + iter, _ := d.db.NewIter(&pebble.IterOptions{ LowerBound: append(prefix, start...), UpperBound: upperBound(prefix), })
diff --git ethereum/go-ethereum/ethdb/pebble/pebble_test.go taikoxyz/taiko-geth/ethdb/pebble/pebble_test.go index 590d5bf0353d0ac09aa7904455246e3e4b153710..1d5611f211e3649ee488a3fb94a2a073179a15c4 100644 --- ethereum/go-ethereum/ethdb/pebble/pebble_test.go +++ taikoxyz/taiko-geth/ethdb/pebble/pebble_test.go @@ -14,8 +14,6 @@ // // You should have received a copy of the GNU Lesser General Public License // along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.   -//go:build (arm64 || amd64) && !openbsd - package pebble   import (
diff --git ethereum/go-ethereum/graphql/graphql.go taikoxyz/taiko-geth/graphql/graphql.go index 7aa427b458bf75f665376122b32ab738b70f6f3a..8304a64cf49f4596abdbe381d7cc2425c98e6bff 100644 --- ethereum/go-ethereum/graphql/graphql.go +++ taikoxyz/taiko-geth/graphql/graphql.go @@ -272,8 +272,6 @@ if tx == nil { return hexutil.Big{} } switch tx.Type() { - case types.AccessListTxType: - return hexutil.Big(*tx.GasPrice()) case types.DynamicFeeTxType: if block != nil { if baseFee, _ := block.BaseFeePerGas(ctx); baseFee != nil { @@ -312,9 +310,7 @@ if tx == nil { return nil } switch tx.Type() { - case types.AccessListTxType: - return nil - case types.DynamicFeeTxType: + case types.DynamicFeeTxType, types.BlobTxType: return (*hexutil.Big)(tx.GasFeeCap()) default: return nil @@ -327,13 +323,31 @@ if tx == nil { return nil } switch tx.Type() { - case types.AccessListTxType: - return nil - case types.DynamicFeeTxType: + case types.DynamicFeeTxType, types.BlobTxType: return (*hexutil.Big)(tx.GasTipCap()) default: return nil } +} + +func (t *Transaction) MaxFeePerBlobGas(ctx context.Context) *hexutil.Big { + tx, _ := t.resolve(ctx) + if tx == nil { + return nil + } + return (*hexutil.Big)(tx.BlobGasFeeCap()) +} + +func (t *Transaction) BlobVersionedHashes(ctx context.Context) *[]common.Hash { + tx, _ := t.resolve(ctx) + if tx == nil { + return nil + } + if tx.Type() != types.BlobTxType { + return nil + } + blobHashes := tx.BlobHashes() + return &blobHashes }   func (t *Transaction) EffectiveTip(ctx context.Context) (*hexutil.Big, error) { @@ -466,6 +480,40 @@ return nil, err } ret := hexutil.Uint64(receipt.CumulativeGasUsed) return &ret, nil +} + +func (t *Transaction) BlobGasUsed(ctx context.Context) (*hexutil.Uint64, error) { + tx, _ := t.resolve(ctx) + if tx == nil { + return nil, nil + } + if tx.Type() != types.BlobTxType { + return nil, nil + } + + receipt, err := t.getReceipt(ctx) + if err != nil || receipt == nil { + return nil, err + } + ret := hexutil.Uint64(receipt.BlobGasUsed) + return &ret, nil +} + +func (t *Transaction) BlobGasPrice(ctx context.Context) (*hexutil.Big, error) { + tx, _ := t.resolve(ctx) + if tx == nil { + return nil, nil + } + if tx.Type() != types.BlobTxType { + return nil, nil + } + + receipt, err := t.getReceipt(ctx) + if err != nil || receipt == nil { + return nil, err + } + ret := (*hexutil.Big)(receipt.BlobGasPrice) + return ret, nil }   func (t *Transaction) CreatedContract(ctx context.Context, args BlockNumberArgs) (*Account, error) { @@ -1019,6 +1067,30 @@ } return &ret, nil }   +func (b *Block) BlobGasUsed(ctx context.Context) (*hexutil.Uint64, error) { + header, err := b.resolveHeader(ctx) + if err != nil { + return nil, err + } + if header.BlobGasUsed == nil { + return nil, nil + } + ret := hexutil.Uint64(*header.BlobGasUsed) + return &ret, nil +} + +func (b *Block) ExcessBlobGas(ctx context.Context) (*hexutil.Uint64, error) { + header, err := b.resolveHeader(ctx) + if err != nil { + return nil, err + } + if header.ExcessBlobGas == nil { + return nil, nil + } + ret := hexutil.Uint64(*header.ExcessBlobGas) + return &ret, nil +} + // BlockFilterCriteria encapsulates criteria passed to a `logs` accessor inside // a block. type BlockFilterCriteria struct { @@ -1217,6 +1289,9 @@ func (r *Resolver) Block(ctx context.Context, args struct { Number *Long Hash *common.Hash }) (*Block, error) { + if args.Number != nil && args.Hash != nil { + return nil, errors.New("only one of number or hash must be specified") + } var numberOrHash rpc.BlockNumberOrHash if args.Number != nil { if *args.Number < 0 {
diff --git ethereum/go-ethereum/graphql/schema.go taikoxyz/taiko-geth/graphql/schema.go index 5de5bad305e85c758a94ddeac8c839602f647fcb..5738923fc17087a77869b9fc6ee9be8901186faa 100644 --- ethereum/go-ethereum/graphql/schema.go +++ taikoxyz/taiko-geth/graphql/schema.go @@ -71,8 +71,8 @@ # Transaction is the transaction that generated this log entry. transaction: Transaction! }   - #EIP-2718 - type AccessTuple{ + # EIP-2718 + type AccessTuple { address: Address! storageKeys : [Bytes32!]! } @@ -112,6 +112,8 @@ # MaxFeePerGas is the maximum fee per gas offered to include a transaction, in wei. maxFeePerGas: BigInt # MaxPriorityFeePerGas is the maximum miner tip per gas offered to include a transaction, in wei. maxPriorityFeePerGas: BigInt + # MaxFeePerBlobGas is the maximum blob gas fee cap per blob the sender is willing to pay for blob transaction, in wei. + maxFeePerBlobGas: BigInt # EffectiveTip is the actual amount of reward going to miner after considering the max fee cap. effectiveTip: BigInt # Gas is the maximum amount of gas this transaction can consume. @@ -141,6 +143,10 @@ # maxPriorityFeePerGas). Legacy transactions and EIP-2930 transactions are # coerced into the EIP-1559 format by setting both maxFeePerGas and # maxPriorityFeePerGas as the transaction's gas price. effectiveGasPrice: BigInt + # BlobGasUsed is the amount of blob gas used by this transaction. + blobGasUsed: Long + # blobGasPrice is the actual value per blob gas deducted from the senders account. + blobGasPrice: BigInt # CreatedContract is the account that was created by a contract creation # transaction. If the transaction was not a contract creation transaction, # or it has not yet been mined, this field will be null. @@ -162,6 +168,8 @@ raw: Bytes! # RawReceipt is the canonical encoding of the receipt. For post EIP-2718 typed transactions # this is equivalent to TxType || ReceiptEncoding. rawReceipt: Bytes! + # BlobVersionedHashes is a set of hash outputs from the blobs in the transaction. + blobVersionedHashes: [Bytes32!] }   # BlockFilterCriteria encapsulates log filter criteria for a filter applied @@ -171,16 +179,16 @@ # Addresses is list of addresses that are of interest. If this list is # empty, results will not be filtered by address. addresses: [Address!] # Topics list restricts matches to particular event topics. Each event has a list - # of topics. Topics matches a prefix of that list. An empty element array matches any - # topic. Non-empty elements represent an alternative that matches any of the - # contained topics. - # - # Examples: - # - [] or nil matches any topic list - # - [[A]] matches topic A in first position - # - [[], [B]] matches any topic in first position, B in second position - # - [[A], [B]] matches topic A in first position, B in second position - # - [[A, B]], [C, D]] matches topic (A OR B) in first position, (C OR D) in second position + # of topics. Topics matches a prefix of that list. An empty element array matches any + # topic. Non-empty elements represent an alternative that matches any of the + # contained topics. + # + # Examples: + # - [] or nil matches any topic list + # - [[A]] matches topic A in first position + # - [[], [B]] matches any topic in first position, B in second position + # - [[A], [B]] matches topic A in first position, B in second position + # - [[A, B]], [C, D]] matches topic (A OR B) in first position, (C OR D) in second position topics: [[Bytes32!]!] }   @@ -267,6 +275,10 @@ withdrawalsRoot: Bytes32 # Withdrawals is a list of withdrawals associated with this block. If # withdrawals are unavailable for this block, this field will be null. withdrawals: [Withdrawal!] + # BlobGasUsed is the total amount of gas used by the transactions. + blobGasUsed: Long + # ExcessBlobGas is a running total of blob gas consumed in excess of the target, prior to the block. + excessBlobGas: Long }   # CallData represents the data associated with a local contract call. @@ -312,21 +324,21 @@ # Addresses is a list of addresses that are of interest. If this list is # empty, results will not be filtered by address. addresses: [Address!] # Topics list restricts matches to particular event topics. Each event has a list - # of topics. Topics matches a prefix of that list. An empty element array matches any - # topic. Non-empty elements represent an alternative that matches any of the - # contained topics. - # - # Examples: - # - [] or nil matches any topic list - # - [[A]] matches topic A in first position - # - [[], [B]] matches any topic in first position, B in second position - # - [[A], [B]] matches topic A in first position, B in second position - # - [[A, B]], [C, D]] matches topic (A OR B) in first position, (C OR D) in second position + # of topics. Topics matches a prefix of that list. An empty element array matches any + # topic. Non-empty elements represent an alternative that matches any of the + # contained topics. + # + # Examples: + # - [] or nil matches any topic list + # - [[A]] matches topic A in first position + # - [[], [B]] matches any topic in first position, B in second position + # - [[A], [B]] matches topic A in first position, B in second position + # - [[A, B]], [C, D]] matches topic (A OR B) in first position, (C OR D) in second position topics: [[Bytes32!]!] }   # SyncState contains the current synchronisation state of the client. - type SyncState{ + type SyncState { # StartingBlock is the block number at which synchronisation started. startingBlock: Long! # CurrentBlock is the point at which synchronisation has presently reached. @@ -337,17 +349,17 @@ }   # Pending represents the current pending state. type Pending { - # TransactionCount is the number of transactions in the pending state. - transactionCount: Long! - # Transactions is a list of transactions in the current pending state. - transactions: [Transaction!] - # Account fetches an Ethereum account for the pending state. - account(address: Address!): Account! - # Call executes a local call operation for the pending state. - call(data: CallData!): CallResult - # EstimateGas estimates the amount of gas that will be required for - # successful execution of a transaction for the pending state. - estimateGas(data: CallData!): Long! + # TransactionCount is the number of transactions in the pending state. + transactionCount: Long! + # Transactions is a list of transactions in the current pending state. + transactions: [Transaction!] + # Account fetches an Ethereum account for the pending state. + account(address: Address!): Account! + # Call executes a local call operation for the pending state. + call(data: CallData!): CallResult + # EstimateGas estimates the amount of gas that will be required for + # successful execution of a transaction for the pending state. + estimateGas(data: CallData!): Long! }   type Query {
diff --git ethereum/go-ethereum/graphql/service.go taikoxyz/taiko-geth/graphql/service.go index 4ca427658a94b3677cd6f73104edf92e4836a460..f33e763058e33e7988eb02a56ab06f9ee12d841c 100644 --- ethereum/go-ethereum/graphql/service.go +++ taikoxyz/taiko-geth/graphql/service.go @@ -88,7 +88,9 @@ }) }   response := h.Schema.Exec(ctx, params.Query, params.OperationName, params.Variables) - timer.Stop() + if timer != nil { + timer.Stop() + } responded.Do(func() { responseJSON, err := json.Marshal(response) if err != nil {
diff --git ethereum/go-ethereum/internal/build/azure.go taikoxyz/taiko-geth/internal/build/azure.go index 9d1c4f300a88f3d439f15e41273b763227c19e77..4085228d14e38b28444fbc0d4bf5f36140d36cd2 100644 --- ethereum/go-ethereum/internal/build/azure.go +++ taikoxyz/taiko-geth/internal/build/azure.go @@ -22,6 +22,7 @@ "fmt" "os"   "github.com/Azure/azure-sdk-for-go/sdk/storage/azblob" + "github.com/Azure/azure-sdk-for-go/sdk/storage/azblob/container" )   // AzureBlobstoreConfig is an authentication and configuration struct containing @@ -48,8 +49,8 @@ credential, err := azblob.NewSharedKeyCredential(config.Account, config.Token) if err != nil { return err } - u := fmt.Sprintf("https://%s.blob.core.windows.net/%s", config.Account, config.Container) - container, err := azblob.NewContainerClientWithSharedKey(u, credential, nil) + a := fmt.Sprintf("https://%s.blob.core.windows.net/", config.Account) + client, err := azblob.NewClientWithSharedKeyCredential(a, credential, nil) if err != nil { return err } @@ -60,38 +61,38 @@ return err } defer in.Close()   - blockblob := container.NewBlockBlobClient(name) - _, err = blockblob.Upload(context.Background(), in, nil) + _, err = client.UploadFile(context.Background(), config.Container, name, in, nil) return err }   // AzureBlobstoreList lists all the files contained within an azure blobstore. -func AzureBlobstoreList(config AzureBlobstoreConfig) ([]*azblob.BlobItemInternal, error) { +func AzureBlobstoreList(config AzureBlobstoreConfig) ([]*container.BlobItem, error) { // Create an authenticated client against the Azure cloud credential, err := azblob.NewSharedKeyCredential(config.Account, config.Token) if err != nil { return nil, err } - u := fmt.Sprintf("https://%s.blob.core.windows.net/%s", config.Account, config.Container) - container, err := azblob.NewContainerClientWithSharedKey(u, credential, nil) + a := fmt.Sprintf("https://%s.blob.core.windows.net/", config.Account) + client, err := azblob.NewClientWithSharedKeyCredential(a, credential, nil) if err != nil { return nil, err } - var maxResults int32 = 5000 - pager := container.ListBlobsFlat(&azblob.ContainerListBlobFlatSegmentOptions{ - Maxresults: &maxResults, - }) - var allBlobs []*azblob.BlobItemInternal - for pager.NextPage(context.Background()) { - res := pager.PageResponse() - allBlobs = append(allBlobs, res.ContainerListBlobFlatSegmentResult.Segment.BlobItems...) + pager := client.NewListBlobsFlatPager(config.Container, nil) + + var blobs []*container.BlobItem + for pager.More() { + page, err := pager.NextPage(context.TODO()) + if err != nil { + return nil, err + } + blobs = append(blobs, page.Segment.BlobItems...) } - return allBlobs, pager.Err() + return blobs, nil }   // AzureBlobstoreDelete iterates over a list of files to delete and removes them // from the blobstore. -func AzureBlobstoreDelete(config AzureBlobstoreConfig, blobs []*azblob.BlobItemInternal) error { +func AzureBlobstoreDelete(config AzureBlobstoreConfig, blobs []*container.BlobItem) error { if *DryRunFlag { for _, blob := range blobs { fmt.Printf("would delete %s (%s) from %s/%s\n", *blob.Name, blob.Properties.LastModified, config.Account, config.Container) @@ -103,15 +104,14 @@ credential, err := azblob.NewSharedKeyCredential(config.Account, config.Token) if err != nil { return err } - u := fmt.Sprintf("https://%s.blob.core.windows.net/%s", config.Account, config.Container) - container, err := azblob.NewContainerClientWithSharedKey(u, credential, nil) + a := fmt.Sprintf("https://%s.blob.core.windows.net/", config.Account) + client, err := azblob.NewClientWithSharedKeyCredential(a, credential, nil) if err != nil { return err } // Iterate over the blobs and delete them for _, blob := range blobs { - blockblob := container.NewBlockBlobClient(*blob.Name) - if _, err := blockblob.Delete(context.Background(), &azblob.DeleteBlobOptions{}); err != nil { + if _, err := client.DeleteBlob(context.Background(), config.Container, *blob.Name, nil); err != nil { return err } fmt.Printf("deleted %s (%s)\n", *blob.Name, blob.Properties.LastModified)
diff --git ethereum/go-ethereum/internal/build/gotool.go taikoxyz/taiko-geth/internal/build/gotool.go index 296ba8c36ecb050a269af4a498abc802c15b5618..32ca20e869a54251f2d9150a5a06536fdcba6e0c 100644 --- ethereum/go-ethereum/internal/build/gotool.go +++ taikoxyz/taiko-geth/internal/build/gotool.go @@ -84,7 +84,11 @@ }   // DownloadGo downloads the Go binary distribution and unpacks it into a temporary // directory. It returns the GOROOT of the unpacked toolchain. -func DownloadGo(csdb *ChecksumDB, version string) string { +func DownloadGo(csdb *ChecksumDB) string { + version, err := Version(csdb, "golang") + if err != nil { + log.Fatal(err) + } // Shortcut: if the Go version that runs this script matches the // requested version exactly, there is no need to download anything. activeGo := strings.TrimPrefix(runtime.Version(), "go") @@ -126,3 +130,52 @@ log.Fatal(err) } return goroot } + +// Version returns the versions defined in the checksumdb. +func Version(csdb *ChecksumDB, version string) (string, error) { + for _, l := range csdb.allChecksums { + if !strings.HasPrefix(l, "# version:") { + continue + } + v := strings.Split(l, ":")[1] + parts := strings.Split(v, " ") + if len(parts) != 2 { + log.Print("Erroneous version-string", "v", l) + continue + } + if parts[0] == version { + log.Printf("Found version %q", parts[1]) + return parts[1], nil + } + } + return "", fmt.Errorf("no version found for '%v'", version) +} + +// DownloadAndVerifyChecksums downloads all files and checks that they match +// the checksum given in checksums.txt. +// This task can be used to sanity-check new checksums. +func DownloadAndVerifyChecksums(csdb *ChecksumDB) { + var ( + base = "" + ucache = os.TempDir() + ) + for _, l := range csdb.allChecksums { + if strings.HasPrefix(l, "# https://") { + base = l[2:] + continue + } + if strings.HasPrefix(l, "#") { + continue + } + hashFile := strings.Split(l, " ") + if len(hashFile) != 2 { + continue + } + file := hashFile[1] + url := base + file + dst := filepath.Join(ucache, file) + if err := csdb.DownloadFile(url, dst); err != nil { + log.Print(err) + } + } +}
diff --git ethereum/go-ethereum/internal/debug/flags.go taikoxyz/taiko-geth/internal/debug/flags.go index 52a6342452a17ea09b9311cfd03fa2454b4188cf..736fede9433499a7dc02741a7a28e9aa53aabdc7 100644 --- ethereum/go-ethereum/internal/debug/flags.go +++ taikoxyz/taiko-geth/internal/debug/flags.go @@ -87,8 +87,9 @@ Usage: "Prepends log messages with call-site location (file and line number)", Category: flags.LoggingCategory, } logRotateFlag = &cli.BoolFlag{ - Name: "log.rotate", - Usage: "Enables log file rotation", + Name: "log.rotate", + Usage: "Enables log file rotation", + Category: flags.LoggingCategory, } logMaxSizeMBsFlag = &cli.IntFlag{ Name: "log.maxsize",
diff --git ethereum/go-ethereum/internal/debug/loudpanic.go taikoxyz/taiko-geth/internal/debug/loudpanic.go index 86e6bc88f83f2df82e60975aa967c29674614121..a7296e7b3f334b1a1d1a064177469323875610db 100644 --- ethereum/go-ethereum/internal/debug/loudpanic.go +++ taikoxyz/taiko-geth/internal/debug/loudpanic.go @@ -14,9 +14,6 @@ // // You should have received a copy of the GNU Lesser General Public License // along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.   -//go:build go1.6 -// +build go1.6 - package debug   import "runtime/debug"
diff --git ethereum/go-ethereum/internal/debug/loudpanic_fallback.go taikoxyz/taiko-geth/internal/debug/loudpanic_fallback.go deleted file mode 100644 index 377490e5bee571fa18bd97e8bb9502a42990fe46..0000000000000000000000000000000000000000 --- ethereum/go-ethereum/internal/debug/loudpanic_fallback.go +++ /dev/null @@ -1,25 +0,0 @@ -// Copyright 2016 The go-ethereum Authors -// This file is part of the go-ethereum library. -// -// The go-ethereum library is free software: you can redistribute it and/or modify -// it under the terms of the GNU Lesser General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// The go-ethereum library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Lesser General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public License -// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>. - -//go:build !go1.6 -// +build !go1.6 - -package debug - -// LoudPanic panics in a way that gets all goroutine stacks printed on stderr. -func LoudPanic(x interface{}) { - panic(x) -}
diff --git ethereum/go-ethereum/internal/debug/trace.go taikoxyz/taiko-geth/internal/debug/trace.go index eea879823429b3107bac2d0e3e87a006f6cc9cb4..e291030b82e32bac23eaa1579add8350cb50c853 100644 --- ethereum/go-ethereum/internal/debug/trace.go +++ taikoxyz/taiko-geth/internal/debug/trace.go @@ -14,9 +14,6 @@ // // You should have received a copy of the GNU Lesser General Public License // along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.   -//go:build go1.5 -// +build go1.5 - package debug   import (
diff --git ethereum/go-ethereum/internal/debug/trace_fallback.go taikoxyz/taiko-geth/internal/debug/trace_fallback.go deleted file mode 100644 index ec07d991efd62d43a0164d9a0c26723c4d7cb0e0..0000000000000000000000000000000000000000 --- ethereum/go-ethereum/internal/debug/trace_fallback.go +++ /dev/null @@ -1,32 +0,0 @@ -// Copyright 2016 The go-ethereum Authors -// This file is part of the go-ethereum library. -// -// The go-ethereum library is free software: you can redistribute it and/or modify -// it under the terms of the GNU Lesser General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// The go-ethereum library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Lesser General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public License -// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>. - -//go:build !go1.5 -// +build !go1.5 - -// no-op implementation of tracing methods for Go < 1.5. - -package debug - -import "errors" - -func (*HandlerT) StartGoTrace(string) error { - return errors.New("tracing is not supported on Go < 1.5") -} - -func (*HandlerT) StopGoTrace() error { - return errors.New("tracing is not supported on Go < 1.5") -}
diff --git ethereum/go-ethereum/internal/ethapi/api.go taikoxyz/taiko-geth/internal/ethapi/api.go index 52dbaf164cd79c0e6799772adb2a8019149c2ba5..640693132e2bb6c34bcee6bfdce1044b21481834 100644 --- ethereum/go-ethereum/internal/ethapi/api.go +++ taikoxyz/taiko-geth/internal/ethapi/api.go @@ -46,6 +46,7 @@ "github.com/ethereum/go-ethereum/p2p" "github.com/ethereum/go-ethereum/params" "github.com/ethereum/go-ethereum/rlp" "github.com/ethereum/go-ethereum/rpc" + "github.com/ethereum/go-ethereum/trie" "github.com/tyler-smith/go-bip39" )   @@ -674,9 +675,6 @@ var ( keys = make([]common.Hash, len(storageKeys)) keyLengths = make([]int, len(storageKeys)) storageProof = make([]StorageResult, len(storageKeys)) - storageTrie state.Trie - storageHash = types.EmptyRootHash - codeHash = types.EmptyCodeHash ) // Deserialize all keys. This prevents state access on invalid input. for i, hexKey := range storageKeys { @@ -686,61 +684,65 @@ if err != nil { return nil, err } } - - state, _, err := s.b.StateAndHeaderByNumberOrHash(ctx, blockNrOrHash) - if state == nil || err != nil { - return nil, err - } - if storageTrie, err = state.StorageTrie(address); err != nil { + statedb, header, err := s.b.StateAndHeaderByNumberOrHash(ctx, blockNrOrHash) + if statedb == nil || err != nil { return nil, err } + codeHash := statedb.GetCodeHash(address) + storageRoot := statedb.GetStorageRoot(address)   - // If we have a storageTrie, the account exists and we must update - // the storage root hash and the code hash. - if storageTrie != nil { - storageHash = storageTrie.Hash() - codeHash = state.GetCodeHash(address) - } - // Create the proofs for the storageKeys. - for i, key := range keys { - // Output key encoding is a bit special: if the input was a 32-byte hash, it is - // returned as such. Otherwise, we apply the QUANTITY encoding mandated by the - // JSON-RPC spec for getProof. This behavior exists to preserve backwards - // compatibility with older client versions. - var outputKey string - if keyLengths[i] != 32 { - outputKey = hexutil.EncodeBig(key.Big()) - } else { - outputKey = hexutil.Encode(key[:]) + if len(keys) > 0 { + var storageTrie state.Trie + if storageRoot != types.EmptyRootHash && storageRoot != (common.Hash{}) { + id := trie.StorageTrieID(header.Root, crypto.Keccak256Hash(address.Bytes()), storageRoot) + st, err := trie.NewStateTrie(id, statedb.Database().TrieDB()) + if err != nil { + return nil, err + } + storageTrie = st } - - if storageTrie == nil { - storageProof[i] = StorageResult{outputKey, &hexutil.Big{}, []string{}} - continue + // Create the proofs for the storageKeys. + for i, key := range keys { + // Output key encoding is a bit special: if the input was a 32-byte hash, it is + // returned as such. Otherwise, we apply the QUANTITY encoding mandated by the + // JSON-RPC spec for getProof. This behavior exists to preserve backwards + // compatibility with older client versions. + var outputKey string + if keyLengths[i] != 32 { + outputKey = hexutil.EncodeBig(key.Big()) + } else { + outputKey = hexutil.Encode(key[:]) + } + if storageTrie == nil { + storageProof[i] = StorageResult{outputKey, &hexutil.Big{}, []string{}} + continue + } + var proof proofList + if err := storageTrie.Prove(crypto.Keccak256(key.Bytes()), &proof); err != nil { + return nil, err + } + value := (*hexutil.Big)(statedb.GetState(address, key).Big()) + storageProof[i] = StorageResult{outputKey, value, proof} } - var proof proofList - if err := storageTrie.Prove(crypto.Keccak256(key.Bytes()), &proof); err != nil { - return nil, err - } - value := (*hexutil.Big)(state.GetState(address, key).Big()) - storageProof[i] = StorageResult{outputKey, value, proof} } - // Create the accountProof. - accountProof, proofErr := state.GetProof(address) - if proofErr != nil { - return nil, proofErr + tr, err := trie.NewStateTrie(trie.StateTrieID(header.Root), statedb.Database().TrieDB()) + if err != nil { + return nil, err + } + var accountProof proofList + if err := tr.Prove(crypto.Keccak256(address.Bytes()), &accountProof); err != nil { + return nil, err } - return &AccountResult{ Address: address, - AccountProof: toHexSlice(accountProof), - Balance: (*hexutil.Big)(state.GetBalance(address)), + AccountProof: accountProof, + Balance: (*hexutil.Big)(statedb.GetBalance(address)), CodeHash: codeHash, - Nonce: hexutil.Uint64(state.GetNonce(address)), - StorageHash: storageHash, + Nonce: hexutil.Uint64(statedb.GetNonce(address)), + StorageHash: storageRoot, StorageProof: storageProof, - }, state.Error() + }, statedb.Error() }   // decodeHash parses a hex-encoded 32-byte hash. The input may optionally @@ -897,6 +899,34 @@ res := state.GetState(address, key) return res[:], state.Error() }   +// GetBlockReceipts returns the block receipts for the given block hash or number or tag. +func (s *BlockChainAPI) GetBlockReceipts(ctx context.Context, blockNrOrHash rpc.BlockNumberOrHash) ([]map[string]interface{}, error) { + block, err := s.b.BlockByNumberOrHash(ctx, blockNrOrHash) + if block == nil || err != nil { + // When the block doesn't exist, the RPC method should return JSON null + // as per specification. + return nil, nil + } + receipts, err := s.b.GetReceipts(ctx, block.Hash()) + if err != nil { + return nil, err + } + txs := block.Transactions() + if len(txs) != len(receipts) { + return nil, fmt.Errorf("receipts length mismatch: %d vs %d", len(txs), len(receipts)) + } + + // Derive the sender. + signer := types.MakeSigner(s.b.ChainConfig(), block.Number(), block.Time()) + + result := make([]map[string]interface{}, len(receipts)) + for i, receipt := range receipts { + result[i] = marshalReceipt(receipt, block.Hash(), block.NumberU64(), signer, txs[i], i) + } + + return result, nil +} + // OverrideAccount indicates the overriding fields of account during the execution // of a message call. // Note, state and stateDiff can't be specified at the same time. If state is @@ -955,13 +985,14 @@ }   // BlockOverrides is a set of header fields to override. type BlockOverrides struct { - Number *hexutil.Big - Difficulty *hexutil.Big - Time *hexutil.Uint64 - GasLimit *hexutil.Uint64 - Coinbase *common.Address - Random *common.Hash - BaseFee *hexutil.Big + Number *hexutil.Big + Difficulty *hexutil.Big + Time *hexutil.Uint64 + GasLimit *hexutil.Uint64 + Coinbase *common.Address + Random *common.Hash + BaseFee *hexutil.Big + BlobBaseFee *hexutil.Big }   // Apply overrides the given header fields into the given block context. @@ -989,6 +1020,9 @@ blockCtx.Random = diff.Random } if diff.BaseFee != nil { blockCtx.BaseFee = diff.BaseFee.ToInt() + } + if diff.BlobBaseFee != nil { + blockCtx.BlobBaseFee = diff.BlobBaseFee.ToInt() } }   @@ -1122,8 +1156,12 @@ // Additionally, the caller can specify a batch of contract for fields overriding. // // Note, this function doesn't make and changes in the state/blockchain and is // useful to execute and retrieve values. -func (s *BlockChainAPI) Call(ctx context.Context, args TransactionArgs, blockNrOrHash rpc.BlockNumberOrHash, overrides *StateOverride, blockOverrides *BlockOverrides) (hexutil.Bytes, error) { - result, err := DoCall(ctx, s.b, args, blockNrOrHash, overrides, blockOverrides, s.b.RPCEVMTimeout(), s.b.RPCGasCap()) +func (s *BlockChainAPI) Call(ctx context.Context, args TransactionArgs, blockNrOrHash *rpc.BlockNumberOrHash, overrides *StateOverride, blockOverrides *BlockOverrides) (hexutil.Bytes, error) { + if blockNrOrHash == nil { + latest := rpc.BlockNumberOrHashWithNumber(rpc.LatestBlockNumber) + blockNrOrHash = &latest + } + result, err := DoCall(ctx, s.b, args, *blockNrOrHash, overrides, blockOverrides, s.b.RPCEVMTimeout(), s.b.RPCGasCap()) if err != nil { return nil, err } @@ -1134,12 +1172,30 @@ } return result.Return(), result.Err }   +// executeEstimate is a helper that executes the transaction under a given gas limit and returns +// true if the transaction fails for a reason that might be related to not enough gas. A non-nil +// error means execution failed due to reasons unrelated to the gas limit. +func executeEstimate(ctx context.Context, b Backend, args TransactionArgs, state *state.StateDB, header *types.Header, gasCap uint64, gasLimit uint64) (bool, *core.ExecutionResult, error) { + args.Gas = (*hexutil.Uint64)(&gasLimit) + result, err := doCall(ctx, b, args, state, header, nil, nil, 0, gasCap) + if err != nil { + if errors.Is(err, core.ErrIntrinsicGas) { + return true, nil, nil // Special case, raise gas limit + } + return true, nil, err // Bail out + } + return result.Failed(), result, nil +} + +// DoEstimateGas returns the lowest possible gas limit that allows the transaction to run +// successfully at block `blockNrOrHash`. It returns error if the transaction would revert, or if +// there are unexpected failures. The gas limit is capped by both `args.Gas` (if non-nil & +// non-zero) and `gasCap` (if non-zero). func DoEstimateGas(ctx context.Context, b Backend, args TransactionArgs, blockNrOrHash rpc.BlockNumberOrHash, overrides *StateOverride, gasCap uint64) (hexutil.Uint64, error) { - // Binary search the gas requirement, as it may be higher than the amount used + // Binary search the gas limit, as it may need to be higher than the amount used var ( - lo uint64 = params.TxGas - 1 - hi uint64 - cap uint64 + lo uint64 // lowest-known gas limit where tx execution fails + hi uint64 // lowest-known gas limit where tx execution succeeds ) // Use zero address if sender unspecified. if args.From == nil { @@ -1170,16 +1226,17 @@ feeCap = args.MaxFeePerGas.ToInt() } else { feeCap = common.Big0 } + + state, header, err := b.StateAndHeaderByNumberOrHash(ctx, blockNrOrHash) + if state == nil || err != nil { + return 0, err + } + if err := overrides.Apply(state); err != nil { + return 0, err + } + // Recap the highest gas limit with account's available balance. if feeCap.BitLen() != 0 { - state, _, err := b.StateAndHeaderByNumberOrHash(ctx, blockNrOrHash) - if err != nil { - return 0, err - } - err = overrides.Apply(state) - if err != nil { - return 0, err - } balance := state.GetBalance(*args.From) // from can't be nil available := new(big.Int).Set(balance) if args.Value != nil { @@ -1206,39 +1263,42 @@ if gasCap != 0 && hi > gasCap { log.Warn("Caller gas above allowance, capping", "requested", hi, "cap", gasCap) hi = gasCap } - cap = hi   - // Create a helper to check if a gas allowance results in an executable transaction - executable := func(gas uint64, state *state.StateDB, header *types.Header) (bool, *core.ExecutionResult, error) { - args.Gas = (*hexutil.Uint64)(&gas) - - result, err := doCall(ctx, b, args, state, header, nil, nil, 0, gasCap) - if err != nil { - if errors.Is(err, core.ErrIntrinsicGas) { - return true, nil, nil // Special case, raise gas limit + // We first execute the transaction at the highest allowable gas limit, since if this fails we + // can return error immediately. + failed, result, err := executeEstimate(ctx, b, args, state.Copy(), header, gasCap, hi) + if err != nil { + return 0, err + } + if failed { + if result != nil && result.Err != vm.ErrOutOfGas { + if len(result.Revert()) > 0 { + return 0, newRevertError(result) } - return true, nil, err // Bail out + return 0, result.Err } - return result.Failed(), result, nil + return 0, fmt.Errorf("gas required exceeds allowance (%d)", hi) } - state, header, err := b.StateAndHeaderByNumberOrHash(ctx, blockNrOrHash) - if state == nil || err != nil { - return 0, err - } - err = overrides.Apply(state) - if err != nil { - return 0, err - } - // Execute the binary search and hone in on an executable gas limit + // For almost any transaction, the gas consumed by the unconstrained execution above + // lower-bounds the gas limit required for it to succeed. One exception is those txs that + // explicitly check gas remaining in order to successfully execute within a given limit, but we + // probably don't want to return a lowest possible gas limit for these cases anyway. + lo = result.UsedGas - 1 + + // Binary search for the smallest gas limit that allows the tx to execute successfully. for lo+1 < hi { - s := state.Copy() mid := (hi + lo) / 2 - failed, _, err := executable(mid, s, header) - - // If the error is not nil(consensus error), it means the provided message - // call or transaction will never be accepted no matter how much gas it is - // assigned. Return the error directly, don't struggle any more. + if mid > lo*2 { + // Most txs don't need much higher gas limit than their gas used, and most txs don't + // require near the full block limit of gas, so the selection of where to bisect the + // range here is skewed to favor the low side. + mid = lo * 2 + } + failed, _, err = executeEstimate(ctx, b, args, state.Copy(), header, gasCap, mid) if err != nil { + // This should not happen under normal conditions since if we make it this far the + // transaction had run without error at least once before. + log.Error("execution error in estimate gas", "err", err) return 0, err } if failed { @@ -1247,28 +1307,14 @@ } else { hi = mid } } - // Reject the transaction as invalid if it still fails at the highest allowance - if hi == cap { - failed, result, err := executable(hi, state, header) - if err != nil { - return 0, err - } - if failed { - if result != nil && result.Err != vm.ErrOutOfGas { - if len(result.Revert()) > 0 { - return 0, newRevertError(result) - } - return 0, result.Err - } - // Otherwise, the specified gas cap is too low - return 0, fmt.Errorf("gas required exceeds allowance (%d)", cap) - } - } return hexutil.Uint64(hi), nil }   -// EstimateGas returns an estimate of the amount of gas needed to execute the -// given transaction against the current pending block. +// EstimateGas returns the lowest possible gas limit that allows the transaction to run +// successfully at block `blockNrOrHash`, or the latest block if `blockNrOrHash` is unspecified. It +// returns error if the transaction would revert or if there are unexpected failures. The returned +// value is capped by both `args.Gas` (if non-nil & non-zero) and the backend's RPCGasCap +// configuration (if non-zero). func (s *BlockChainAPI) EstimateGas(ctx context.Context, args TransactionArgs, blockNrOrHash *rpc.BlockNumberOrHash, overrides *StateOverride) (hexutil.Uint64, error) { bNrOrHash := rpc.BlockNumberOrHashWithNumber(rpc.LatestBlockNumber) if blockNrOrHash != nil { @@ -1297,15 +1343,21 @@ "timestamp": hexutil.Uint64(head.Time), "transactionsRoot": head.TxHash, "receiptsRoot": head.ReceiptHash, } - if head.BaseFee != nil { result["baseFeePerGas"] = (*hexutil.Big)(head.BaseFee) } - if head.WithdrawalsHash != nil { result["withdrawalsRoot"] = head.WithdrawalsHash } - + if head.BlobGasUsed != nil { + result["blobGasUsed"] = hexutil.Uint64(*head.BlobGasUsed) + } + if head.ExcessBlobGas != nil { + result["excessBlobGas"] = hexutil.Uint64(*head.ExcessBlobGas) + } + if head.ParentBeaconRoot != nil { + result["parentBeaconBlockRoot"] = head.ParentBeaconRoot + } return result }   @@ -1364,26 +1416,28 @@ }   // RPCTransaction represents a transaction that will serialize to the RPC representation of a transaction type RPCTransaction struct { - BlockHash *common.Hash `json:"blockHash"` - BlockNumber *hexutil.Big `json:"blockNumber"` - From common.Address `json:"from"` - Gas hexutil.Uint64 `json:"gas"` - GasPrice *hexutil.Big `json:"gasPrice"` - GasFeeCap *hexutil.Big `json:"maxFeePerGas,omitempty"` - GasTipCap *hexutil.Big `json:"maxPriorityFeePerGas,omitempty"` - Hash common.Hash `json:"hash"` - Input hexutil.Bytes `json:"input"` - Nonce hexutil.Uint64 `json:"nonce"` - To *common.Address `json:"to"` - TransactionIndex *hexutil.Uint64 `json:"transactionIndex"` - Value *hexutil.Big `json:"value"` - Type hexutil.Uint64 `json:"type"` - Accesses *types.AccessList `json:"accessList,omitempty"` - ChainID *hexutil.Big `json:"chainId,omitempty"` - V *hexutil.Big `json:"v"` - R *hexutil.Big `json:"r"` - S *hexutil.Big `json:"s"` - YParity *hexutil.Uint64 `json:"yParity,omitempty"` + BlockHash *common.Hash `json:"blockHash"` + BlockNumber *hexutil.Big `json:"blockNumber"` + From common.Address `json:"from"` + Gas hexutil.Uint64 `json:"gas"` + GasPrice *hexutil.Big `json:"gasPrice"` + GasFeeCap *hexutil.Big `json:"maxFeePerGas,omitempty"` + GasTipCap *hexutil.Big `json:"maxPriorityFeePerGas,omitempty"` + MaxFeePerBlobGas *hexutil.Big `json:"maxFeePerBlobGas,omitempty"` + Hash common.Hash `json:"hash"` + Input hexutil.Bytes `json:"input"` + Nonce hexutil.Uint64 `json:"nonce"` + To *common.Address `json:"to"` + TransactionIndex *hexutil.Uint64 `json:"transactionIndex"` + Value *hexutil.Big `json:"value"` + Type hexutil.Uint64 `json:"type"` + Accesses *types.AccessList `json:"accessList,omitempty"` + ChainID *hexutil.Big `json:"chainId,omitempty"` + BlobVersionedHashes []common.Hash `json:"blobVersionedHashes,omitempty"` + V *hexutil.Big `json:"v"` + R *hexutil.Big `json:"r"` + S *hexutil.Big `json:"s"` + YParity *hexutil.Uint64 `json:"yParity,omitempty"` }   // newRPCTransaction returns a transaction that will serialize to the RPC @@ -1437,15 +1491,43 @@ result.GasTipCap = (*hexutil.Big)(tx.GasTipCap()) // if the transaction has been mined, compute the effective gas price if baseFee != nil && blockHash != (common.Hash{}) { // price = min(gasTipCap + baseFee, gasFeeCap) - price := math.BigMin(new(big.Int).Add(tx.GasTipCap(), baseFee), tx.GasFeeCap()) - result.GasPrice = (*hexutil.Big)(price) + result.GasPrice = (*hexutil.Big)(effectiveGasPrice(tx, baseFee)) } else { result.GasPrice = (*hexutil.Big)(tx.GasFeeCap()) } + + case types.BlobTxType: + al := tx.AccessList() + yparity := hexutil.Uint64(v.Sign()) + result.Accesses = &al + result.ChainID = (*hexutil.Big)(tx.ChainId()) + result.YParity = &yparity + result.GasFeeCap = (*hexutil.Big)(tx.GasFeeCap()) + result.GasTipCap = (*hexutil.Big)(tx.GasTipCap()) + // if the transaction has been mined, compute the effective gas price + if baseFee != nil && blockHash != (common.Hash{}) { + result.GasPrice = (*hexutil.Big)(effectiveGasPrice(tx, baseFee)) + } else { + result.GasPrice = (*hexutil.Big)(tx.GasFeeCap()) + } + result.MaxFeePerBlobGas = (*hexutil.Big)(tx.BlobGasFeeCap()) + result.BlobVersionedHashes = tx.BlobHashes() } return result }   +// effectiveGasPrice computes the transaction gas fee, based on the given basefee value. +// +// price = min(gasTipCap + baseFee, gasFeeCap) +func effectiveGasPrice(tx *types.Transaction, baseFee *big.Int) *big.Int { + fee := tx.GasTipCap() + fee = fee.Add(fee, baseFee) + if tx.GasFeeCapIntCmp(fee) < 0 { + return tx.GasFeeCap() + } + return fee +} + // NewRPCPendingTransaction returns a pending transaction that will serialize to the RPC representation func NewRPCPendingTransaction(tx *types.Transaction, current *types.Header, config *params.ChainConfig) *RPCTransaction { var ( @@ -1717,13 +1799,18 @@ receipt := receipts[index]   // Derive the sender. signer := types.MakeSigner(s.b.ChainConfig(), header.Number, header.Time) + return marshalReceipt(receipt, blockHash, blockNumber, signer, tx, int(index)), nil +} + +// marshalReceipt marshals a transaction receipt into a JSON object. +func marshalReceipt(receipt *types.Receipt, blockHash common.Hash, blockNumber uint64, signer types.Signer, tx *types.Transaction, txIndex int) map[string]interface{} { from, _ := types.Sender(signer, tx)   fields := map[string]interface{}{ "blockHash": blockHash, "blockNumber": hexutil.Uint64(blockNumber), - "transactionHash": hash, - "transactionIndex": hexutil.Uint64(index), + "transactionHash": tx.Hash(), + "transactionIndex": hexutil.Uint64(txIndex), "from": from, "to": tx.To(), "gasUsed": hexutil.Uint64(receipt.GasUsed), @@ -1745,11 +1832,16 @@ if receipt.Logs == nil { fields["logs"] = []*types.Log{} }   + if tx.Type() == types.BlobTxType { + fields["blobGasUsed"] = hexutil.Uint64(receipt.BlobGasUsed) + fields["blobGasPrice"] = (*hexutil.Big)(receipt.BlobGasPrice) + } + // If the ContractAddress is 20 0x0 bytes, assume it is not a contract creation if receipt.ContractAddress != (common.Address{}) { fields["contractAddress"] = receipt.ContractAddress } - return fields, nil + return fields }   // sign is a helper function that signs a transaction with the private key of the given address. @@ -2097,20 +2189,23 @@ }   // ChaindbProperty returns leveldb properties of the key-value database. func (api *DebugAPI) ChaindbProperty(property string) (string, error) { - if property == "" { - property = "leveldb.stats" - } else if !strings.HasPrefix(property, "leveldb.") { - property = "leveldb." + property - } return api.b.ChainDb().Stat(property) }   // ChaindbCompact flattens the entire key-value database into a single level, // removing all unused slots and merging all keys. func (api *DebugAPI) ChaindbCompact() error { - for b := byte(0); b < 255; b++ { - log.Info("Compacting chain database", "range", fmt.Sprintf("0x%0.2X-0x%0.2X", b, b+1)) - if err := api.b.ChainDb().Compact([]byte{b}, []byte{b + 1}); err != nil { + cstart := time.Now() + for b := 0; b <= 255; b++ { + var ( + start = []byte{byte(b)} + end = []byte{byte(b + 1)} + ) + if b == 255 { + end = nil + } + log.Info("Compacting database", "range", fmt.Sprintf("%#X-%#X", start, end), "elapsed", common.PrettyDuration(time.Since(cstart))) + if err := api.b.ChainDb().Compact(start, end); err != nil { log.Error("Database compaction failed", "err", err) return err } @@ -2163,12 +2258,3 @@ return fmt.Errorf("tx fee (%.2f ether) exceeds the configured cap (%.2f ether)", feeFloat, cap) } return nil } - -// toHexSlice creates a slice of hex-strings based on []byte. -func toHexSlice(b [][]byte) []string { - r := make([]string, len(b)) - for i := range b { - r[i] = hexutil.Encode(b[i]) - } - return r -}
diff --git ethereum/go-ethereum/internal/ethapi/api_test.go taikoxyz/taiko-geth/internal/ethapi/api_test.go index b0877dc37849fab709a8d3b1d07ea0864592a37e..59882cd6bb5438040e8aa0fed227001cd93cb306 100644 --- ethereum/go-ethereum/internal/ethapi/api_test.go +++ taikoxyz/taiko-geth/internal/ethapi/api_test.go @@ -23,6 +23,8 @@ "encoding/json" "errors" "fmt" "math/big" + "os" + "path/filepath" "reflect" "testing" "time" @@ -32,6 +34,7 @@ "github.com/ethereum/go-ethereum/accounts" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common/hexutil" "github.com/ethereum/go-ethereum/consensus" + "github.com/ethereum/go-ethereum/consensus/beacon" "github.com/ethereum/go-ethereum/consensus/ethash" "github.com/ethereum/go-ethereum/core" "github.com/ethereum/go-ethereum/core/bloombits" @@ -45,19 +48,18 @@ "github.com/ethereum/go-ethereum/event" "github.com/ethereum/go-ethereum/internal/blocktest" "github.com/ethereum/go-ethereum/params" "github.com/ethereum/go-ethereum/rpc" - "github.com/stretchr/testify/assert" + "github.com/holiman/uint256" "github.com/stretchr/testify/require" "golang.org/x/exp/slices" )   -func TestTransaction_RoundTripRpcJSON(t *testing.T) { +func testTransactionMarshal(t *testing.T, tests []txData, config *params.ChainConfig) { + t.Parallel() var ( - config = params.AllEthashProtocolChanges signer = types.LatestSigner(config) key, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291") - tests = allTransactionTypes(common.Address{0xde, 0xad}, config) ) - t.Parallel() + for i, tt := range tests { var tx2 types.Transaction tx, err := types.SignNewTx(key, signer, tt.Tx) @@ -86,6 +88,23 @@ want, have := tt.Want, string(data) require.JSONEqf(t, want, have, "test %d: rpc json not match, want %s have %s", i, want, have) } } +} + +func TestTransaction_RoundTripRpcJSON(t *testing.T) { + var ( + config = params.AllEthashProtocolChanges + tests = allTransactionTypes(common.Address{0xde, 0xad}, config) + ) + testTransactionMarshal(t, tests, config) +} + +func TestTransactionBlobTx(t *testing.T) { + config := *params.TestChainConfig + config.ShanghaiTime = new(uint64) + config.CancunTime = new(uint64) + tests := allBlobTxs(common.Address{0xde, 0xad}, &config) + + testTransactionMarshal(t, tests, &config) }   type txData struct { @@ -338,15 +357,60 @@ }, } }   +func allBlobTxs(addr common.Address, config *params.ChainConfig) []txData { + return []txData{ + { + Tx: &types.BlobTx{ + Nonce: 6, + GasTipCap: uint256.NewInt(1), + GasFeeCap: uint256.NewInt(5), + Gas: 6, + To: addr, + BlobFeeCap: uint256.NewInt(1), + BlobHashes: []common.Hash{{1}}, + Value: new(uint256.Int), + V: uint256.NewInt(32), + R: uint256.NewInt(10), + S: uint256.NewInt(11), + }, + Want: `{ + "blockHash": null, + "blockNumber": null, + "from": "0x71562b71999873db5b286df957af199ec94617f7", + "gas": "0x6", + "gasPrice": "0x5", + "maxFeePerGas": "0x5", + "maxPriorityFeePerGas": "0x1", + "maxFeePerBlobGas": "0x1", + "hash": "0x1f2b59a20e61efc615ad0cbe936379d6bbea6f938aafaf35eb1da05d8e7f46a3", + "input": "0x", + "nonce": "0x6", + "to": "0xdead000000000000000000000000000000000000", + "transactionIndex": null, + "value": "0x0", + "type": "0x3", + "accessList": [], + "chainId": "0x1", + "blobVersionedHashes": [ + "0x0100000000000000000000000000000000000000000000000000000000000000" + ], + "v": "0x0", + "r": "0x618be8908e0e5320f8f3b48042a079fe5a335ebd4ed1422a7d2207cd45d872bc", + "s": "0x27b2bc6c80e849a8e8b764d4549d8c2efac3441e73cf37054eb0a9b9f8e89b27", + "yParity": "0x0" + }`, + }, + } +} + type testBackend struct { db ethdb.Database chain *core.BlockChain pending *types.Block }   -func newTestBackend(t *testing.T, n int, gspec *core.Genesis, generator func(i int, b *core.BlockGen)) *testBackend { +func newTestBackend(t *testing.T, n int, gspec *core.Genesis, engine consensus.Engine, generator func(i int, b *core.BlockGen)) *testBackend { var ( - engine = ethash.NewFaker() cacheConfig = &core.CacheConfig{ TrieCleanLimit: 256, TrieDirtyLimit: 256, @@ -550,7 +614,7 @@ genBlocks = 10 signer = types.HomesteadSigner{} randomAccounts = newAccounts(2) ) - api := NewBlockChainAPI(newTestBackend(t, genBlocks, genesis, func(i int, b *core.BlockGen) { + api := NewBlockChainAPI(newTestBackend(t, genBlocks, genesis, ethash.NewFaker(), func(i int, b *core.BlockGen) { // Transfer from account[0] to account[1] // value: 1000 wei // fee: 0 wei @@ -653,7 +717,7 @@ } genBlocks = 10 signer = types.HomesteadSigner{} ) - api := NewBlockChainAPI(newTestBackend(t, genBlocks, genesis, func(i int, b *core.BlockGen) { + api := NewBlockChainAPI(newTestBackend(t, genBlocks, genesis, ethash.NewFaker(), func(i int, b *core.BlockGen) { // Transfer from account[0] to account[1] // value: 1000 wei // fee: 0 wei @@ -782,7 +846,7 @@ want: "0x000000000000000000000000000000000000000000000000000000000000000b", }, } for i, tc := range testSuite { - result, err := api.Call(context.Background(), tc.call, rpc.BlockNumberOrHash{BlockNumber: &tc.blockNumber}, &tc.overrides, &tc.blockOverrides) + result, err := api.Call(context.Background(), tc.call, &rpc.BlockNumberOrHash{BlockNumber: &tc.blockNumber}, &tc.overrides, &tc.blockOverrides) if tc.expectErr != nil { if err == nil { t.Errorf("test %d: want error %v, have nothing", i, tc.expectErr) @@ -1036,7 +1100,7 @@ if err != nil { t.Errorf("test %d: json marshal error: %v", i, err) continue } - assert.JSONEqf(t, tc.want, string(out), "test %d", i) + require.JSONEqf(t, tc.want, string(out), "test %d", i) } }   @@ -1074,7 +1138,7 @@ Amount: 10, } pending = types.NewBlockWithWithdrawals(&types.Header{Number: big.NewInt(11), Time: 42}, []*types.Transaction{tx}, nil, nil, []*types.Withdrawal{withdrawal}, blocktest.NewHasher()) ) - backend := newTestBackend(t, genBlocks, genesis, func(i int, b *core.BlockGen) { + backend := newTestBackend(t, genBlocks, genesis, ethash.NewFaker(), func(i int, b *core.BlockGen) { // Transfer from account[0] to account[1] // value: 1000 wei // fee: 0 wei @@ -1099,628 +1163,156 @@ blockNumber rpc.BlockNumber blockHash *common.Hash fullTx bool reqHeader bool - want string + file string expectErr error }{ // 0. latest header { blockNumber: rpc.LatestBlockNumber, reqHeader: true, - want: `{ - "baseFeePerGas": "0xfdc7303", - "difficulty": "0x20000", - "extraData": "0x", - "gasLimit": "0x47e7c4", - "gasUsed": "0x5208", - "hash": "0x97f540a3577c0f645c5dada5da86f38350e8f847e71f21124f917835003e2607", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "miner": "0x0000000000000000000000000000000000000000", - "mixHash": "0x0000000000000000000000000000000000000000000000000000000000000000", - "nonce": "0x0000000000000000", - "number": "0xa", - "parentHash": "0xda97ed946e0d502fb898b0ac881bd44da3c7fee5eaf184431e1ec3d361dad17e", - "receiptsRoot": "0x056b23fbba480696b65fe5a59b8f2148a1299103c4f57df839233af2cf4ca2d2", - "sha3Uncles": "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347", - "stateRoot": "0xbb62872e4023fa8a8b17b9cc37031f4817d9595779748d01cba408b495707a91", - "timestamp": "0x64", - "totalDifficulty": "0x1", - "transactionsRoot": "0xb0893d21a4a44dc26a962a6e91abae66df87fb61ac9c60e936aee89c76331445" - }`, + file: "tag-latest", }, // 1. genesis header { blockNumber: rpc.BlockNumber(0), reqHeader: true, - want: `{ - "baseFeePerGas": "0x3b9aca00", - "difficulty": "0x20000", - "extraData": "0x", - "gasLimit": "0x47e7c4", - "gasUsed": "0x0", - "hash": "0xbdc7d83b8f876938810462fe8d053263a482e44201e3883d4ae204ff4de7eff5", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "miner": "0x0000000000000000000000000000000000000000", - "mixHash": "0x0000000000000000000000000000000000000000000000000000000000000000", - "nonce": "0x0000000000000000", - "number": "0x0", - "parentHash": "0x0000000000000000000000000000000000000000000000000000000000000000", - "receiptsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", - "sha3Uncles": "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347", - "stateRoot": "0xfe168c5e9584a85927212e5bea5304bb7d0d8a893453b4b2c52176a72f585ae2", - "timestamp": "0x0", - "totalDifficulty": "0x1", - "transactionsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421" - }`, + file: "number-0", }, // 2. #1 header { blockNumber: rpc.BlockNumber(1), reqHeader: true, - want: `{ - "baseFeePerGas": "0x342770c0", - "difficulty": "0x20000", - "extraData": "0x", - "gasLimit": "0x47e7c4", - "gasUsed": "0x5208", - "hash": "0x0da274b315de8e4d5bf8717218ec43540464ef36378cb896469bb731e1d3f3cb", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "miner": "0x0000000000000000000000000000000000000000", - "mixHash": "0x0000000000000000000000000000000000000000000000000000000000000000", - "nonce": "0x0000000000000000", - "number": "0x1", - "parentHash": "0xbdc7d83b8f876938810462fe8d053263a482e44201e3883d4ae204ff4de7eff5", - "receiptsRoot": "0x056b23fbba480696b65fe5a59b8f2148a1299103c4f57df839233af2cf4ca2d2", - "sha3Uncles": "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347", - "stateRoot": "0x92c5c55a698963f5b06e3aee415630f5c48b0760e537af94917ce9c4f42a2e22", - "timestamp": "0xa", - "totalDifficulty": "0x1", - "transactionsRoot": "0xca0ebcce920d2cdfbf9e1dbe90ed3441a1a576f344bd80e60508da814916f4e7" - }`, + file: "number-1", }, // 3. latest-1 header { blockNumber: rpc.BlockNumber(9), reqHeader: true, - want: `{ - "baseFeePerGas": "0x121a9cca", - "difficulty": "0x20000", - "extraData": "0x", - "gasLimit": "0x47e7c4", - "gasUsed": "0x5208", - "hash": "0xda97ed946e0d502fb898b0ac881bd44da3c7fee5eaf184431e1ec3d361dad17e", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "miner": "0x0000000000000000000000000000000000000000", - "mixHash": "0x0000000000000000000000000000000000000000000000000000000000000000", - "nonce": "0x0000000000000000", - "number": "0x9", - "parentHash": "0x5abd19c39d9f1c6e52998e135ea14e1fbc5db3fa2a108f4538e238ca5c2e68d7", - "receiptsRoot": "0x056b23fbba480696b65fe5a59b8f2148a1299103c4f57df839233af2cf4ca2d2", - "sha3Uncles": "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347", - "stateRoot": "0xbd4aa2c2873df709151075250a8c01c9a14d2b0e2f715dbdd16e0ef8030c2cf0", - "timestamp": "0x5a", - "totalDifficulty": "0x1", - "transactionsRoot": "0x0767ed8359337dc6a8fdc77fe52db611bed1be87aac73c4556b1bf1dd3d190a5" - }`, + file: "number-latest-1", }, // 4. latest+1 header { blockNumber: rpc.BlockNumber(11), reqHeader: true, - want: "null", + file: "number-latest+1", }, // 5. pending header { blockNumber: rpc.PendingBlockNumber, reqHeader: true, - want: `{ - "difficulty": "0x0", - "extraData": "0x", - "gasLimit": "0x0", - "gasUsed": "0x0", - "hash": null, - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "miner": null, - "mixHash": "0x0000000000000000000000000000000000000000000000000000000000000000", - "nonce": null, - "number": "0xb", - "parentHash": "0x0000000000000000000000000000000000000000000000000000000000000000", - "receiptsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", - "sha3Uncles": "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347", - "stateRoot": "0x0000000000000000000000000000000000000000000000000000000000000000", - "timestamp": "0x2a", - "totalDifficulty": null, - "transactionsRoot": "0x98d9f6dd0aa479c0fb448f2627e9f1964aca699fccab8f6e95861547a4699e37", - "withdrawalsRoot": "0x73d756269cdfc22e7e17a3548e36f42f750ca06d7e3cd98d1b6d0eb5add9dc84" - }`, + file: "tag-pending", }, // 6. latest block { blockNumber: rpc.LatestBlockNumber, - want: `{ - "baseFeePerGas": "0xfdc7303", - "difficulty": "0x20000", - "extraData": "0x", - "gasLimit": "0x47e7c4", - "gasUsed": "0x5208", - "hash": "0x97f540a3577c0f645c5dada5da86f38350e8f847e71f21124f917835003e2607", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "miner": "0x0000000000000000000000000000000000000000", - "mixHash": "0x0000000000000000000000000000000000000000000000000000000000000000", - "nonce": "0x0000000000000000", - "number": "0xa", - "parentHash": "0xda97ed946e0d502fb898b0ac881bd44da3c7fee5eaf184431e1ec3d361dad17e", - "receiptsRoot": "0x056b23fbba480696b65fe5a59b8f2148a1299103c4f57df839233af2cf4ca2d2", - "sha3Uncles": "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347", - "size": "0x26a", - "stateRoot": "0xbb62872e4023fa8a8b17b9cc37031f4817d9595779748d01cba408b495707a91", - "timestamp": "0x64", - "totalDifficulty": "0x1", - "transactions": [ - "0x3ee4094ca1e0b07a66dd616a057e081e53144ca7e9685a126fd4dda9ca042644" - ], - "transactionsRoot": "0xb0893d21a4a44dc26a962a6e91abae66df87fb61ac9c60e936aee89c76331445", - "uncles": [] - }`, + file: "tag-latest", }, // 7. genesis block { blockNumber: rpc.BlockNumber(0), - want: `{ - "baseFeePerGas": "0x3b9aca00", - "difficulty": "0x20000", - "extraData": "0x", - "gasLimit": "0x47e7c4", - "gasUsed": "0x0", - "hash": "0xbdc7d83b8f876938810462fe8d053263a482e44201e3883d4ae204ff4de7eff5", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "miner": "0x0000000000000000000000000000000000000000", - "mixHash": "0x0000000000000000000000000000000000000000000000000000000000000000", - "nonce": "0x0000000000000000", - "number": "0x0", - "parentHash": "0x0000000000000000000000000000000000000000000000000000000000000000", - "receiptsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", - "sha3Uncles": "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347", - "size": "0x200", - "stateRoot": "0xfe168c5e9584a85927212e5bea5304bb7d0d8a893453b4b2c52176a72f585ae2", - "timestamp": "0x0", - "totalDifficulty": "0x1", - "transactions": [], - "transactionsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", - "uncles": [] - }`, + file: "number-0", }, // 8. #1 block { blockNumber: rpc.BlockNumber(1), - want: `{ - "baseFeePerGas": "0x342770c0", - "difficulty": "0x20000", - "extraData": "0x", - "gasLimit": "0x47e7c4", - "gasUsed": "0x5208", - "hash": "0x0da274b315de8e4d5bf8717218ec43540464ef36378cb896469bb731e1d3f3cb", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "miner": "0x0000000000000000000000000000000000000000", - "mixHash": "0x0000000000000000000000000000000000000000000000000000000000000000", - "nonce": "0x0000000000000000", - "number": "0x1", - "parentHash": "0xbdc7d83b8f876938810462fe8d053263a482e44201e3883d4ae204ff4de7eff5", - "receiptsRoot": "0x056b23fbba480696b65fe5a59b8f2148a1299103c4f57df839233af2cf4ca2d2", - "sha3Uncles": "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347", - "size": "0x26a", - "stateRoot": "0x92c5c55a698963f5b06e3aee415630f5c48b0760e537af94917ce9c4f42a2e22", - "timestamp": "0xa", - "totalDifficulty": "0x1", - "transactions": [ - "0x644a31c354391520d00e95b9affbbb010fc79ac268144ab8e28207f4cf51097e" - ], - "transactionsRoot": "0xca0ebcce920d2cdfbf9e1dbe90ed3441a1a576f344bd80e60508da814916f4e7", - "uncles": [] - }`, + file: "number-1", }, // 9. latest-1 block { blockNumber: rpc.BlockNumber(9), fullTx: true, - want: `{ - "baseFeePerGas": "0x121a9cca", - "difficulty": "0x20000", - "extraData": "0x", - "gasLimit": "0x47e7c4", - "gasUsed": "0x5208", - "hash": "0xda97ed946e0d502fb898b0ac881bd44da3c7fee5eaf184431e1ec3d361dad17e", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "miner": "0x0000000000000000000000000000000000000000", - "mixHash": "0x0000000000000000000000000000000000000000000000000000000000000000", - "nonce": "0x0000000000000000", - "number": "0x9", - "parentHash": "0x5abd19c39d9f1c6e52998e135ea14e1fbc5db3fa2a108f4538e238ca5c2e68d7", - "receiptsRoot": "0x056b23fbba480696b65fe5a59b8f2148a1299103c4f57df839233af2cf4ca2d2", - "sha3Uncles": "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347", - "size": "0x26a", - "stateRoot": "0xbd4aa2c2873df709151075250a8c01c9a14d2b0e2f715dbdd16e0ef8030c2cf0", - "timestamp": "0x5a", - "totalDifficulty": "0x1", - "transactions": [ - { - "blockHash": "0xda97ed946e0d502fb898b0ac881bd44da3c7fee5eaf184431e1ec3d361dad17e", - "blockNumber": "0x9", - "from": "0x703c4b2bd70c169f5717101caee543299fc946c7", - "gas": "0x5208", - "gasPrice": "0x121a9cca", - "hash": "0xecd155a61a5734b3efab75924e3ae34026c7c4133d8c2a46122bd03d7d199725", - "input": "0x", - "nonce": "0x8", - "to": "0x0d3ab14bbad3d99f4203bd7a11acb94882050e7e", - "transactionIndex": "0x0", - "value": "0x3e8", - "type": "0x0", - "v": "0x1b", - "r": "0xc6028b8e983d62fa8542f8a7633fb23cc941be2c897134352d95a7d9b19feafd", - "s": "0xeb6adcaaae3bed489c6cce4435f9db05d23a52820c78bd350e31eec65ed809d" - } - ], - "transactionsRoot": "0x0767ed8359337dc6a8fdc77fe52db611bed1be87aac73c4556b1bf1dd3d190a5", - "uncles": [] - }`, + file: "number-latest-1", }, // 10. latest+1 block { blockNumber: rpc.BlockNumber(11), fullTx: true, - want: "null", + file: "number-latest+1", }, // 11. pending block { blockNumber: rpc.PendingBlockNumber, - want: `{ - "difficulty": "0x0", - "extraData": "0x", - "gasLimit": "0x0", - "gasUsed": "0x0", - "hash": null, - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "miner": null, - "mixHash": "0x0000000000000000000000000000000000000000000000000000000000000000", - "nonce": null, - "number": "0xb", - "parentHash": "0x0000000000000000000000000000000000000000000000000000000000000000", - "receiptsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", - "sha3Uncles": "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347", - "size": "0x256", - "stateRoot": "0x0000000000000000000000000000000000000000000000000000000000000000", - "timestamp": "0x2a", - "totalDifficulty": null, - "transactions": [ - "0x4afee081df5dff7a025964032871f7d4ba4d21baf5f6376a2f4a9f79fc506298" - ], - "transactionsRoot": "0x98d9f6dd0aa479c0fb448f2627e9f1964aca699fccab8f6e95861547a4699e37", - "withdrawals": [ - { - "index": "0x0", - "validatorIndex": "0x1", - "address": "0x1234000000000000000000000000000000000000", - "amount": "0xa" - } - ], - "withdrawalsRoot": "0x73d756269cdfc22e7e17a3548e36f42f750ca06d7e3cd98d1b6d0eb5add9dc84", - "uncles": [] - }`, + file: "tag-pending", }, // 12. pending block + fullTx { blockNumber: rpc.PendingBlockNumber, fullTx: true, - want: `{ - "difficulty": "0x0", - "extraData": "0x", - "gasLimit": "0x0", - "gasUsed": "0x0", - "hash": null, - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "miner": null, - "mixHash": "0x0000000000000000000000000000000000000000000000000000000000000000", - "nonce": null, - "number": "0xb", - "parentHash": "0x0000000000000000000000000000000000000000000000000000000000000000", - "receiptsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", - "sha3Uncles": "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347", - "size": "0x256", - "stateRoot": "0x0000000000000000000000000000000000000000000000000000000000000000", - "timestamp": "0x2a", - "totalDifficulty": null, - "transactions": [ - { - "blockHash": "0x6cebd9f966ea686f44b981685e3f0eacea28591a7a86d7fbbe521a86e9f81165", - "blockNumber": "0xb", - "from": "0x0000000000000000000000000000000000000000", - "gas": "0x457", - "gasPrice": "0x2b67", - "hash": "0x4afee081df5dff7a025964032871f7d4ba4d21baf5f6376a2f4a9f79fc506298", - "input": "0x111111", - "nonce": "0xb", - "to": "0x0d3ab14bbad3d99f4203bd7a11acb94882050e7e", - "transactionIndex": "0x0", - "value": "0x6f", - "type": "0x0", - "chainId": "0x7fffffffffffffee", - "v": "0x0", - "r": "0x0", - "s": "0x0" - } - ], - "transactionsRoot": "0x98d9f6dd0aa479c0fb448f2627e9f1964aca699fccab8f6e95861547a4699e37", - "uncles": [], - "withdrawals": [ - { - "index": "0x0", - "validatorIndex": "0x1", - "address": "0x1234000000000000000000000000000000000000", - "amount": "0xa" - } - ], - "withdrawalsRoot": "0x73d756269cdfc22e7e17a3548e36f42f750ca06d7e3cd98d1b6d0eb5add9dc84" - }`, + file: "tag-pending-fullTx", }, // 13. latest header by hash { blockHash: &blockHashes[len(blockHashes)-1], reqHeader: true, - want: `{ - "baseFeePerGas": "0xfdc7303", - "difficulty": "0x20000", - "extraData": "0x", - "gasLimit": "0x47e7c4", - "gasUsed": "0x5208", - "hash": "0x97f540a3577c0f645c5dada5da86f38350e8f847e71f21124f917835003e2607", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "miner": "0x0000000000000000000000000000000000000000", - "mixHash": "0x0000000000000000000000000000000000000000000000000000000000000000", - "nonce": "0x0000000000000000", - "number": "0xa", - "parentHash": "0xda97ed946e0d502fb898b0ac881bd44da3c7fee5eaf184431e1ec3d361dad17e", - "receiptsRoot": "0x056b23fbba480696b65fe5a59b8f2148a1299103c4f57df839233af2cf4ca2d2", - "sha3Uncles": "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347", - "stateRoot": "0xbb62872e4023fa8a8b17b9cc37031f4817d9595779748d01cba408b495707a91", - "timestamp": "0x64", - "totalDifficulty": "0x1", - "transactionsRoot": "0xb0893d21a4a44dc26a962a6e91abae66df87fb61ac9c60e936aee89c76331445" - }`, + file: "hash-latest", }, // 14. genesis header by hash { blockHash: &blockHashes[0], reqHeader: true, - want: `{ - "baseFeePerGas": "0x3b9aca00", - "difficulty": "0x20000", - "extraData": "0x", - "gasLimit": "0x47e7c4", - "gasUsed": "0x0", - "hash": "0xbdc7d83b8f876938810462fe8d053263a482e44201e3883d4ae204ff4de7eff5", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "miner": "0x0000000000000000000000000000000000000000", - "mixHash": "0x0000000000000000000000000000000000000000000000000000000000000000", - "nonce": "0x0000000000000000", - "number": "0x0", - "parentHash": "0x0000000000000000000000000000000000000000000000000000000000000000", - "receiptsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", - "sha3Uncles": "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347", - "stateRoot": "0xfe168c5e9584a85927212e5bea5304bb7d0d8a893453b4b2c52176a72f585ae2", - "timestamp": "0x0", - "totalDifficulty": "0x1", - "transactionsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421" - }`, + file: "hash-0", }, // 15. #1 header { blockHash: &blockHashes[1], reqHeader: true, - want: `{ - "baseFeePerGas": "0x342770c0", - "difficulty": "0x20000", - "extraData": "0x", - "gasLimit": "0x47e7c4", - "gasUsed": "0x5208", - "hash": "0x0da274b315de8e4d5bf8717218ec43540464ef36378cb896469bb731e1d3f3cb", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "miner": "0x0000000000000000000000000000000000000000", - "mixHash": "0x0000000000000000000000000000000000000000000000000000000000000000", - "nonce": "0x0000000000000000", - "number": "0x1", - "parentHash": "0xbdc7d83b8f876938810462fe8d053263a482e44201e3883d4ae204ff4de7eff5", - "receiptsRoot": "0x056b23fbba480696b65fe5a59b8f2148a1299103c4f57df839233af2cf4ca2d2", - "sha3Uncles": "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347", - "stateRoot": "0x92c5c55a698963f5b06e3aee415630f5c48b0760e537af94917ce9c4f42a2e22", - "timestamp": "0xa", - "totalDifficulty": "0x1", - "transactionsRoot": "0xca0ebcce920d2cdfbf9e1dbe90ed3441a1a576f344bd80e60508da814916f4e7" - }`, + file: "hash-1", }, // 16. latest-1 header { blockHash: &blockHashes[len(blockHashes)-2], reqHeader: true, - want: `{ - "baseFeePerGas": "0x121a9cca", - "difficulty": "0x20000", - "extraData": "0x", - "gasLimit": "0x47e7c4", - "gasUsed": "0x5208", - "hash": "0xda97ed946e0d502fb898b0ac881bd44da3c7fee5eaf184431e1ec3d361dad17e", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "miner": "0x0000000000000000000000000000000000000000", - "mixHash": "0x0000000000000000000000000000000000000000000000000000000000000000", - "nonce": "0x0000000000000000", - "number": "0x9", - "parentHash": "0x5abd19c39d9f1c6e52998e135ea14e1fbc5db3fa2a108f4538e238ca5c2e68d7", - "receiptsRoot": "0x056b23fbba480696b65fe5a59b8f2148a1299103c4f57df839233af2cf4ca2d2", - "sha3Uncles": "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347", - "stateRoot": "0xbd4aa2c2873df709151075250a8c01c9a14d2b0e2f715dbdd16e0ef8030c2cf0", - "timestamp": "0x5a", - "totalDifficulty": "0x1", - "transactionsRoot": "0x0767ed8359337dc6a8fdc77fe52db611bed1be87aac73c4556b1bf1dd3d190a5" - }`, + file: "hash-latest-1", }, // 17. empty hash { blockHash: &common.Hash{}, reqHeader: true, - want: "null", + file: "hash-empty", }, // 18. pending hash { blockHash: &pendingHash, reqHeader: true, - want: `null`, + file: `hash-pending`, }, // 19. latest block { blockHash: &blockHashes[len(blockHashes)-1], - want: `{ - "baseFeePerGas": "0xfdc7303", - "difficulty": "0x20000", - "extraData": "0x", - "gasLimit": "0x47e7c4", - "gasUsed": "0x5208", - "hash": "0x97f540a3577c0f645c5dada5da86f38350e8f847e71f21124f917835003e2607", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "miner": "0x0000000000000000000000000000000000000000", - "mixHash": "0x0000000000000000000000000000000000000000000000000000000000000000", - "nonce": "0x0000000000000000", - "number": "0xa", - "parentHash": "0xda97ed946e0d502fb898b0ac881bd44da3c7fee5eaf184431e1ec3d361dad17e", - "receiptsRoot": "0x056b23fbba480696b65fe5a59b8f2148a1299103c4f57df839233af2cf4ca2d2", - "sha3Uncles": "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347", - "size": "0x26a", - "stateRoot": "0xbb62872e4023fa8a8b17b9cc37031f4817d9595779748d01cba408b495707a91", - "timestamp": "0x64", - "totalDifficulty": "0x1", - "transactions": [ - "0x3ee4094ca1e0b07a66dd616a057e081e53144ca7e9685a126fd4dda9ca042644" - ], - "transactionsRoot": "0xb0893d21a4a44dc26a962a6e91abae66df87fb61ac9c60e936aee89c76331445", - "uncles": [] - }`, + file: "hash-latest", }, // 20. genesis block { blockHash: &blockHashes[0], - want: `{ - "baseFeePerGas": "0x3b9aca00", - "difficulty": "0x20000", - "extraData": "0x", - "gasLimit": "0x47e7c4", - "gasUsed": "0x0", - "hash": "0xbdc7d83b8f876938810462fe8d053263a482e44201e3883d4ae204ff4de7eff5", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "miner": "0x0000000000000000000000000000000000000000", - "mixHash": "0x0000000000000000000000000000000000000000000000000000000000000000", - "nonce": "0x0000000000000000", - "number": "0x0", - "parentHash": "0x0000000000000000000000000000000000000000000000000000000000000000", - "receiptsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", - "sha3Uncles": "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347", - "size": "0x200", - "stateRoot": "0xfe168c5e9584a85927212e5bea5304bb7d0d8a893453b4b2c52176a72f585ae2", - "timestamp": "0x0", - "totalDifficulty": "0x1", - "transactions": [], - "transactionsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", - "uncles": [] - }`, + file: "hash-genesis", }, // 21. #1 block { blockHash: &blockHashes[1], - want: `{ - "baseFeePerGas": "0x342770c0", - "difficulty": "0x20000", - "extraData": "0x", - "gasLimit": "0x47e7c4", - "gasUsed": "0x5208", - "hash": "0x0da274b315de8e4d5bf8717218ec43540464ef36378cb896469bb731e1d3f3cb", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "miner": "0x0000000000000000000000000000000000000000", - "mixHash": "0x0000000000000000000000000000000000000000000000000000000000000000", - "nonce": "0x0000000000000000", - "number": "0x1", - "parentHash": "0xbdc7d83b8f876938810462fe8d053263a482e44201e3883d4ae204ff4de7eff5", - "receiptsRoot": "0x056b23fbba480696b65fe5a59b8f2148a1299103c4f57df839233af2cf4ca2d2", - "sha3Uncles": "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347", - "size": "0x26a", - "stateRoot": "0x92c5c55a698963f5b06e3aee415630f5c48b0760e537af94917ce9c4f42a2e22", - "timestamp": "0xa", - "totalDifficulty": "0x1", - "transactions": [ - "0x644a31c354391520d00e95b9affbbb010fc79ac268144ab8e28207f4cf51097e" - ], - "transactionsRoot": "0xca0ebcce920d2cdfbf9e1dbe90ed3441a1a576f344bd80e60508da814916f4e7", - "uncles": [] - }`, + file: "hash-1", }, // 22. latest-1 block { blockHash: &blockHashes[len(blockHashes)-2], fullTx: true, - want: `{ - "baseFeePerGas": "0x121a9cca", - "difficulty": "0x20000", - "extraData": "0x", - "gasLimit": "0x47e7c4", - "gasUsed": "0x5208", - "hash": "0xda97ed946e0d502fb898b0ac881bd44da3c7fee5eaf184431e1ec3d361dad17e", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "miner": "0x0000000000000000000000000000000000000000", - "mixHash": "0x0000000000000000000000000000000000000000000000000000000000000000", - "nonce": "0x0000000000000000", - "number": "0x9", - "parentHash": "0x5abd19c39d9f1c6e52998e135ea14e1fbc5db3fa2a108f4538e238ca5c2e68d7", - "receiptsRoot": "0x056b23fbba480696b65fe5a59b8f2148a1299103c4f57df839233af2cf4ca2d2", - "sha3Uncles": "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347", - "size": "0x26a", - "stateRoot": "0xbd4aa2c2873df709151075250a8c01c9a14d2b0e2f715dbdd16e0ef8030c2cf0", - "timestamp": "0x5a", - "totalDifficulty": "0x1", - "transactions": [ - { - "blockHash": "0xda97ed946e0d502fb898b0ac881bd44da3c7fee5eaf184431e1ec3d361dad17e", - "blockNumber": "0x9", - "from": "0x703c4b2bd70c169f5717101caee543299fc946c7", - "gas": "0x5208", - "gasPrice": "0x121a9cca", - "hash": "0xecd155a61a5734b3efab75924e3ae34026c7c4133d8c2a46122bd03d7d199725", - "input": "0x", - "nonce": "0x8", - "to": "0x0d3ab14bbad3d99f4203bd7a11acb94882050e7e", - "transactionIndex": "0x0", - "value": "0x3e8", - "type": "0x0", - "v": "0x1b", - "r": "0xc6028b8e983d62fa8542f8a7633fb23cc941be2c897134352d95a7d9b19feafd", - "s": "0xeb6adcaaae3bed489c6cce4435f9db05d23a52820c78bd350e31eec65ed809d" - } - ], - "transactionsRoot": "0x0767ed8359337dc6a8fdc77fe52db611bed1be87aac73c4556b1bf1dd3d190a5", - "uncles": [] - }`, + file: "hash-latest-1-fullTx", }, // 23. empty hash + body { blockHash: &common.Hash{}, fullTx: true, - want: "null", + file: "hash-empty-fullTx", }, // 24. pending block { blockHash: &pendingHash, - want: `null`, + file: `hash-pending`, }, // 25. pending block + fullTx { blockHash: &pendingHash, fullTx: true, - want: `null`, + file: "hash-pending-fullTx", }, }   @@ -1728,18 +1320,23 @@ for i, tt := range testSuite { var ( result map[string]interface{} err error + rpc string ) if tt.blockHash != nil { if tt.reqHeader { result = api.GetHeaderByHash(context.Background(), *tt.blockHash) + rpc = "eth_getHeaderByHash" } else { result, err = api.GetBlockByHash(context.Background(), *tt.blockHash, tt.fullTx) + rpc = "eth_getBlockByHash" } } else { if tt.reqHeader { result, err = api.GetHeaderByNumber(context.Background(), tt.blockNumber) + rpc = "eth_getHeaderByNumber" } else { result, err = api.GetBlockByNumber(context.Background(), tt.blockNumber, tt.fullTx) + rpc = "eth_getBlockByNumber" } } if tt.expectErr != nil { @@ -1756,20 +1353,15 @@ if err != nil { t.Errorf("test %d: want no error, have %v", i, err) continue } - data, err := json.Marshal(result) - if err != nil { - t.Errorf("test %d: json marshal error", i) - continue - } - want, have := tt.want, string(data) - require.JSONEqf(t, want, have, "test %d: json not match, want: %s, have: %s", i, want, have) + + testRPCResponseWithFile(t, i, result, rpc, tt.file) } }   -func TestRPCGetTransactionReceipt(t *testing.T) { - t.Parallel() - - // Initialize test accounts +func setupReceiptBackend(t *testing.T, genBlocks int) (*testBackend, []common.Hash) { + config := *params.TestChainConfig + config.ShanghaiTime = new(uint64) + config.CancunTime = new(uint64) var ( acc1Key, _ = crypto.HexToECDSA("8a1f9a8f95be41cd7ccb6168179afb4504aefe388d1e14474d32c45c72ce7b7a") acc2Key, _ = crypto.HexToECDSA("49a7b37aa6f6645917e7b807e9d1c00d4fa71f18343b0d4122a4d2df64dd6fee") @@ -1777,7 +1369,9 @@ acc1Addr = crypto.PubkeyToAddress(acc1Key.PublicKey) acc2Addr = crypto.PubkeyToAddress(acc2Key.PublicKey) contract = common.HexToAddress("0000000000000000000000000000000000031ec7") genesis = &core.Genesis{ - Config: params.TestChainConfig, + Config: &config, + ExcessBlobGas: new(uint64), + BlobGasUsed: new(uint64), Alloc: core.GenesisAlloc{ acc1Addr: {Balance: big.NewInt(params.Ether)}, acc2Addr: {Balance: big.NewInt(params.Ether)}, @@ -1794,11 +1388,14 @@ // } contract: {Balance: big.NewInt(params.Ether), Code: common.FromHex("0x608060405234801561001057600080fd5b506004361061002b5760003560e01c8063a9059cbb14610030575b600080fd5b61004a6004803603810190610045919061016a565b610060565b60405161005791906101c5565b60405180910390f35b60008273ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef846040516100bf91906101ef565b60405180910390a36001905092915050565b600080fd5b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b6000610101826100d6565b9050919050565b610111816100f6565b811461011c57600080fd5b50565b60008135905061012e81610108565b92915050565b6000819050919050565b61014781610134565b811461015257600080fd5b50565b6000813590506101648161013e565b92915050565b60008060408385031215610181576101806100d1565b5b600061018f8582860161011f565b92505060206101a085828601610155565b9150509250929050565b60008115159050919050565b6101bf816101aa565b82525050565b60006020820190506101da60008301846101b6565b92915050565b6101e981610134565b82525050565b600060208201905061020460008301846101e0565b9291505056fea2646970667358221220b469033f4b77b9565ee84e0a2f04d496b18160d26034d54f9487e57788fd36d564736f6c63430008120033")}, }, } - genBlocks = 5 - signer = types.LatestSignerForChainID(params.TestChainConfig.ChainID) - txHashes = make([]common.Hash, genBlocks) + signer = types.LatestSignerForChainID(params.TestChainConfig.ChainID) + txHashes = make([]common.Hash, genBlocks) ) - backend := newTestBackend(t, genBlocks, genesis, func(i int, b *core.BlockGen) { + + // Set the terminal total difficulty in the config + genesis.Config.TerminalTotalDifficulty = big.NewInt(0) + genesis.Config.TerminalTotalDifficultyPassed = true + backend := newTestBackend(t, genBlocks, genesis, beacon.New(ethash.NewFaker()), func(i int, b *core.BlockGen) { var ( tx *types.Transaction err error @@ -1829,6 +1426,20 @@ Address: contract, StorageKeys: []common.Hash{{0}}, }} tx, err = types.SignTx(types.NewTx(&types.AccessListTx{Nonce: uint64(i), To: nil, Gas: 58100, GasPrice: b.BaseFee(), Data: common.FromHex("0x60806040"), AccessList: accessList}), signer, acc1Key) + case 5: + // blob tx + fee := big.NewInt(500) + fee.Add(fee, b.BaseFee()) + tx, err = types.SignTx(types.NewTx(&types.BlobTx{ + Nonce: uint64(i), + GasTipCap: uint256.NewInt(1), + GasFeeCap: uint256.MustFromBig(fee), + Gas: params.TxGas, + To: acc2Addr, + BlobFeeCap: uint256.NewInt(1), + BlobHashes: []common.Hash{{1}}, + Value: new(uint256.Int), + }), signer, acc1Key) } if err != nil { t.Errorf("failed to sign tx: %v", err) @@ -1837,147 +1448,62 @@ if tx != nil { b.AddTx(tx) txHashes[i] = tx.Hash() } + b.SetPoS() }) - api := NewTransactionAPI(backend, new(AddrLocker)) - blockHashes := make([]common.Hash, genBlocks+1) - ctx := context.Background() - for i := 0; i <= genBlocks; i++ { - header, err := backend.HeaderByNumber(ctx, rpc.BlockNumber(i)) - if err != nil { - t.Errorf("failed to get block: %d err: %v", i, err) - } - blockHashes[i] = header.Hash() - } + return backend, txHashes +} + +func TestRPCGetTransactionReceipt(t *testing.T) { + t.Parallel() + + var ( + backend, txHashes = setupReceiptBackend(t, 6) + api = NewTransactionAPI(backend, new(AddrLocker)) + )   var testSuite = []struct { txHash common.Hash - want string + file string }{ // 0. normal success { txHash: txHashes[0], - want: `{ - "blockHash": "0x1356e49a24d4504e450b303aa770f4ae13c29b9ffacaea1d7dd4043396229dd9", - "blockNumber": "0x1", - "contractAddress": null, - "cumulativeGasUsed": "0x5208", - "effectiveGasPrice": "0x342770c0", - "from": "0x703c4b2bd70c169f5717101caee543299fc946c7", - "gasUsed": "0x5208", - "logs": [], - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "status": "0x1", - "to": "0x0d3ab14bbad3d99f4203bd7a11acb94882050e7e", - "transactionHash": "0x644a31c354391520d00e95b9affbbb010fc79ac268144ab8e28207f4cf51097e", - "transactionIndex": "0x0", - "type": "0x0" - }`, + file: "normal-transfer-tx", }, // 1. create contract { txHash: txHashes[1], - want: `{ - "blockHash": "0x4fc27a4efa7fb8faa04b12b53ec8c8424ab4c21aab1323846365f000e8b4a594", - "blockNumber": "0x2", - "contractAddress": "0xae9bea628c4ce503dcfd7e305cab4e29e7476592", - "cumulativeGasUsed": "0xcf4e", - "effectiveGasPrice": "0x2db16291", - "from": "0x703c4b2bd70c169f5717101caee543299fc946c7", - "gasUsed": "0xcf4e", - "logs": [], - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "status": "0x1", - "to": null, - "transactionHash": "0x340e58cda5086495010b571fe25067fecc9954dc4ee3cedece00691fa3f5904a", - "transactionIndex": "0x0", - "type": "0x0" - }`, + file: "create-contract-tx", }, // 2. with logs success { txHash: txHashes[2], - want: `{ - "blockHash": "0x73385c190219326907524b0020ef453ebc450eaa971ebce16f79e2d23e7e8d4d", - "blockNumber": "0x3", - "contractAddress": null, - "cumulativeGasUsed": "0x5e28", - "effectiveGasPrice": "0x281c2534", - "from": "0x703c4b2bd70c169f5717101caee543299fc946c7", - "gasUsed": "0x5e28", - "logs": [ - { - "address": "0x0000000000000000000000000000000000031ec7", - "topics": [ - "0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef", - "0x000000000000000000000000703c4b2bd70c169f5717101caee543299fc946c7", - "0x0000000000000000000000000000000000000000000000000000000000000003" - ], - "data": "0x000000000000000000000000000000000000000000000000000000000000000d", - "blockNumber": "0x3", - "transactionHash": "0x9dbf43ec9afc8d711932618616471088f66ba4f25fd5c672d97473d02dae967f", - "transactionIndex": "0x0", - "blockHash": "0x73385c190219326907524b0020ef453ebc450eaa971ebce16f79e2d23e7e8d4d", - "logIndex": "0x0", - "removed": false - } - ], - "logsBloom": "0x00000000000000000000008000000000000000000000000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000800000000000000008000000000000000000000000000000000020000000080000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000800000000000000000400000000002000000000000800000000000000000000000000000000000000000000000000000000000000000000000000000000020000000000000000000000000", - "status": "0x1", - "to": "0x0000000000000000000000000000000000031ec7", - "transactionHash": "0x9dbf43ec9afc8d711932618616471088f66ba4f25fd5c672d97473d02dae967f", - "transactionIndex": "0x0", - "type": "0x0" - }`, + file: "with-logs", }, // 3. dynamic tx with logs success { txHash: txHashes[3], - want: `{ - "blockHash": "0x77c3f8919590e0e68db4ce74a3da3140ac3e96dd3d078a48db1da4c08b07503d", - "blockNumber": "0x4", - "contractAddress": null, - "cumulativeGasUsed": "0x538d", - "effectiveGasPrice": "0x2325c3e8", - "from": "0x703c4b2bd70c169f5717101caee543299fc946c7", - "gasUsed": "0x538d", - "logs": [], - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "status": "0x0", - "to": "0x0000000000000000000000000000000000031ec7", - "transactionHash": "0x672e3e39adf23b5656989b7a36e54d54004b1866f53871113bc52e137edb9faf", - "transactionIndex": "0x0", - "type": "0x2" - }`, + file: `dynamic-tx-with-logs`, }, // 4. access list tx with create contract { txHash: txHashes[4], - want: `{ - "blockHash": "0x08e23d8e3711a21fbb8becd7de22fda8fb0a49fba14e1be763d00f99063627e1", - "blockNumber": "0x5", - "contractAddress": "0xfdaa97661a584d977b4d3abb5370766ff5b86a18", - "cumulativeGasUsed": "0xe01a", - "effectiveGasPrice": "0x1ecb3f75", - "from": "0x703c4b2bd70c169f5717101caee543299fc946c7", - "gasUsed": "0xe01a", - "logs": [], - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "status": "0x1", - "to": null, - "transactionHash": "0x8f3c4e2663af0312d508ebd8587f0c88dccbbc8a9bcc322421ff4bc28c456a92", - "transactionIndex": "0x0", - "type": "0x1" - }`, + file: "create-contract-with-access-list", }, // 5. txhash empty { txHash: common.Hash{}, - want: `null`, + file: "txhash-empty", }, // 6. txhash not found { txHash: common.HexToHash("deadbeef"), - want: `null`, + file: "txhash-notfound", + }, + // 7. blob tx + { + txHash: txHashes[5], + file: "blob-tx", }, }   @@ -1991,12 +1517,121 @@ if err != nil { t.Errorf("test %d: want no error, have %v", i, err) continue } - data, err := json.Marshal(result) + testRPCResponseWithFile(t, i, result, "eth_getTransactionReceipt", tt.file) + } +} + +func TestRPCGetBlockReceipts(t *testing.T) { + t.Parallel() + + var ( + genBlocks = 6 + backend, _ = setupReceiptBackend(t, genBlocks) + api = NewBlockChainAPI(backend) + ) + blockHashes := make([]common.Hash, genBlocks+1) + ctx := context.Background() + for i := 0; i <= genBlocks; i++ { + header, err := backend.HeaderByNumber(ctx, rpc.BlockNumber(i)) if err != nil { - t.Errorf("test %d: json marshal error", i) + t.Errorf("failed to get block: %d err: %v", i, err) + } + blockHashes[i] = header.Hash() + } + + var testSuite = []struct { + test rpc.BlockNumberOrHash + file string + }{ + // 0. block without any txs(hash) + { + test: rpc.BlockNumberOrHashWithHash(blockHashes[0], false), + file: "number-0", + }, + // 1. block without any txs(number) + { + test: rpc.BlockNumberOrHashWithNumber(0), + file: "number-1", + }, + // 2. earliest tag + { + test: rpc.BlockNumberOrHashWithNumber(rpc.EarliestBlockNumber), + file: "tag-earliest", + }, + // 3. latest tag + { + test: rpc.BlockNumberOrHashWithNumber(rpc.LatestBlockNumber), + file: "tag-latest", + }, + // 4. block with legacy transfer tx(hash) + { + test: rpc.BlockNumberOrHashWithHash(blockHashes[1], false), + file: "block-with-legacy-transfer-tx", + }, + // 5. block with contract create tx(number) + { + test: rpc.BlockNumberOrHashWithNumber(rpc.BlockNumber(2)), + file: "block-with-contract-create-tx", + }, + // 6. block with legacy contract call tx(hash) + { + test: rpc.BlockNumberOrHashWithHash(blockHashes[3], false), + file: "block-with-legacy-contract-call-tx", + }, + // 7. block with dynamic fee tx(number) + { + test: rpc.BlockNumberOrHashWithNumber(rpc.BlockNumber(4)), + file: "block-with-dynamic-fee-tx", + }, + // 8. block is empty + { + test: rpc.BlockNumberOrHashWithHash(common.Hash{}, false), + file: "hash-empty", + }, + // 9. block is not found + { + test: rpc.BlockNumberOrHashWithHash(common.HexToHash("deadbeef"), false), + file: "hash-notfound", + }, + // 10. block is not found + { + test: rpc.BlockNumberOrHashWithNumber(rpc.BlockNumber(genBlocks + 1)), + file: "block-notfound", + }, + // 11. block with blob tx + { + test: rpc.BlockNumberOrHashWithNumber(rpc.BlockNumber(6)), + file: "block-with-blob-tx", + }, + } + + for i, tt := range testSuite { + var ( + result interface{} + err error + ) + result, err = api.GetBlockReceipts(context.Background(), tt.test) + if err != nil { + t.Errorf("test %d: want no error, have %v", i, err) continue } - want, have := tt.want, string(data) - require.JSONEqf(t, want, have, "test %d: json not match, want: %s, have: %s", i, want, have) + testRPCResponseWithFile(t, i, result, "eth_getBlockReceipts", tt.file) } } + +func testRPCResponseWithFile(t *testing.T, testid int, result interface{}, rpc string, file string) { + data, err := json.MarshalIndent(result, "", " ") + if err != nil { + t.Errorf("test %d: json marshal error", testid) + return + } + outputFile := filepath.Join("testdata", fmt.Sprintf("%s-%s.json", rpc, file)) + if os.Getenv("WRITE_TEST_FILES") != "" { + os.WriteFile(outputFile, data, 0644) + } + want, err := os.ReadFile(outputFile) + if err != nil { + t.Fatalf("error reading expected test file: %s output: %v", outputFile, err) + } + require.JSONEqf(t, string(want), string(data), "test %d: json not match, want: %s, have: %s", testid, string(want), string(data)) +}
diff --git ethereum/go-ethereum/internal/flags/categories.go taikoxyz/taiko-geth/internal/flags/categories.go index ac71931879b4e66f046a90b9ff55098360a62111..487684d98b3e4388fae941d96e9e7ffce6c1b214 100644 --- ethereum/go-ethereum/internal/flags/categories.go +++ taikoxyz/taiko-geth/internal/flags/categories.go @@ -22,7 +22,7 @@ const ( EthCategory = "ETHEREUM" LightCategory = "LIGHT CLIENT" DevCategory = "DEVELOPER CHAIN" - EthashCategory = "ETHASH" + StateCategory = "STATE HISTORY MANAGEMENT" TxPoolCategory = "TRANSACTION POOL (EVM)" BlobPoolCategory = "TRANSACTION POOL (BLOB)" PerfCategory = "PERFORMANCE TUNING"
diff --git ethereum/go-ethereum/internal/flags/flags.go taikoxyz/taiko-geth/internal/flags/flags.go index b0756b4e0a1f9490ed865f488b6a7e4a798646d5..69e9743556b4164d61390055492b6295d51b599d 100644 --- ethereum/go-ethereum/internal/flags/flags.go +++ taikoxyz/taiko-geth/internal/flags/flags.go @@ -20,11 +20,13 @@ import ( "encoding" "errors" "flag" + "fmt" "math/big" "os" "os/user" "path/filepath" "strings" + "syscall"   "github.com/ethereum/go-ethereum/common/math" "github.com/urfave/cli/v2" @@ -68,6 +70,7 @@ Value DirectoryString   Aliases []string + EnvVars []string }   // For cli.Flag: @@ -79,6 +82,14 @@ // Apply called by cli library, grabs variable from environment (if in env) // and adds variable to flag set for parsing. func (f *DirectoryFlag) Apply(set *flag.FlagSet) error { + for _, envVar := range f.EnvVars { + envVar = strings.TrimSpace(envVar) + if value, found := syscall.Getenv(envVar); found { + f.Value.Set(value) + f.HasBeenSet = true + break + } + } eachName(f, func(name string) { set.Var(&f.Value, f.Name, f.Usage) }) @@ -102,7 +113,7 @@ func (f *DirectoryFlag) TakesValue() bool { return true } func (f *DirectoryFlag) GetUsage() string { return f.Usage } func (f *DirectoryFlag) GetValue() string { return f.Value.String() } -func (f *DirectoryFlag) GetEnvVars() []string { return nil } // env not supported +func (f *DirectoryFlag) GetEnvVars() []string { return f.EnvVars }   func (f *DirectoryFlag) GetDefaultText() string { if f.DefaultText != "" { @@ -156,6 +167,7 @@ Value TextMarshaler   Aliases []string + EnvVars []string }   // For cli.Flag: @@ -165,6 +177,16 @@ func (f *TextMarshalerFlag) IsSet() bool { return f.HasBeenSet } func (f *TextMarshalerFlag) String() string { return cli.FlagStringer(f) }   func (f *TextMarshalerFlag) Apply(set *flag.FlagSet) error { + for _, envVar := range f.EnvVars { + envVar = strings.TrimSpace(envVar) + if value, found := syscall.Getenv(envVar); found { + if err := f.Value.UnmarshalText([]byte(value)); err != nil { + return fmt.Errorf("could not parse %q from environment variable %q for flag %s: %s", value, envVar, f.Name, err) + } + f.HasBeenSet = true + break + } + } eachName(f, func(name string) { set.Var(textMarshalerVal{f.Value}, f.Name, f.Usage) }) @@ -187,7 +209,7 @@ // For cli.DocGenerationFlag:   func (f *TextMarshalerFlag) TakesValue() bool { return true } func (f *TextMarshalerFlag) GetUsage() string { return f.Usage } -func (f *TextMarshalerFlag) GetEnvVars() []string { return nil } // env not supported +func (f *TextMarshalerFlag) GetEnvVars() []string { return f.EnvVars }   func (f *TextMarshalerFlag) GetValue() string { t, err := f.Value.MarshalText() @@ -237,6 +259,7 @@ Value *big.Int   Aliases []string + EnvVars []string }   // For cli.Flag: @@ -246,6 +269,16 @@ func (f *BigFlag) IsSet() bool { return f.HasBeenSet } func (f *BigFlag) String() string { return cli.FlagStringer(f) }   func (f *BigFlag) Apply(set *flag.FlagSet) error { + for _, envVar := range f.EnvVars { + envVar = strings.TrimSpace(envVar) + if value, found := syscall.Getenv(envVar); found { + if _, ok := f.Value.SetString(value, 10); !ok { + return fmt.Errorf("could not parse %q from environment variable %q for flag %s", value, envVar, f.Name) + } + f.HasBeenSet = true + break + } + } eachName(f, func(name string) { f.Value = new(big.Int) set.Var((*bigValue)(f.Value), f.Name, f.Usage) @@ -271,7 +304,7 @@ func (f *BigFlag) TakesValue() bool { return true } func (f *BigFlag) GetUsage() string { return f.Usage } func (f *BigFlag) GetValue() string { return f.Value.String() } -func (f *BigFlag) GetEnvVars() []string { return nil } // env not supported +func (f *BigFlag) GetEnvVars() []string { return f.EnvVars }   func (f *BigFlag) GetDefaultText() string { if f.DefaultText != "" {
diff --git ethereum/go-ethereum/internal/flags/helpers.go taikoxyz/taiko-geth/internal/flags/helpers.go index f210e729dd27b512332e441192f37e6fcfd56f78..d4b8e373cc45dbb1f73dea0124cf1fc851475902 100644 --- ethereum/go-ethereum/internal/flags/helpers.go +++ taikoxyz/taiko-geth/internal/flags/helpers.go @@ -18,12 +18,21 @@ package flags   import ( "fmt" + "os" + "regexp" + "sort" "strings"   "github.com/ethereum/go-ethereum/internal/version" + "github.com/ethereum/go-ethereum/log" "github.com/ethereum/go-ethereum/params" + "github.com/mattn/go-isatty" "github.com/urfave/cli/v2" ) + +// usecolor defines whether the CLI help should use colored output or normal dumb +// colorless terminal formatting. +var usecolor = (isatty.IsTerminal(os.Stdout.Fd()) || isatty.IsCygwinTerminal(os.Stdout.Fd())) && os.Getenv("TERM") != "dumb"   // NewApp creates an app with sane defaults. func NewApp(usage string) *cli.App { @@ -129,6 +138,14 @@ } }   func init() { + if usecolor { + // Annotate all help categories with colors + cli.AppHelpTemplate = regexp.MustCompile("[A-Z ]+:").ReplaceAllString(cli.AppHelpTemplate, "\u001B[33m$0\u001B[0m") + + // Annotate flag categories with colors (private template, so need to + // copy-paste the entire thing here...) + cli.AppHelpTemplate = strings.ReplaceAll(cli.AppHelpTemplate, "{{template \"visibleFlagCategoryTemplate\" .}}", "{{range .VisibleFlagCategories}}\n {{if .Name}}\u001B[33m{{.Name}}\u001B[0m\n\n {{end}}{{$flglen := len .Flags}}{{range $i, $e := .Flags}}{{if eq (subtract $flglen $i) 1}}{{$e}}\n{{else}}{{$e}}\n {{end}}{{end}}{{end}}") + } cli.FlagStringer = FlagString }   @@ -138,37 +155,31 @@ df, ok := f.(cli.DocGenerationFlag) if !ok { return "" } - needsPlaceholder := df.TakesValue() placeholder := "" if needsPlaceholder { placeholder = "value" }   - namesText := pad(cli.FlagNamePrefixer(df.Names(), placeholder), 30) + namesText := cli.FlagNamePrefixer(df.Names(), placeholder)   defaultValueString := "" if s := df.GetDefaultText(); s != "" { defaultValueString = " (default: " + s + ")" } - - usage := strings.TrimSpace(df.GetUsage()) envHint := strings.TrimSpace(cli.FlagEnvHinter(df.GetEnvVars(), "")) - if len(envHint) > 0 { - usage += " " + envHint + if envHint != "" { + envHint = " (" + envHint[1:len(envHint)-1] + ")" } - + usage := strings.TrimSpace(df.GetUsage()) usage = wordWrap(usage, 80) usage = indent(usage, 10)   - return fmt.Sprintf("\n %s%s\n%s", namesText, defaultValueString, usage) -} - -func pad(s string, length int) string { - if len(s) < length { - s += strings.Repeat(" ", length-len(s)) + if usecolor { + return fmt.Sprintf("\n \u001B[32m%-35s%-35s\u001B[0m%s\n%s", namesText, defaultValueString, envHint, usage) + } else { + return fmt.Sprintf("\n %-35s%-35s%s\n%s", namesText, defaultValueString, envHint, usage) } - return s }   func indent(s string, nspace int) string { @@ -213,3 +224,78 @@ }   return output.String() } + +// AutoEnvVars extends all the specific CLI flags with automatically generated +// env vars by capitalizing the flag, replacing . with _ and prefixing it with +// the specified string. +// +// Note, the prefix should *not* contain the separator underscore, that will be +// added automatically. +func AutoEnvVars(flags []cli.Flag, prefix string) { + for _, flag := range flags { + envvar := strings.ToUpper(prefix + "_" + strings.ReplaceAll(strings.ReplaceAll(flag.Names()[0], ".", "_"), "-", "_")) + + switch flag := flag.(type) { + case *cli.StringFlag: + flag.EnvVars = append(flag.EnvVars, envvar) + + case *cli.BoolFlag: + flag.EnvVars = append(flag.EnvVars, envvar) + + case *cli.IntFlag: + flag.EnvVars = append(flag.EnvVars, envvar) + + case *cli.Uint64Flag: + flag.EnvVars = append(flag.EnvVars, envvar) + + case *cli.DurationFlag: + flag.EnvVars = append(flag.EnvVars, envvar) + + case *cli.PathFlag: + flag.EnvVars = append(flag.EnvVars, envvar) + + case *BigFlag: + flag.EnvVars = append(flag.EnvVars, envvar) + + case *TextMarshalerFlag: + flag.EnvVars = append(flag.EnvVars, envvar) + + case *DirectoryFlag: + flag.EnvVars = append(flag.EnvVars, envvar) + } + } +} + +// CheckEnvVars iterates over all the environment variables and checks if any of +// them look like a CLI flag but is not consumed. This can be used to detect old +// or mistyped names. +func CheckEnvVars(ctx *cli.Context, flags []cli.Flag, prefix string) { + known := make(map[string]string) + for _, flag := range flags { + docflag, ok := flag.(cli.DocGenerationFlag) + if !ok { + continue + } + for _, envvar := range docflag.GetEnvVars() { + known[envvar] = flag.Names()[0] + } + } + keyvals := os.Environ() + sort.Strings(keyvals) + + for _, keyval := range keyvals { + key := strings.Split(keyval, "=")[0] + if !strings.HasPrefix(key, prefix) { + continue + } + if flag, ok := known[key]; ok { + if ctx.Count(flag) > 0 { + log.Info("Config environment variable found", "envvar", key, "shadowedby", "--"+flag) + } else { + log.Info("Config environment variable found", "envvar", key) + } + } else { + log.Warn("Unknown config environment variable", "envvar", key) + } + } +}
diff --git ethereum/go-ethereum/internal/web3ext/web3ext.go taikoxyz/taiko-geth/internal/web3ext/web3ext.go index 55f19f3104eeb9c32b4aac8a882147ee594bbdea..b86b5909d2cb09046dc8eeacb7ae7377e5d63d0a 100644 --- ethereum/go-ethereum/internal/web3ext/web3ext.go +++ taikoxyz/taiko-geth/internal/web3ext/web3ext.go @@ -617,6 +617,11 @@ call: 'eth_call', params: 4, inputFormatter: [web3._extend.formatters.inputCallFormatter, web3._extend.formatters.inputDefaultBlockNumberFormatter, null, null], }), + new web3._extend.Method({ + name: 'getBlockReceipts', + call: 'eth_getBlockReceipts', + params: 1, + }), ], properties: [ new web3._extend.Property({
diff --git ethereum/go-ethereum/light/lightchain_test.go taikoxyz/taiko-geth/light/lightchain_test.go index e3d756f801118b7d2d4d3494aa96a926f61bbb3c..5694ca72c26693fde44814edf3cdc12364a12ba3 100644 --- ethereum/go-ethereum/light/lightchain_test.go +++ taikoxyz/taiko-geth/light/lightchain_test.go @@ -29,6 +29,7 @@ "github.com/ethereum/go-ethereum/core/rawdb" "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/ethdb" "github.com/ethereum/go-ethereum/params" + "github.com/ethereum/go-ethereum/trie" )   // So we can deterministically seed different blockchains @@ -55,7 +56,7 @@ // header only chain. func newCanonical(n int) (ethdb.Database, *LightChain, error) { db := rawdb.NewMemoryDatabase() gspec := core.Genesis{Config: params.TestChainConfig} - genesis := gspec.MustCommit(db) + genesis := gspec.MustCommit(db, trie.NewDatabase(db, trie.HashDefaults)) blockchain, _ := NewLightChain(&dummyOdr{db: db, indexerConfig: TestClientIndexerConfig}, gspec.Config, ethash.NewFaker())   // Create and inject the requested chain @@ -75,7 +76,7 @@ gspec := &core.Genesis{ Difficulty: big.NewInt(1), Config: params.TestChainConfig, } - gspec.MustCommit(db) + gspec.MustCommit(db, trie.NewDatabase(db, trie.HashDefaults)) lc, err := NewLightChain(&dummyOdr{db: db}, gspec.Config, ethash.NewFullFaker()) if err != nil { panic(err)
diff --git ethereum/go-ethereum/light/odr.go taikoxyz/taiko-geth/light/odr.go index 2597027435ba2fdf7e52add58e76015bdd43f125..39f626ee2c5368bf23ee41f21fe66aea1a6616eb 100644 --- ethereum/go-ethereum/light/odr.go +++ taikoxyz/taiko-geth/light/odr.go @@ -27,6 +27,7 @@ "github.com/ethereum/go-ethereum/core/rawdb" "github.com/ethereum/go-ethereum/core/txpool" "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/ethdb" + "github.com/ethereum/go-ethereum/trie/trienode" )   // NoOdr is the default context passed to an ODR capable function when the ODR @@ -90,7 +91,7 @@ // TrieRequest is the ODR request type for state/storage trie entries type TrieRequest struct { Id *TrieID Key []byte - Proof *NodeSet + Proof *trienode.ProofSet }   // StoreResult stores the retrieved data in local database @@ -143,7 +144,7 @@ ChtNum, BlockNum uint64 ChtRoot common.Hash Header *types.Header Td *big.Int - Proof *NodeSet + Proof *trienode.ProofSet }   // StoreResult stores the retrieved data in local database @@ -163,7 +164,7 @@ BitIdx uint SectionIndexList []uint64 BloomTrieRoot common.Hash BloomBits [][]byte - Proofs *NodeSet + Proofs *trienode.ProofSet }   // StoreResult stores the retrieved data in local database
diff --git ethereum/go-ethereum/light/odr_test.go taikoxyz/taiko-geth/light/odr_test.go index 79f901bbdb680fd4f96258ec9a62c29de7456a85..c415d73e7ef2396556eeed0e4a81da016c4512c8 100644 --- ethereum/go-ethereum/light/odr_test.go +++ taikoxyz/taiko-geth/light/odr_test.go @@ -36,6 +36,8 @@ "github.com/ethereum/go-ethereum/crypto" "github.com/ethereum/go-ethereum/ethdb" "github.com/ethereum/go-ethereum/params" "github.com/ethereum/go-ethereum/rlp" + "github.com/ethereum/go-ethereum/trie" + "github.com/ethereum/go-ethereum/trie/trienode" )   var ( @@ -94,7 +96,7 @@ } if err != nil { panic(err) } - nodes := NewNodeSet() + nodes := trienode.NewProofSet() t.Prove(req.Key, nodes) req.Proof = nodes case *CodeRequest: @@ -282,7 +284,7 @@ if _, err := blockchain.InsertChain(gchain); err != nil { t.Fatal(err) }   - gspec.MustCommit(ldb) + gspec.MustCommit(ldb, trie.NewDatabase(ldb, trie.HashDefaults)) odr := &testOdr{sdb: sdb, ldb: ldb, serverState: blockchain.StateCache(), indexerConfig: TestClientIndexerConfig} lightchain, err := NewLightChain(odr, gspec.Config, ethash.NewFullFaker()) if err != nil {
diff --git ethereum/go-ethereum/light/odr_util.go taikoxyz/taiko-geth/light/odr_util.go index 02379ce5fff633443a9ddfd37f806af0e0033680..9cac7df4fa98323fbf6a4a2e44c43b7584a84a03 100644 --- ethereum/go-ethereum/light/odr_util.go +++ taikoxyz/taiko-geth/light/odr_util.go @@ -17,7 +17,6 @@ package light   import ( - "bytes" "context" "errors" "math/big" @@ -126,7 +125,7 @@ if err != nil { return nil, err } body := new(types.Body) - if err := rlp.Decode(bytes.NewReader(data), body); err != nil { + if err := rlp.DecodeBytes(data, body); err != nil { return nil, err } return body, nil
diff --git ethereum/go-ethereum/light/postprocess.go taikoxyz/taiko-geth/light/postprocess.go index 567814e2bfd7366d1210c1ee3d196433fdffdc30..a317e30b90a45c1dbb15dfb9985a96048f3182aa 100644 --- ethereum/go-ethereum/light/postprocess.go +++ taikoxyz/taiko-geth/light/postprocess.go @@ -145,7 +145,7 @@ backend := &ChtIndexerBackend{ diskdb: db, odr: odr, trieTable: trieTable, - triedb: trie.NewDatabaseWithConfig(trieTable, &trie.Config{Cache: 1}), // Use a tiny cache only to keep memory down + triedb: trie.NewDatabase(trieTable, trie.HashDefaults), sectionSize: size, disablePruning: disablePruning, } @@ -348,7 +348,7 @@ backend := &BloomTrieIndexerBackend{ diskdb: db, odr: odr, trieTable: trieTable, - triedb: trie.NewDatabaseWithConfig(trieTable, &trie.Config{Cache: 1}), // Use a tiny cache only to keep memory down + triedb: trie.NewDatabase(trieTable, trie.HashDefaults), parentSize: parentSize, size: size, disablePruning: disablePruning, @@ -363,7 +363,7 @@ // ODR backend in order to be able to add new entries and calculate subsequent root hashes func (b *BloomTrieIndexerBackend) fetchMissingNodes(ctx context.Context, section uint64, root common.Hash) error { indexCh := make(chan uint, types.BloomBitLength) type res struct { - nodes *NodeSet + nodes *trienode.ProofSet err error } resCh := make(chan res, types.BloomBitLength)
diff --git ethereum/go-ethereum/light/trie.go taikoxyz/taiko-geth/light/trie.go index 4967cc74e5ba813c50436b3bd34b5cfda830c732..1847f1e71b3c6db84ff4f293d197624c33e6c31d 100644 --- ethereum/go-ethereum/light/trie.go +++ taikoxyz/taiko-geth/light/trie.go @@ -215,7 +215,8 @@ id = trie.StorageTrieID(t.id.StateRoot, crypto.Keccak256Hash(t.id.AccountAddress), t.id.Root) } else { id = trie.StateTrieID(t.id.StateRoot) } - t.trie, err = trie.New(id, trie.NewDatabase(t.db.backend.Database())) + triedb := trie.NewDatabase(t.db.backend.Database(), trie.HashDefaults) + t.trie, err = trie.New(id, triedb) } if err == nil { err = fn() @@ -247,7 +248,8 @@ id = trie.StorageTrieID(t.id.StateRoot, crypto.Keccak256Hash(t.id.AccountAddress), t.id.Root) } else { id = trie.StateTrieID(t.id.StateRoot) } - t, err := trie.New(id, trie.NewDatabase(t.db.backend.Database())) + triedb := trie.NewDatabase(t.db.backend.Database(), trie.HashDefaults) + t, err := trie.New(id, triedb) if err == nil { it.t.trie = t }
diff --git ethereum/go-ethereum/light/trie_test.go taikoxyz/taiko-geth/light/trie_test.go index ad7d769c84a440ee6fce81783f7eab1e1bdd780d..fe724e9eea563c8ce2ec1595efeca8b24e3e6628 100644 --- ethereum/go-ethereum/light/trie_test.go +++ taikoxyz/taiko-geth/light/trie_test.go @@ -50,7 +50,7 @@ if _, err := blockchain.InsertChain(gchain); err != nil { panic(err) }   - gspec.MustCommit(lightdb) + gspec.MustCommit(lightdb, trie.NewDatabase(lightdb, trie.HashDefaults)) ctx := context.Background() odr := &testOdr{sdb: fulldb, ldb: lightdb, serverState: blockchain.StateCache(), indexerConfig: TestClientIndexerConfig} head := blockchain.CurrentHeader()
diff --git ethereum/go-ethereum/light/txpool_test.go taikoxyz/taiko-geth/light/txpool_test.go index 1181e3889e5fbefb4b22cc5e29fac982faa61f99..1eec7bc4277993dd317d92db875e0c3b09b2c193 100644 --- ethereum/go-ethereum/light/txpool_test.go +++ taikoxyz/taiko-geth/light/txpool_test.go @@ -30,6 +30,7 @@ "github.com/ethereum/go-ethereum/core/rawdb" "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/core/vm" "github.com/ethereum/go-ethereum/params" + "github.com/ethereum/go-ethereum/trie" )   type testTxRelay struct { @@ -96,7 +97,7 @@ if _, err := blockchain.InsertChain(gchain); err != nil { panic(err) }   - gspec.MustCommit(ldb) + gspec.MustCommit(ldb, trie.NewDatabase(ldb, trie.HashDefaults)) odr := &testOdr{sdb: sdb, ldb: ldb, serverState: blockchain.StateCache(), indexerConfig: TestClientIndexerConfig} relay := &testTxRelay{ send: make(chan int, 1),
diff --git ethereum/go-ethereum/log/format.go taikoxyz/taiko-geth/log/format.go index 6a03013b816c3c726e77feeb48f6e5603a25513e..1adf79c17e684055787a52f6a3b4f3156b964353 100644 --- ethereum/go-ethereum/log/format.go +++ taikoxyz/taiko-geth/log/format.go @@ -33,7 +33,15 @@ // PrintOrigins sets or unsets log location (file:line) printing for terminal // format output. func PrintOrigins(print bool) { locationEnabled.Store(print) + if print { + stackEnabled.Store(true) + } } + +// stackEnabled is an atomic flag controlling whether the log handler needs +// to store the callsite stack. This is needed in case any handler wants to +// print locations (locationEnabled), use vmodule, or print full stacks (BacktraceAt). +var stackEnabled atomic.Bool   // locationEnabled is an atomic flag controlling whether the terminal formatter // should append the log locations too when printing entries.
diff --git ethereum/go-ethereum/log/handler.go taikoxyz/taiko-geth/log/handler.go index 892cfcc3e1ac5de176d23c7f6753aca55c87fb4d..4a0cf578f6cd23d680019a362868fe49e1c7b5f4 100644 --- ethereum/go-ethereum/log/handler.go +++ taikoxyz/taiko-geth/log/handler.go @@ -7,6 +7,7 @@ "net" "os" "reflect" "sync" + "sync/atomic"   "github.com/go-stack/stack" ) @@ -354,3 +355,21 @@ func (m muster) NetHandler(network, addr string, fmtr Format) Handler { return must(NetHandler(network, addr, fmtr)) } + +// swapHandler wraps another handler that may be swapped out +// dynamically at runtime in a thread-safe fashion. +type swapHandler struct { + handler atomic.Value +} + +func (h *swapHandler) Log(r *Record) error { + return (*h.handler.Load().(*Handler)).Log(r) +} + +func (h *swapHandler) Swap(newHandler Handler) { + h.handler.Store(&newHandler) +} + +func (h *swapHandler) Get() Handler { + return *h.handler.Load().(*Handler) +}
diff --git ethereum/go-ethereum/log/handler_glog.go taikoxyz/taiko-geth/log/handler_glog.go index 6db5f1a4c9ba353a76f7f23187374182ceaec071..afca0808b38a38a199420960a78a973721dd9ee0 100644 --- ethereum/go-ethereum/log/handler_glog.go +++ taikoxyz/taiko-geth/log/handler_glog.go @@ -139,7 +139,10 @@ h.patterns = filter h.siteCache = make(map[uintptr]Lvl) h.override.Store(len(filter) != 0) - + // Enable location storage (globally) + if len(h.patterns) > 0 { + stackEnabled.Store(true) + } return nil }   @@ -172,7 +175,8 @@ defer h.lock.Unlock()   h.location = location h.backtrace.Store(len(location) > 0) - + // Enable location storage (globally) + stackEnabled.Store(true) return nil }
diff --git ethereum/go-ethereum/log/handler_go13.go taikoxyz/taiko-geth/log/handler_go13.go deleted file mode 100644 index 4df694debed86c78da1fbf9e84f45beca29688b9..0000000000000000000000000000000000000000 --- ethereum/go-ethereum/log/handler_go13.go +++ /dev/null @@ -1,27 +0,0 @@ -//go:build !go1.4 -// +build !go1.4 - -package log - -import ( - "sync/atomic" - "unsafe" -) - -// swapHandler wraps another handler that may be swapped out -// dynamically at runtime in a thread-safe fashion. -type swapHandler struct { - handler unsafe.Pointer -} - -func (h *swapHandler) Log(r *Record) error { - return h.Get().Log(r) -} - -func (h *swapHandler) Get() Handler { - return *(*Handler)(atomic.LoadPointer(&h.handler)) -} - -func (h *swapHandler) Swap(newHandler Handler) { - atomic.StorePointer(&h.handler, unsafe.Pointer(&newHandler)) -}
diff --git ethereum/go-ethereum/log/handler_go14.go taikoxyz/taiko-geth/log/handler_go14.go deleted file mode 100644 index d0cb14aa063b2ff6f20e9f1eb1881fe776482c57..0000000000000000000000000000000000000000 --- ethereum/go-ethereum/log/handler_go14.go +++ /dev/null @@ -1,24 +0,0 @@ -//go:build go1.4 -// +build go1.4 - -package log - -import "sync/atomic" - -// swapHandler wraps another handler that may be swapped out -// dynamically at runtime in a thread-safe fashion. -type swapHandler struct { - handler atomic.Value -} - -func (h *swapHandler) Log(r *Record) error { - return (*h.handler.Load().(*Handler)).Log(r) -} - -func (h *swapHandler) Swap(newHandler Handler) { - h.handler.Store(&newHandler) -} - -func (h *swapHandler) Get() Handler { - return *h.handler.Load().(*Handler) -}
diff --git ethereum/go-ethereum/log/logger.go taikoxyz/taiko-geth/log/logger.go index 4e471a22da9a3ac3c524c98478da0450842ea646..42e7e375d0025fd06618b7a216e6e906f2efac07 100644 --- ethereum/go-ethereum/log/logger.go +++ taikoxyz/taiko-geth/log/logger.go @@ -177,19 +177,22 @@ h *swapHandler }   func (l *logger) write(msg string, lvl Lvl, ctx []interface{}, skip int) { - l.h.Log(&Record{ + record := &Record{ Time: time.Now(), Lvl: lvl, Msg: msg, Ctx: newContext(l.ctx, ctx), - Call: stack.Caller(skip), KeyNames: RecordKeyNames{ Time: timeKey, Msg: msgKey, Lvl: lvlKey, Ctx: ctxKey, }, - }) + } + if stackEnabled.Load() { + record.Call = stack.Caller(skip) + } + l.h.Log(record) }   func (l *logger) New(ctx ...interface{}) Logger {
diff --git ethereum/go-ethereum/log/logger_test.go taikoxyz/taiko-geth/log/logger_test.go new file mode 100644 index 0000000000000000000000000000000000000000..2e59b3fdf0b1140e7073a830a6cc01f74e5a0dc1 --- /dev/null +++ taikoxyz/taiko-geth/log/logger_test.go @@ -0,0 +1,67 @@ +package log + +import ( + "bytes" + "os" + "strings" + "testing" +) + +// TestLoggingWithTrace checks that if BackTraceAt is set, then the +// gloghandler is capable of spitting out a stacktrace +func TestLoggingWithTrace(t *testing.T) { + defer stackEnabled.Store(stackEnabled.Load()) + out := new(bytes.Buffer) + logger := New() + { + glog := NewGlogHandler(StreamHandler(out, TerminalFormat(false))) + glog.Verbosity(LvlTrace) + if err := glog.BacktraceAt("logger_test.go:24"); err != nil { + t.Fatal(err) + } + logger.SetHandler(glog) + } + logger.Trace("a message", "foo", "bar") // Will be bumped to INFO + have := out.String() + if !strings.HasPrefix(have, "INFO") { + t.Fatalf("backtraceat should bump level to info: %s", have) + } + // The timestamp is locale-dependent, so we want to trim that off + // "INFO [01-01|00:00:00.000] a messag ..." -> "a messag..." + have = strings.Split(have, "]")[1] + wantPrefix := " a message\n\ngoroutine" + if !strings.HasPrefix(have, wantPrefix) { + t.Errorf("\nhave: %q\nwant: %q\n", have, wantPrefix) + } +} + +// TestLoggingWithVmodule checks that vmodule works. +func TestLoggingWithVmodule(t *testing.T) { + defer stackEnabled.Store(stackEnabled.Load()) + out := new(bytes.Buffer) + logger := New() + { + glog := NewGlogHandler(StreamHandler(out, TerminalFormat(false))) + glog.Verbosity(LvlCrit) + logger.SetHandler(glog) + logger.Warn("This should not be seen", "ignored", "true") + glog.Vmodule("logger_test.go=5") + } + logger.Trace("a message", "foo", "bar") + have := out.String() + // The timestamp is locale-dependent, so we want to trim that off + // "INFO [01-01|00:00:00.000] a messag ..." -> "a messag..." + have = strings.Split(have, "]")[1] + want := " a message foo=bar\n" + if have != want { + t.Errorf("\nhave: %q\nwant: %q\n", have, want) + } +} + +func BenchmarkTraceLogging(b *testing.B) { + Root().SetHandler(LvlFilterHandler(LvlInfo, StreamHandler(os.Stderr, TerminalFormat(true)))) + b.ResetTimer() + for i := 0; i < b.N; i++ { + Trace("a message", "v", i) + } +}
diff --git ethereum/go-ethereum/metrics/counter.go taikoxyz/taiko-geth/metrics/counter.go index 55e1c59540f62f491e563aa864c73b1c04631eba..cb81599c215aafd1f72a0a6cea090904ac43e8e6 100644 --- ethereum/go-ethereum/metrics/counter.go +++ taikoxyz/taiko-geth/metrics/counter.go @@ -4,13 +4,16 @@ import ( "sync/atomic" )   +type CounterSnapshot interface { + Count() int64 +} + // Counters hold an int64 value that can be incremented and decremented. type Counter interface { Clear() - Count() int64 Dec(int64) Inc(int64) - Snapshot() Counter + Snapshot() CounterSnapshot }   // GetOrRegisterCounter returns an existing Counter or constructs and registers @@ -38,13 +41,13 @@ func NewCounter() Counter { if !Enabled { return NilCounter{} } - return &StandardCounter{} + return new(StandardCounter) }   // NewCounterForced constructs a new StandardCounter and returns it no matter if // the global switch is enabled or not. func NewCounterForced() Counter { - return &StandardCounter{} + return new(StandardCounter) }   // NewRegisteredCounter constructs and registers a new StandardCounter. @@ -70,75 +73,40 @@ r.Register(name, c) return c }   -// CounterSnapshot is a read-only copy of another Counter. -type CounterSnapshot int64 - -// Clear panics. -func (CounterSnapshot) Clear() { - panic("Clear called on a CounterSnapshot") -} +// counterSnapshot is a read-only copy of another Counter. +type counterSnapshot int64   // Count returns the count at the time the snapshot was taken. -func (c CounterSnapshot) Count() int64 { return int64(c) } - -// Dec panics. -func (CounterSnapshot) Dec(int64) { - panic("Dec called on a CounterSnapshot") -} - -// Inc panics. -func (CounterSnapshot) Inc(int64) { - panic("Inc called on a CounterSnapshot") -} - -// Snapshot returns the snapshot. -func (c CounterSnapshot) Snapshot() Counter { return c } +func (c counterSnapshot) Count() int64 { return int64(c) }   // NilCounter is a no-op Counter. type NilCounter struct{}   -// Clear is a no-op. -func (NilCounter) Clear() {} - -// Count is a no-op. -func (NilCounter) Count() int64 { return 0 } - -// Dec is a no-op. -func (NilCounter) Dec(i int64) {} - -// Inc is a no-op. -func (NilCounter) Inc(i int64) {} - -// Snapshot is a no-op. -func (NilCounter) Snapshot() Counter { return NilCounter{} } +func (NilCounter) Clear() {} +func (NilCounter) Dec(i int64) {} +func (NilCounter) Inc(i int64) {} +func (NilCounter) Snapshot() CounterSnapshot { return (*emptySnapshot)(nil) }   // StandardCounter is the standard implementation of a Counter and uses the // sync/atomic package to manage a single int64 value. -type StandardCounter struct { - count atomic.Int64 -} +type StandardCounter atomic.Int64   // Clear sets the counter to zero. func (c *StandardCounter) Clear() { - c.count.Store(0) -} - -// Count returns the current count. -func (c *StandardCounter) Count() int64 { - return c.count.Load() + (*atomic.Int64)(c).Store(0) }   // Dec decrements the counter by the given amount. func (c *StandardCounter) Dec(i int64) { - c.count.Add(-i) + (*atomic.Int64)(c).Add(-i) }   // Inc increments the counter by the given amount. func (c *StandardCounter) Inc(i int64) { - c.count.Add(i) + (*atomic.Int64)(c).Add(i) }   // Snapshot returns a read-only copy of the counter. -func (c *StandardCounter) Snapshot() Counter { - return CounterSnapshot(c.Count()) +func (c *StandardCounter) Snapshot() CounterSnapshot { + return counterSnapshot((*atomic.Int64)(c).Load()) }
diff --git ethereum/go-ethereum/metrics/counter_float64.go taikoxyz/taiko-geth/metrics/counter_float64.go index d1197bb8e0ae9e7747f1eff36e9ae7ebc9b7210a..15c81494efb819b8200e331f3d52839813df6f5f 100644 --- ethereum/go-ethereum/metrics/counter_float64.go +++ taikoxyz/taiko-geth/metrics/counter_float64.go @@ -5,13 +5,16 @@ "math" "sync/atomic" )   +type CounterFloat64Snapshot interface { + Count() float64 +} + // CounterFloat64 holds a float64 value that can be incremented and decremented. type CounterFloat64 interface { Clear() - Count() float64 Dec(float64) Inc(float64) - Snapshot() CounterFloat64 + Snapshot() CounterFloat64Snapshot }   // GetOrRegisterCounterFloat64 returns an existing CounterFloat64 or constructs and registers @@ -71,47 +74,19 @@ r.Register(name, c) return c }   -// CounterFloat64Snapshot is a read-only copy of another CounterFloat64. -type CounterFloat64Snapshot float64 - -// Clear panics. -func (CounterFloat64Snapshot) Clear() { - panic("Clear called on a CounterFloat64Snapshot") -} +// counterFloat64Snapshot is a read-only copy of another CounterFloat64. +type counterFloat64Snapshot float64   // Count returns the value at the time the snapshot was taken. -func (c CounterFloat64Snapshot) Count() float64 { return float64(c) } - -// Dec panics. -func (CounterFloat64Snapshot) Dec(float64) { - panic("Dec called on a CounterFloat64Snapshot") -} - -// Inc panics. -func (CounterFloat64Snapshot) Inc(float64) { - panic("Inc called on a CounterFloat64Snapshot") -} - -// Snapshot returns the snapshot. -func (c CounterFloat64Snapshot) Snapshot() CounterFloat64 { return c } +func (c counterFloat64Snapshot) Count() float64 { return float64(c) }   -// NilCounterFloat64 is a no-op CounterFloat64. type NilCounterFloat64 struct{}   -// Clear is a no-op. -func (NilCounterFloat64) Clear() {} - -// Count is a no-op. -func (NilCounterFloat64) Count() float64 { return 0.0 } - -// Dec is a no-op. -func (NilCounterFloat64) Dec(i float64) {} - -// Inc is a no-op. -func (NilCounterFloat64) Inc(i float64) {} - -// Snapshot is a no-op. -func (NilCounterFloat64) Snapshot() CounterFloat64 { return NilCounterFloat64{} } +func (NilCounterFloat64) Clear() {} +func (NilCounterFloat64) Count() float64 { return 0.0 } +func (NilCounterFloat64) Dec(i float64) {} +func (NilCounterFloat64) Inc(i float64) {} +func (NilCounterFloat64) Snapshot() CounterFloat64Snapshot { return NilCounterFloat64{} }   // StandardCounterFloat64 is the standard implementation of a CounterFloat64 and uses the // atomic to manage a single float64 value. @@ -124,11 +99,6 @@ func (c *StandardCounterFloat64) Clear() { c.floatBits.Store(0) }   -// Count returns the current value. -func (c *StandardCounterFloat64) Count() float64 { - return math.Float64frombits(c.floatBits.Load()) -} - // Dec decrements the counter by the given amount. func (c *StandardCounterFloat64) Dec(v float64) { atomicAddFloat(&c.floatBits, -v) @@ -140,8 +110,9 @@ atomicAddFloat(&c.floatBits, v) }   // Snapshot returns a read-only copy of the counter. -func (c *StandardCounterFloat64) Snapshot() CounterFloat64 { - return CounterFloat64Snapshot(c.Count()) +func (c *StandardCounterFloat64) Snapshot() CounterFloat64Snapshot { + v := math.Float64frombits(c.floatBits.Load()) + return counterFloat64Snapshot(v) }   func atomicAddFloat(fbits *atomic.Uint64, v float64) {
diff --git ethereum/go-ethereum/metrics/counter_float_64_test.go taikoxyz/taiko-geth/metrics/counter_float_64_test.go index f17aca330cbed85f9ce6a11d9baaafbcabc3a9f4..c21bd3307fa104869b77491b4596797e5ef10698 100644 --- ethereum/go-ethereum/metrics/counter_float_64_test.go +++ taikoxyz/taiko-geth/metrics/counter_float_64_test.go @@ -27,7 +27,7 @@ wg.Done() }() } wg.Wait() - if have, want := c.Count(), 10.0*float64(b.N); have != want { + if have, want := c.Snapshot().Count(), 10.0*float64(b.N); have != want { b.Fatalf("have %f want %f", have, want) } } @@ -36,7 +36,7 @@ func TestCounterFloat64Clear(t *testing.T) { c := NewCounterFloat64() c.Inc(1.0) c.Clear() - if count := c.Count(); count != 0 { + if count := c.Snapshot().Count(); count != 0 { t.Errorf("c.Count(): 0 != %v\n", count) } } @@ -44,7 +44,7 @@ func TestCounterFloat64Dec1(t *testing.T) { c := NewCounterFloat64() c.Dec(1.0) - if count := c.Count(); count != -1.0 { + if count := c.Snapshot().Count(); count != -1.0 { t.Errorf("c.Count(): -1.0 != %v\n", count) } } @@ -52,7 +52,7 @@ func TestCounterFloat64Dec2(t *testing.T) { c := NewCounterFloat64() c.Dec(2.0) - if count := c.Count(); count != -2.0 { + if count := c.Snapshot().Count(); count != -2.0 { t.Errorf("c.Count(): -2.0 != %v\n", count) } } @@ -60,7 +60,7 @@ func TestCounterFloat64Inc1(t *testing.T) { c := NewCounterFloat64() c.Inc(1.0) - if count := c.Count(); count != 1.0 { + if count := c.Snapshot().Count(); count != 1.0 { t.Errorf("c.Count(): 1.0 != %v\n", count) } } @@ -68,7 +68,7 @@ func TestCounterFloat64Inc2(t *testing.T) { c := NewCounterFloat64() c.Inc(2.0) - if count := c.Count(); count != 2.0 { + if count := c.Snapshot().Count(); count != 2.0 { t.Errorf("c.Count(): 2.0 != %v\n", count) } } @@ -85,7 +85,7 @@ }   func TestCounterFloat64Zero(t *testing.T) { c := NewCounterFloat64() - if count := c.Count(); count != 0 { + if count := c.Snapshot().Count(); count != 0 { t.Errorf("c.Count(): 0 != %v\n", count) } } @@ -93,7 +93,7 @@ func TestGetOrRegisterCounterFloat64(t *testing.T) { r := NewRegistry() NewRegisteredCounterFloat64("foo", r).Inc(47.0) - if c := GetOrRegisterCounterFloat64("foo", r); c.Count() != 47.0 { + if c := GetOrRegisterCounterFloat64("foo", r).Snapshot(); c.Count() != 47.0 { t.Fatal(c) } }
diff --git ethereum/go-ethereum/metrics/counter_test.go taikoxyz/taiko-geth/metrics/counter_test.go index af26ef1548fee722d2f19041a99e3c871a109a2a..1b15b23f215fe13c64c21ef3de34989a8fbea064 100644 --- ethereum/go-ethereum/metrics/counter_test.go +++ taikoxyz/taiko-geth/metrics/counter_test.go @@ -14,7 +14,7 @@ func TestCounterClear(t *testing.T) { c := NewCounter() c.Inc(1) c.Clear() - if count := c.Count(); count != 0 { + if count := c.Snapshot().Count(); count != 0 { t.Errorf("c.Count(): 0 != %v\n", count) } } @@ -22,7 +22,7 @@ func TestCounterDec1(t *testing.T) { c := NewCounter() c.Dec(1) - if count := c.Count(); count != -1 { + if count := c.Snapshot().Count(); count != -1 { t.Errorf("c.Count(): -1 != %v\n", count) } } @@ -30,7 +30,7 @@ func TestCounterDec2(t *testing.T) { c := NewCounter() c.Dec(2) - if count := c.Count(); count != -2 { + if count := c.Snapshot().Count(); count != -2 { t.Errorf("c.Count(): -2 != %v\n", count) } } @@ -38,7 +38,7 @@ func TestCounterInc1(t *testing.T) { c := NewCounter() c.Inc(1) - if count := c.Count(); count != 1 { + if count := c.Snapshot().Count(); count != 1 { t.Errorf("c.Count(): 1 != %v\n", count) } } @@ -46,7 +46,7 @@ func TestCounterInc2(t *testing.T) { c := NewCounter() c.Inc(2) - if count := c.Count(); count != 2 { + if count := c.Snapshot().Count(); count != 2 { t.Errorf("c.Count(): 2 != %v\n", count) } } @@ -63,7 +63,7 @@ }   func TestCounterZero(t *testing.T) { c := NewCounter() - if count := c.Count(); count != 0 { + if count := c.Snapshot().Count(); count != 0 { t.Errorf("c.Count(): 0 != %v\n", count) } } @@ -71,7 +71,7 @@ func TestGetOrRegisterCounter(t *testing.T) { r := NewRegistry() NewRegisteredCounter("foo", r).Inc(47) - if c := GetOrRegisterCounter("foo", r); c.Count() != 47 { + if c := GetOrRegisterCounter("foo", r).Snapshot(); c.Count() != 47 { t.Fatal(c) } }
diff --git ethereum/go-ethereum/metrics/doc.go taikoxyz/taiko-geth/metrics/doc.go deleted file mode 100644 index 13f429c1689d24c765488286e4f1308384388fc0..0000000000000000000000000000000000000000 --- ethereum/go-ethereum/metrics/doc.go +++ /dev/null @@ -1,4 +0,0 @@ -package metrics - -const epsilon = 0.0000000000000001 -const epsilonPercentile = .00000000001
diff --git ethereum/go-ethereum/metrics/ewma.go taikoxyz/taiko-geth/metrics/ewma.go index ed95cba19b4f81224ee72bad5cbb6180ad76edf9..1d7a4f00cf4575f9c0f944be5fd560e44869e665 100644 --- ethereum/go-ethereum/metrics/ewma.go +++ taikoxyz/taiko-geth/metrics/ewma.go @@ -7,11 +7,14 @@ "sync/atomic" "time" )   +type EWMASnapshot interface { + Rate() float64 +} + // EWMAs continuously calculate an exponentially-weighted moving average // based on an outside source of clock ticks. type EWMA interface { - Rate() float64 - Snapshot() EWMA + Snapshot() EWMASnapshot Tick() Update(int64) } @@ -36,40 +39,19 @@ func NewEWMA15() EWMA { return NewEWMA(1 - math.Exp(-5.0/60.0/15)) }   -// EWMASnapshot is a read-only copy of another EWMA. -type EWMASnapshot float64 +// ewmaSnapshot is a read-only copy of another EWMA. +type ewmaSnapshot float64   // Rate returns the rate of events per second at the time the snapshot was // taken. -func (a EWMASnapshot) Rate() float64 { return float64(a) } - -// Snapshot returns the snapshot. -func (a EWMASnapshot) Snapshot() EWMA { return a } - -// Tick panics. -func (EWMASnapshot) Tick() { - panic("Tick called on an EWMASnapshot") -} - -// Update panics. -func (EWMASnapshot) Update(int64) { - panic("Update called on an EWMASnapshot") -} +func (a ewmaSnapshot) Rate() float64 { return float64(a) }   // NilEWMA is a no-op EWMA. type NilEWMA struct{}   -// Rate is a no-op. -func (NilEWMA) Rate() float64 { return 0.0 } - -// Snapshot is a no-op. -func (NilEWMA) Snapshot() EWMA { return NilEWMA{} } - -// Tick is a no-op. -func (NilEWMA) Tick() {} - -// Update is a no-op. -func (NilEWMA) Update(n int64) {} +func (NilEWMA) Snapshot() EWMASnapshot { return (*emptySnapshot)(nil) } +func (NilEWMA) Tick() {} +func (NilEWMA) Update(n int64) {}   // StandardEWMA is the standard implementation of an EWMA and tracks the number // of uncounted events and processes them on each tick. It uses the @@ -77,37 +59,50 @@ // sync/atomic package to manage uncounted events. type StandardEWMA struct { uncounted atomic.Int64 alpha float64 - rate float64 - init bool + rate atomic.Uint64 + init atomic.Bool mutex sync.Mutex }   -// Rate returns the moving average rate of events per second. -func (a *StandardEWMA) Rate() float64 { - a.mutex.Lock() - defer a.mutex.Unlock() - return a.rate * float64(time.Second) -} - // Snapshot returns a read-only copy of the EWMA. -func (a *StandardEWMA) Snapshot() EWMA { - return EWMASnapshot(a.Rate()) +func (a *StandardEWMA) Snapshot() EWMASnapshot { + r := math.Float64frombits(a.rate.Load()) * float64(time.Second) + return ewmaSnapshot(r) }   // Tick ticks the clock to update the moving average. It assumes it is called // every five seconds. func (a *StandardEWMA) Tick() { - count := a.uncounted.Load() - a.uncounted.Add(-count) - instantRate := float64(count) / float64(5*time.Second) + // Optimization to avoid mutex locking in the hot-path. + if a.init.Load() { + a.updateRate(a.fetchInstantRate()) + return + } + // Slow-path: this is only needed on the first Tick() and preserves transactional updating + // of init and rate in the else block. The first conditional is needed below because + // a different thread could have set a.init = 1 between the time of the first atomic load and when + // the lock was acquired. a.mutex.Lock() - defer a.mutex.Unlock() - if a.init { - a.rate += a.alpha * (instantRate - a.rate) + if a.init.Load() { + // The fetchInstantRate() uses atomic loading, which is unnecessary in this critical section + // but again, this section is only invoked on the first successful Tick() operation. + a.updateRate(a.fetchInstantRate()) } else { - a.init = true - a.rate = instantRate + a.init.Store(true) + a.rate.Store(math.Float64bits(a.fetchInstantRate())) } + a.mutex.Unlock() +} + +func (a *StandardEWMA) fetchInstantRate() float64 { + count := a.uncounted.Swap(0) + return float64(count) / float64(5*time.Second) +} + +func (a *StandardEWMA) updateRate(instantRate float64) { + currentRate := math.Float64frombits(a.rate.Load()) + currentRate += a.alpha * (instantRate - currentRate) + a.rate.Store(math.Float64bits(currentRate)) }   // Update adds n uncounted events.
diff --git ethereum/go-ethereum/metrics/ewma_test.go taikoxyz/taiko-geth/metrics/ewma_test.go index 5b244191616e7cd8539175d0dd1e9f6e6a0caef1..9a91b43db81a4b499a5660477cb6b76a8b862701 100644 --- ethereum/go-ethereum/metrics/ewma_test.go +++ taikoxyz/taiko-geth/metrics/ewma_test.go @@ -5,6 +5,8 @@ "math" "testing" )   +const epsilon = 0.0000000000000001 + func BenchmarkEWMA(b *testing.B) { a := NewEWMA1() b.ResetTimer() @@ -14,72 +16,33 @@ a.Tick() } }   +func BenchmarkEWMAParallel(b *testing.B) { + a := NewEWMA1() + b.ResetTimer() + + b.RunParallel(func(pb *testing.PB) { + for pb.Next() { + a.Update(1) + a.Tick() + } + }) +} + func TestEWMA1(t *testing.T) { a := NewEWMA1() a.Update(3) a.Tick() - if rate := a.Rate(); math.Abs(0.6-rate) > epsilon { - t.Errorf("initial a.Rate(): 0.6 != %v\n", rate) - } - elapseMinute(a) - if rate := a.Rate(); math.Abs(0.22072766470286553-rate) > epsilon { - t.Errorf("1 minute a.Rate(): 0.22072766470286553 != %v\n", rate) - } - elapseMinute(a) - if rate := a.Rate(); math.Abs(0.08120116994196772-rate) > epsilon { - t.Errorf("2 minute a.Rate(): 0.08120116994196772 != %v\n", rate) - } - elapseMinute(a) - if rate := a.Rate(); math.Abs(0.029872241020718428-rate) > epsilon { - t.Errorf("3 minute a.Rate(): 0.029872241020718428 != %v\n", rate) - } - elapseMinute(a) - if rate := a.Rate(); math.Abs(0.01098938333324054-rate) > epsilon { - t.Errorf("4 minute a.Rate(): 0.01098938333324054 != %v\n", rate) - } - elapseMinute(a) - if rate := a.Rate(); math.Abs(0.004042768199451294-rate) > epsilon { - t.Errorf("5 minute a.Rate(): 0.004042768199451294 != %v\n", rate) - } - elapseMinute(a) - if rate := a.Rate(); math.Abs(0.0014872513059998212-rate) > epsilon { - t.Errorf("6 minute a.Rate(): 0.0014872513059998212 != %v\n", rate) - } - elapseMinute(a) - if rate := a.Rate(); math.Abs(0.0005471291793327122-rate) > epsilon { - t.Errorf("7 minute a.Rate(): 0.0005471291793327122 != %v\n", rate) - } - elapseMinute(a) - if rate := a.Rate(); math.Abs(0.00020127757674150815-rate) > epsilon { - t.Errorf("8 minute a.Rate(): 0.00020127757674150815 != %v\n", rate) - } - elapseMinute(a) - if rate := a.Rate(); math.Abs(7.404588245200814e-05-rate) > epsilon { - t.Errorf("9 minute a.Rate(): 7.404588245200814e-05 != %v\n", rate) - } - elapseMinute(a) - if rate := a.Rate(); math.Abs(2.7239957857491083e-05-rate) > epsilon { - t.Errorf("10 minute a.Rate(): 2.7239957857491083e-05 != %v\n", rate) - } - elapseMinute(a) - if rate := a.Rate(); math.Abs(1.0021020474147462e-05-rate) > epsilon { - t.Errorf("11 minute a.Rate(): 1.0021020474147462e-05 != %v\n", rate) - } - elapseMinute(a) - if rate := a.Rate(); math.Abs(3.6865274119969525e-06-rate) > epsilon { - t.Errorf("12 minute a.Rate(): 3.6865274119969525e-06 != %v\n", rate) - } - elapseMinute(a) - if rate := a.Rate(); math.Abs(1.3561976441886433e-06-rate) > epsilon { - t.Errorf("13 minute a.Rate(): 1.3561976441886433e-06 != %v\n", rate) - } - elapseMinute(a) - if rate := a.Rate(); math.Abs(4.989172314621449e-07-rate) > epsilon { - t.Errorf("14 minute a.Rate(): 4.989172314621449e-07 != %v\n", rate) - } - elapseMinute(a) - if rate := a.Rate(); math.Abs(1.8354139230109722e-07-rate) > epsilon { - t.Errorf("15 minute a.Rate(): 1.8354139230109722e-07 != %v\n", rate) + for i, want := range []float64{0.6, + 0.22072766470286553, 0.08120116994196772, 0.029872241020718428, + 0.01098938333324054, 0.004042768199451294, 0.0014872513059998212, + 0.0005471291793327122, 0.00020127757674150815, 7.404588245200814e-05, + 2.7239957857491083e-05, 1.0021020474147462e-05, 3.6865274119969525e-06, + 1.3561976441886433e-06, 4.989172314621449e-07, 1.8354139230109722e-07, + } { + if rate := a.Snapshot().Rate(); math.Abs(want-rate) > epsilon { + t.Errorf("%d minute a.Snapshot().Rate(): %f != %v\n", i, want, rate) + } + elapseMinute(a) } }   @@ -87,68 +50,17 @@ func TestEWMA5(t *testing.T) { a := NewEWMA5() a.Update(3) a.Tick() - if rate := a.Rate(); math.Abs(0.6-rate) > epsilon { - t.Errorf("initial a.Rate(): 0.6 != %v\n", rate) - } - elapseMinute(a) - if rate := a.Rate(); math.Abs(0.49123845184678905-rate) > epsilon { - t.Errorf("1 minute a.Rate(): 0.49123845184678905 != %v\n", rate) - } - elapseMinute(a) - if rate := a.Rate(); math.Abs(0.4021920276213837-rate) > epsilon { - t.Errorf("2 minute a.Rate(): 0.4021920276213837 != %v\n", rate) - } - elapseMinute(a) - if rate := a.Rate(); math.Abs(0.32928698165641596-rate) > epsilon { - t.Errorf("3 minute a.Rate(): 0.32928698165641596 != %v\n", rate) - } - elapseMinute(a) - if rate := a.Rate(); math.Abs(0.269597378470333-rate) > epsilon { - t.Errorf("4 minute a.Rate(): 0.269597378470333 != %v\n", rate) - } - elapseMinute(a) - if rate := a.Rate(); math.Abs(0.2207276647028654-rate) > epsilon { - t.Errorf("5 minute a.Rate(): 0.2207276647028654 != %v\n", rate) - } - elapseMinute(a) - if rate := a.Rate(); math.Abs(0.18071652714732128-rate) > epsilon { - t.Errorf("6 minute a.Rate(): 0.18071652714732128 != %v\n", rate) - } - elapseMinute(a) - if rate := a.Rate(); math.Abs(0.14795817836496392-rate) > epsilon { - t.Errorf("7 minute a.Rate(): 0.14795817836496392 != %v\n", rate) - } - elapseMinute(a) - if rate := a.Rate(); math.Abs(0.12113791079679326-rate) > epsilon { - t.Errorf("8 minute a.Rate(): 0.12113791079679326 != %v\n", rate) - } - elapseMinute(a) - if rate := a.Rate(); math.Abs(0.09917933293295193-rate) > epsilon { - t.Errorf("9 minute a.Rate(): 0.09917933293295193 != %v\n", rate) - } - elapseMinute(a) - if rate := a.Rate(); math.Abs(0.08120116994196763-rate) > epsilon { - t.Errorf("10 minute a.Rate(): 0.08120116994196763 != %v\n", rate) - } - elapseMinute(a) - if rate := a.Rate(); math.Abs(0.06648189501740036-rate) > epsilon { - t.Errorf("11 minute a.Rate(): 0.06648189501740036 != %v\n", rate) - } - elapseMinute(a) - if rate := a.Rate(); math.Abs(0.05443077197364752-rate) > epsilon { - t.Errorf("12 minute a.Rate(): 0.05443077197364752 != %v\n", rate) - } - elapseMinute(a) - if rate := a.Rate(); math.Abs(0.04456414692860035-rate) > epsilon { - t.Errorf("13 minute a.Rate(): 0.04456414692860035 != %v\n", rate) - } - elapseMinute(a) - if rate := a.Rate(); math.Abs(0.03648603757513079-rate) > epsilon { - t.Errorf("14 minute a.Rate(): 0.03648603757513079 != %v\n", rate) - } - elapseMinute(a) - if rate := a.Rate(); math.Abs(0.0298722410207183831020718428-rate) > epsilon { - t.Errorf("15 minute a.Rate(): 0.0298722410207183831020718428 != %v\n", rate) + for i, want := range []float64{ + 0.6, 0.49123845184678905, 0.4021920276213837, 0.32928698165641596, + 0.269597378470333, 0.2207276647028654, 0.18071652714732128, + 0.14795817836496392, 0.12113791079679326, 0.09917933293295193, + 0.08120116994196763, 0.06648189501740036, 0.05443077197364752, + 0.04456414692860035, 0.03648603757513079, 0.0298722410207183831020718428, + } { + if rate := a.Snapshot().Rate(); math.Abs(want-rate) > epsilon { + t.Errorf("%d minute a.Snapshot().Rate(): %f != %v\n", i, want, rate) + } + elapseMinute(a) } }   @@ -156,68 +68,17 @@ func TestEWMA15(t *testing.T) { a := NewEWMA15() a.Update(3) a.Tick() - if rate := a.Rate(); math.Abs(0.6-rate) > epsilon { - t.Errorf("initial a.Rate(): 0.6 != %v\n", rate) - } - elapseMinute(a) - if rate := a.Rate(); math.Abs(0.5613041910189706-rate) > epsilon { - t.Errorf("1 minute a.Rate(): 0.5613041910189706 != %v\n", rate) - } - elapseMinute(a) - if rate := a.Rate(); math.Abs(0.5251039914257684-rate) > epsilon { - t.Errorf("2 minute a.Rate(): 0.5251039914257684 != %v\n", rate) - } - elapseMinute(a) - if rate := a.Rate(); math.Abs(0.4912384518467888184678905-rate) > epsilon { - t.Errorf("3 minute a.Rate(): 0.4912384518467888184678905 != %v\n", rate) - } - elapseMinute(a) - if rate := a.Rate(); math.Abs(0.459557003018789-rate) > epsilon { - t.Errorf("4 minute a.Rate(): 0.459557003018789 != %v\n", rate) - } - elapseMinute(a) - if rate := a.Rate(); math.Abs(0.4299187863442732-rate) > epsilon { - t.Errorf("5 minute a.Rate(): 0.4299187863442732 != %v\n", rate) - } - elapseMinute(a) - if rate := a.Rate(); math.Abs(0.4021920276213831-rate) > epsilon { - t.Errorf("6 minute a.Rate(): 0.4021920276213831 != %v\n", rate) - } - elapseMinute(a) - if rate := a.Rate(); math.Abs(0.37625345116383313-rate) > epsilon { - t.Errorf("7 minute a.Rate(): 0.37625345116383313 != %v\n", rate) - } - elapseMinute(a) - if rate := a.Rate(); math.Abs(0.3519877317060185-rate) > epsilon { - t.Errorf("8 minute a.Rate(): 0.3519877317060185 != %v\n", rate) - } - elapseMinute(a) - if rate := a.Rate(); math.Abs(0.3292869816564153165641596-rate) > epsilon { - t.Errorf("9 minute a.Rate(): 0.3292869816564153165641596 != %v\n", rate) - } - elapseMinute(a) - if rate := a.Rate(); math.Abs(0.3080502714195546-rate) > epsilon { - t.Errorf("10 minute a.Rate(): 0.3080502714195546 != %v\n", rate) - } - elapseMinute(a) - if rate := a.Rate(); math.Abs(0.2881831806538789-rate) > epsilon { - t.Errorf("11 minute a.Rate(): 0.2881831806538789 != %v\n", rate) - } - elapseMinute(a) - if rate := a.Rate(); math.Abs(0.26959737847033216-rate) > epsilon { - t.Errorf("12 minute a.Rate(): 0.26959737847033216 != %v\n", rate) - } - elapseMinute(a) - if rate := a.Rate(); math.Abs(0.2522102307052083-rate) > epsilon { - t.Errorf("13 minute a.Rate(): 0.2522102307052083 != %v\n", rate) - } - elapseMinute(a) - if rate := a.Rate(); math.Abs(0.23594443252115815-rate) > epsilon { - t.Errorf("14 minute a.Rate(): 0.23594443252115815 != %v\n", rate) - } - elapseMinute(a) - if rate := a.Rate(); math.Abs(0.2207276647028646247028654470286553-rate) > epsilon { - t.Errorf("15 minute a.Rate(): 0.2207276647028646247028654470286553 != %v\n", rate) + for i, want := range []float64{ + 0.6, 0.5613041910189706, 0.5251039914257684, 0.4912384518467888184678905, + 0.459557003018789, 0.4299187863442732, 0.4021920276213831, + 0.37625345116383313, 0.3519877317060185, 0.3292869816564153165641596, + 0.3080502714195546, 0.2881831806538789, 0.26959737847033216, + 0.2522102307052083, 0.23594443252115815, 0.2207276647028646247028654470286553, + } { + if rate := a.Snapshot().Rate(); math.Abs(want-rate) > epsilon { + t.Errorf("%d minute a.Snapshot().Rate(): %f != %v\n", i, want, rate) + } + elapseMinute(a) } }
diff --git ethereum/go-ethereum/metrics/exp/exp.go taikoxyz/taiko-geth/metrics/exp/exp.go index 2b04eeab271f96167b8d95e858e79d54cfed49da..7e3f82a075fc3e384478350fae012dc4d128297c 100644 --- ethereum/go-ethereum/metrics/exp/exp.go +++ taikoxyz/taiko-geth/metrics/exp/exp.go @@ -95,24 +95,42 @@ exp.expvarLock.Unlock() return v }   -func (exp *exp) publishCounter(name string, metric metrics.Counter) { +func (exp *exp) getInfo(name string) *expvar.String { + var v *expvar.String + exp.expvarLock.Lock() + p := expvar.Get(name) + if p != nil { + v = p.(*expvar.String) + } else { + v = new(expvar.String) + expvar.Publish(name, v) + } + exp.expvarLock.Unlock() + return v +} + +func (exp *exp) publishCounter(name string, metric metrics.CounterSnapshot) { v := exp.getInt(name) v.Set(metric.Count()) }   -func (exp *exp) publishCounterFloat64(name string, metric metrics.CounterFloat64) { +func (exp *exp) publishCounterFloat64(name string, metric metrics.CounterFloat64Snapshot) { v := exp.getFloat(name) v.Set(metric.Count()) }   -func (exp *exp) publishGauge(name string, metric metrics.Gauge) { +func (exp *exp) publishGauge(name string, metric metrics.GaugeSnapshot) { v := exp.getInt(name) v.Set(metric.Value()) } -func (exp *exp) publishGaugeFloat64(name string, metric metrics.GaugeFloat64) { +func (exp *exp) publishGaugeFloat64(name string, metric metrics.GaugeFloat64Snapshot) { exp.getFloat(name).Set(metric.Value()) }   +func (exp *exp) publishGaugeInfo(name string, metric metrics.GaugeInfoSnapshot) { + exp.getInfo(name).Set(metric.Value().String()) +} + func (exp *exp) publishHistogram(name string, metric metrics.Histogram) { h := metric.Snapshot() ps := h.Percentiles([]float64{0.5, 0.75, 0.95, 0.99, 0.999}) @@ -158,26 +176,28 @@ }   func (exp *exp) publishResettingTimer(name string, metric metrics.ResettingTimer) { t := metric.Snapshot() - ps := t.Percentiles([]float64{50, 75, 95, 99}) - exp.getInt(name + ".count").Set(int64(len(t.Values()))) + ps := t.Percentiles([]float64{0.50, 0.75, 0.95, 0.99}) + exp.getInt(name + ".count").Set(int64(t.Count())) exp.getFloat(name + ".mean").Set(t.Mean()) - exp.getInt(name + ".50-percentile").Set(ps[0]) - exp.getInt(name + ".75-percentile").Set(ps[1]) - exp.getInt(name + ".95-percentile").Set(ps[2]) - exp.getInt(name + ".99-percentile").Set(ps[3]) + exp.getFloat(name + ".50-percentile").Set(ps[0]) + exp.getFloat(name + ".75-percentile").Set(ps[1]) + exp.getFloat(name + ".95-percentile").Set(ps[2]) + exp.getFloat(name + ".99-percentile").Set(ps[3]) }   func (exp *exp) syncToExpvar() { exp.registry.Each(func(name string, i interface{}) { switch i := i.(type) { case metrics.Counter: - exp.publishCounter(name, i) + exp.publishCounter(name, i.Snapshot()) case metrics.CounterFloat64: - exp.publishCounterFloat64(name, i) + exp.publishCounterFloat64(name, i.Snapshot()) case metrics.Gauge: - exp.publishGauge(name, i) + exp.publishGauge(name, i.Snapshot()) case metrics.GaugeFloat64: - exp.publishGaugeFloat64(name, i) + exp.publishGaugeFloat64(name, i.Snapshot()) + case metrics.GaugeInfo: + exp.publishGaugeInfo(name, i.Snapshot()) case metrics.Histogram: exp.publishHistogram(name, i) case metrics.Meter:
diff --git ethereum/go-ethereum/metrics/gauge.go taikoxyz/taiko-geth/metrics/gauge.go index 81137d7f7c5ea3ba77c1a83f8c64f579a2ea7a4e..68f8f11abcd74bc95652b840552612d3702e6c42 100644 --- ethereum/go-ethereum/metrics/gauge.go +++ taikoxyz/taiko-geth/metrics/gauge.go @@ -2,13 +2,18 @@ package metrics   import "sync/atomic"   +// gaugeSnapshot contains a readonly int64. +type GaugeSnapshot interface { + Value() int64 +} + // Gauges hold an int64 value that can be set arbitrarily. type Gauge interface { - Snapshot() Gauge + Snapshot() GaugeSnapshot Update(int64) + UpdateIfGt(int64) Dec(int64) Inc(int64) - Value() int64 }   // GetOrRegisterGauge returns an existing Gauge or constructs and registers a @@ -38,65 +43,20 @@ r.Register(name, c) return c }   -// NewFunctionalGauge constructs a new FunctionalGauge. -func NewFunctionalGauge(f func() int64) Gauge { - if !Enabled { - return NilGauge{} - } - return &FunctionalGauge{value: f} -} - -// NewRegisteredFunctionalGauge constructs and registers a new StandardGauge. -func NewRegisteredFunctionalGauge(name string, r Registry, f func() int64) Gauge { - c := NewFunctionalGauge(f) - if nil == r { - r = DefaultRegistry - } - r.Register(name, c) - return c -} - -// GaugeSnapshot is a read-only copy of another Gauge. -type GaugeSnapshot int64 - -// Snapshot returns the snapshot. -func (g GaugeSnapshot) Snapshot() Gauge { return g } - -// Update panics. -func (GaugeSnapshot) Update(int64) { - panic("Update called on a GaugeSnapshot") -} - -// Dec panics. -func (GaugeSnapshot) Dec(int64) { - panic("Dec called on a GaugeSnapshot") -} - -// Inc panics. -func (GaugeSnapshot) Inc(int64) { - panic("Inc called on a GaugeSnapshot") -} +// gaugeSnapshot is a read-only copy of another Gauge. +type gaugeSnapshot int64   // Value returns the value at the time the snapshot was taken. -func (g GaugeSnapshot) Value() int64 { return int64(g) } +func (g gaugeSnapshot) Value() int64 { return int64(g) }   // NilGauge is a no-op Gauge. type NilGauge struct{}   -// Snapshot is a no-op. -func (NilGauge) Snapshot() Gauge { return NilGauge{} } - -// Update is a no-op. -func (NilGauge) Update(v int64) {} - -// Dec is a no-op. -func (NilGauge) Dec(i int64) {} - -// Inc is a no-op. -func (NilGauge) Inc(i int64) {} - -// Value is a no-op. -func (NilGauge) Value() int64 { return 0 } +func (NilGauge) Snapshot() GaugeSnapshot { return (*emptySnapshot)(nil) } +func (NilGauge) Update(v int64) {} +func (NilGauge) UpdateIfGt(v int64) {} +func (NilGauge) Dec(i int64) {} +func (NilGauge) Inc(i int64) {}   // StandardGauge is the standard implementation of a Gauge and uses the // sync/atomic package to manage a single int64 value. @@ -105,8 +65,8 @@ value atomic.Int64 }   // Snapshot returns a read-only copy of the gauge. -func (g *StandardGauge) Snapshot() Gauge { - return GaugeSnapshot(g.Value()) +func (g *StandardGauge) Snapshot() GaugeSnapshot { + return gaugeSnapshot(g.value.Load()) }   // Update updates the gauge's value. @@ -114,9 +74,17 @@ func (g *StandardGauge) Update(v int64) { g.value.Store(v) }   -// Value returns the gauge's current value. -func (g *StandardGauge) Value() int64 { - return g.value.Load() +// Update updates the gauge's value if v is larger then the current valie. +func (g *StandardGauge) UpdateIfGt(v int64) { + for { + exist := g.value.Load() + if exist >= v { + break + } + if g.value.CompareAndSwap(exist, v) { + break + } + } }   // Dec decrements the gauge's current value by the given amount. @@ -128,31 +96,3 @@ // Inc increments the gauge's current value by the given amount. func (g *StandardGauge) Inc(i int64) { g.value.Add(i) } - -// FunctionalGauge returns value from given function -type FunctionalGauge struct { - value func() int64 -} - -// Value returns the gauge's current value. -func (g FunctionalGauge) Value() int64 { - return g.value() -} - -// Snapshot returns the snapshot. -func (g FunctionalGauge) Snapshot() Gauge { return GaugeSnapshot(g.Value()) } - -// Update panics. -func (FunctionalGauge) Update(int64) { - panic("Update called on a FunctionalGauge") -} - -// Dec panics. -func (FunctionalGauge) Dec(int64) { - panic("Dec called on a FunctionalGauge") -} - -// Inc panics. -func (FunctionalGauge) Inc(int64) { - panic("Inc called on a FunctionalGauge") -}
diff --git ethereum/go-ethereum/metrics/gauge_float64.go taikoxyz/taiko-geth/metrics/gauge_float64.go index 237ff8036e01445b8adfb73c221aba43537e1bb2..967f2bc60e5cf7c3773f04b7d70d8596848ae308 100644 --- ethereum/go-ethereum/metrics/gauge_float64.go +++ taikoxyz/taiko-geth/metrics/gauge_float64.go @@ -5,11 +5,14 @@ "math" "sync/atomic" )   -// GaugeFloat64s hold a float64 value that can be set arbitrarily. +type GaugeFloat64Snapshot interface { + Value() float64 +} + +// GaugeFloat64 hold a float64 value that can be set arbitrarily. type GaugeFloat64 interface { - Snapshot() GaugeFloat64 + Snapshot() GaugeFloat64Snapshot Update(float64) - Value() float64 }   // GetOrRegisterGaugeFloat64 returns an existing GaugeFloat64 or constructs and registers a @@ -39,49 +42,18 @@ r.Register(name, c) return c }   -// NewFunctionalGauge constructs a new FunctionalGauge. -func NewFunctionalGaugeFloat64(f func() float64) GaugeFloat64 { - if !Enabled { - return NilGaugeFloat64{} - } - return &FunctionalGaugeFloat64{value: f} -} - -// NewRegisteredFunctionalGauge constructs and registers a new StandardGauge. -func NewRegisteredFunctionalGaugeFloat64(name string, r Registry, f func() float64) GaugeFloat64 { - c := NewFunctionalGaugeFloat64(f) - if nil == r { - r = DefaultRegistry - } - r.Register(name, c) - return c -} - -// GaugeFloat64Snapshot is a read-only copy of another GaugeFloat64. -type GaugeFloat64Snapshot float64 - -// Snapshot returns the snapshot. -func (g GaugeFloat64Snapshot) Snapshot() GaugeFloat64 { return g } - -// Update panics. -func (GaugeFloat64Snapshot) Update(float64) { - panic("Update called on a GaugeFloat64Snapshot") -} +// gaugeFloat64Snapshot is a read-only copy of another GaugeFloat64. +type gaugeFloat64Snapshot float64   // Value returns the value at the time the snapshot was taken. -func (g GaugeFloat64Snapshot) Value() float64 { return float64(g) } +func (g gaugeFloat64Snapshot) Value() float64 { return float64(g) }   // NilGauge is a no-op Gauge. type NilGaugeFloat64 struct{}   -// Snapshot is a no-op. -func (NilGaugeFloat64) Snapshot() GaugeFloat64 { return NilGaugeFloat64{} } - -// Update is a no-op. -func (NilGaugeFloat64) Update(v float64) {} - -// Value is a no-op. -func (NilGaugeFloat64) Value() float64 { return 0.0 } +func (NilGaugeFloat64) Snapshot() GaugeFloat64Snapshot { return NilGaugeFloat64{} } +func (NilGaugeFloat64) Update(v float64) {} +func (NilGaugeFloat64) Value() float64 { return 0.0 }   // StandardGaugeFloat64 is the standard implementation of a GaugeFloat64 and uses // atomic to manage a single float64 value. @@ -90,34 +62,12 @@ floatBits atomic.Uint64 }   // Snapshot returns a read-only copy of the gauge. -func (g *StandardGaugeFloat64) Snapshot() GaugeFloat64 { - return GaugeFloat64Snapshot(g.Value()) +func (g *StandardGaugeFloat64) Snapshot() GaugeFloat64Snapshot { + v := math.Float64frombits(g.floatBits.Load()) + return gaugeFloat64Snapshot(v) }   // Update updates the gauge's value. func (g *StandardGaugeFloat64) Update(v float64) { g.floatBits.Store(math.Float64bits(v)) } - -// Value returns the gauge's current value. -func (g *StandardGaugeFloat64) Value() float64 { - return math.Float64frombits(g.floatBits.Load()) -} - -// FunctionalGaugeFloat64 returns value from given function -type FunctionalGaugeFloat64 struct { - value func() float64 -} - -// Value returns the gauge's current value. -func (g FunctionalGaugeFloat64) Value() float64 { - return g.value() -} - -// Snapshot returns the snapshot. -func (g FunctionalGaugeFloat64) Snapshot() GaugeFloat64 { return GaugeFloat64Snapshot(g.Value()) } - -// Update panics. -func (FunctionalGaugeFloat64) Update(float64) { - panic("Update called on a FunctionalGaugeFloat64") -}
diff --git ethereum/go-ethereum/metrics/gauge_float64_test.go taikoxyz/taiko-geth/metrics/gauge_float64_test.go index 647d09000935bb47a181095d46b24d0db8ee8d93..f0ac7ea5e7be0ad1f550ba05098f5916bbf6e341 100644 --- ethereum/go-ethereum/metrics/gauge_float64_test.go +++ taikoxyz/taiko-geth/metrics/gauge_float64_test.go @@ -26,16 +26,8 @@ wg.Done() }() } wg.Wait() - if have, want := c.Value(), float64(b.N-1); have != want { + if have, want := c.Snapshot().Value(), float64(b.N-1); have != want { b.Fatalf("have %f want %f", have, want) - } -} - -func TestGaugeFloat64(t *testing.T) { - g := NewGaugeFloat64() - g.Update(47.0) - if v := g.Value(); 47.0 != v { - t.Errorf("g.Value(): 47.0 != %v\n", v) } }   @@ -53,28 +45,7 @@ func TestGetOrRegisterGaugeFloat64(t *testing.T) { r := NewRegistry() NewRegisteredGaugeFloat64("foo", r).Update(47.0) t.Logf("registry: %v", r) - if g := GetOrRegisterGaugeFloat64("foo", r); 47.0 != g.Value() { - t.Fatal(g) - } -} - -func TestFunctionalGaugeFloat64(t *testing.T) { - var counter float64 - fg := NewFunctionalGaugeFloat64(func() float64 { - counter++ - return counter - }) - fg.Value() - fg.Value() - if counter != 2 { - t.Error("counter != 2") - } -} - -func TestGetOrRegisterFunctionalGaugeFloat64(t *testing.T) { - r := NewRegistry() - NewRegisteredFunctionalGaugeFloat64("foo", r, func() float64 { return 47 }) - if g := GetOrRegisterGaugeFloat64("foo", r); g.Value() != 47 { + if g := GetOrRegisterGaugeFloat64("foo", r).Snapshot(); 47.0 != g.Value() { t.Fatal(g) } }
diff --git ethereum/go-ethereum/metrics/gauge_info.go taikoxyz/taiko-geth/metrics/gauge_info.go new file mode 100644 index 0000000000000000000000000000000000000000..c44b2d85f3ad6565da374ac73c09b18131510da8 --- /dev/null +++ taikoxyz/taiko-geth/metrics/gauge_info.go @@ -0,0 +1,84 @@ +package metrics + +import ( + "encoding/json" + "sync" +) + +type GaugeInfoSnapshot interface { + Value() GaugeInfoValue +} + +// GaugeInfos hold a GaugeInfoValue value that can be set arbitrarily. +type GaugeInfo interface { + Update(GaugeInfoValue) + Snapshot() GaugeInfoSnapshot +} + +// GaugeInfoValue is a mapping of keys to values +type GaugeInfoValue map[string]string + +func (val GaugeInfoValue) String() string { + data, _ := json.Marshal(val) + return string(data) +} + +// GetOrRegisterGaugeInfo returns an existing GaugeInfo or constructs and registers a +// new StandardGaugeInfo. +func GetOrRegisterGaugeInfo(name string, r Registry) GaugeInfo { + if nil == r { + r = DefaultRegistry + } + return r.GetOrRegister(name, NewGaugeInfo()).(GaugeInfo) +} + +// NewGaugeInfo constructs a new StandardGaugeInfo. +func NewGaugeInfo() GaugeInfo { + if !Enabled { + return NilGaugeInfo{} + } + return &StandardGaugeInfo{ + value: GaugeInfoValue{}, + } +} + +// NewRegisteredGaugeInfo constructs and registers a new StandardGaugeInfo. +func NewRegisteredGaugeInfo(name string, r Registry) GaugeInfo { + c := NewGaugeInfo() + if nil == r { + r = DefaultRegistry + } + r.Register(name, c) + return c +} + +// gaugeInfoSnapshot is a read-only copy of another GaugeInfo. +type gaugeInfoSnapshot GaugeInfoValue + +// Value returns the value at the time the snapshot was taken. +func (g gaugeInfoSnapshot) Value() GaugeInfoValue { return GaugeInfoValue(g) } + +type NilGaugeInfo struct{} + +func (NilGaugeInfo) Snapshot() GaugeInfoSnapshot { return NilGaugeInfo{} } +func (NilGaugeInfo) Update(v GaugeInfoValue) {} +func (NilGaugeInfo) Value() GaugeInfoValue { return GaugeInfoValue{} } + +// StandardGaugeInfo is the standard implementation of a GaugeInfo and uses +// sync.Mutex to manage a single string value. +type StandardGaugeInfo struct { + mutex sync.Mutex + value GaugeInfoValue +} + +// Snapshot returns a read-only copy of the gauge. +func (g *StandardGaugeInfo) Snapshot() GaugeInfoSnapshot { + return gaugeInfoSnapshot(g.value) +} + +// Update updates the gauge's value. +func (g *StandardGaugeInfo) Update(v GaugeInfoValue) { + g.mutex.Lock() + defer g.mutex.Unlock() + g.value = v +}
diff --git ethereum/go-ethereum/metrics/gauge_info_test.go taikoxyz/taiko-geth/metrics/gauge_info_test.go new file mode 100644 index 0000000000000000000000000000000000000000..319afbf92e8f3284050c133a51e7cd9984a806b0 --- /dev/null +++ taikoxyz/taiko-geth/metrics/gauge_info_test.go @@ -0,0 +1,36 @@ +package metrics + +import ( + "testing" +) + +func TestGaugeInfoJsonString(t *testing.T) { + g := NewGaugeInfo() + g.Update(GaugeInfoValue{ + "chain_id": "5", + "anotherKey": "any_string_value", + "third_key": "anything", + }, + ) + want := `{"anotherKey":"any_string_value","chain_id":"5","third_key":"anything"}` + + original := g.Snapshot() + g.Update(GaugeInfoValue{"value": "updated"}) + + if have := original.Value().String(); have != want { + t.Errorf("\nhave: %v\nwant: %v\n", have, want) + } + if have, want := g.Snapshot().Value().String(), `{"value":"updated"}`; have != want { + t.Errorf("\nhave: %v\nwant: %v\n", have, want) + } +} + +func TestGetOrRegisterGaugeInfo(t *testing.T) { + r := NewRegistry() + NewRegisteredGaugeInfo("foo", r).Update( + GaugeInfoValue{"chain_id": "5"}) + g := GetOrRegisterGaugeInfo("foo", r).Snapshot() + if have, want := g.Value().String(), `{"chain_id":"5"}`; have != want { + t.Errorf("have\n%v\nwant\n%v\n", have, want) + } +}
diff --git ethereum/go-ethereum/metrics/gauge_test.go taikoxyz/taiko-geth/metrics/gauge_test.go index a98fe985d8c280696dec6151e59253c46551efbf..f2ba930bc465993cf2aea611197eae9deccc0bcc 100644 --- ethereum/go-ethereum/metrics/gauge_test.go +++ taikoxyz/taiko-geth/metrics/gauge_test.go @@ -1,7 +1,6 @@ package metrics   import ( - "fmt" "testing" )   @@ -13,14 +12,6 @@ g.Update(int64(i)) } }   -func TestGauge(t *testing.T) { - g := NewGauge() - g.Update(int64(47)) - if v := g.Value(); v != 47 { - t.Errorf("g.Value(): 47 != %v\n", v) - } -} - func TestGaugeSnapshot(t *testing.T) { g := NewGauge() g.Update(int64(47)) @@ -34,35 +25,7 @@ func TestGetOrRegisterGauge(t *testing.T) { r := NewRegistry() NewRegisteredGauge("foo", r).Update(47) - if g := GetOrRegisterGauge("foo", r); g.Value() != 47 { + if g := GetOrRegisterGauge("foo", r); g.Snapshot().Value() != 47 { t.Fatal(g) } } - -func TestFunctionalGauge(t *testing.T) { - var counter int64 - fg := NewFunctionalGauge(func() int64 { - counter++ - return counter - }) - fg.Value() - fg.Value() - if counter != 2 { - t.Error("counter != 2") - } -} - -func TestGetOrRegisterFunctionalGauge(t *testing.T) { - r := NewRegistry() - NewRegisteredFunctionalGauge("foo", r, func() int64 { return 47 }) - if g := GetOrRegisterGauge("foo", r); g.Value() != 47 { - t.Fatal(g) - } -} - -func ExampleGetOrRegisterGauge() { - m := "server.bytes_sent" - g := GetOrRegisterGauge(m, nil) - g.Update(47) - fmt.Println(g.Value()) // Output: 47 -}
diff --git ethereum/go-ethereum/metrics/graphite.go taikoxyz/taiko-geth/metrics/graphite.go index 29f72b0c4181109f4a4c5b98d707b9f3db8986a2..aba752e0ed5eae6ef0e5aae4d44042d4e664ea86 100644 --- ethereum/go-ethereum/metrics/graphite.go +++ taikoxyz/taiko-geth/metrics/graphite.go @@ -66,13 +66,15 @@ w := bufio.NewWriter(conn) c.Registry.Each(func(name string, i interface{}) { switch metric := i.(type) { case Counter: - fmt.Fprintf(w, "%s.%s.count %d %d\n", c.Prefix, name, metric.Count(), now) + fmt.Fprintf(w, "%s.%s.count %d %d\n", c.Prefix, name, metric.Snapshot().Count(), now) case CounterFloat64: - fmt.Fprintf(w, "%s.%s.count %f %d\n", c.Prefix, name, metric.Count(), now) + fmt.Fprintf(w, "%s.%s.count %f %d\n", c.Prefix, name, metric.Snapshot().Count(), now) case Gauge: - fmt.Fprintf(w, "%s.%s.value %d %d\n", c.Prefix, name, metric.Value(), now) + fmt.Fprintf(w, "%s.%s.value %d %d\n", c.Prefix, name, metric.Snapshot().Value(), now) case GaugeFloat64: - fmt.Fprintf(w, "%s.%s.value %f %d\n", c.Prefix, name, metric.Value(), now) + fmt.Fprintf(w, "%s.%s.value %f %d\n", c.Prefix, name, metric.Snapshot().Value(), now) + case GaugeInfo: + fmt.Fprintf(w, "%s.%s.value %s %d\n", c.Prefix, name, metric.Snapshot().Value().String(), now) case Histogram: h := metric.Snapshot() ps := h.Percentiles(c.Percentiles)
diff --git ethereum/go-ethereum/metrics/histogram.go taikoxyz/taiko-geth/metrics/histogram.go index 2c54ce8b4063e06109bd07868ed54b7e8dbd2aa3..44de588bc1dc8b03d5c4221eff2de593627d3a81 100644 --- ethereum/go-ethereum/metrics/histogram.go +++ taikoxyz/taiko-geth/metrics/histogram.go @@ -1,20 +1,14 @@ package metrics   +type HistogramSnapshot interface { + SampleSnapshot +} + // Histograms calculate distribution statistics from a series of int64 values. type Histogram interface { Clear() - Count() int64 - Max() int64 - Mean() float64 - Min() int64 - Percentile(float64) float64 - Percentiles([]float64) []float64 - Sample() Sample - Snapshot() Histogram - StdDev() float64 - Sum() int64 Update(int64) - Variance() float64 + Snapshot() HistogramSnapshot }   // GetOrRegisterHistogram returns an existing Histogram or constructs and @@ -54,108 +48,12 @@ r.Register(name, c) return c }   -// HistogramSnapshot is a read-only copy of another Histogram. -type HistogramSnapshot struct { - sample *SampleSnapshot -} - -// Clear panics. -func (*HistogramSnapshot) Clear() { - panic("Clear called on a HistogramSnapshot") -} - -// Count returns the number of samples recorded at the time the snapshot was -// taken. -func (h *HistogramSnapshot) Count() int64 { return h.sample.Count() } - -// Max returns the maximum value in the sample at the time the snapshot was -// taken. -func (h *HistogramSnapshot) Max() int64 { return h.sample.Max() } - -// Mean returns the mean of the values in the sample at the time the snapshot -// was taken. -func (h *HistogramSnapshot) Mean() float64 { return h.sample.Mean() } - -// Min returns the minimum value in the sample at the time the snapshot was -// taken. -func (h *HistogramSnapshot) Min() int64 { return h.sample.Min() } - -// Percentile returns an arbitrary percentile of values in the sample at the -// time the snapshot was taken. -func (h *HistogramSnapshot) Percentile(p float64) float64 { - return h.sample.Percentile(p) -} - -// Percentiles returns a slice of arbitrary percentiles of values in the sample -// at the time the snapshot was taken. -func (h *HistogramSnapshot) Percentiles(ps []float64) []float64 { - return h.sample.Percentiles(ps) -} - -// Sample returns the Sample underlying the histogram. -func (h *HistogramSnapshot) Sample() Sample { return h.sample } - -// Snapshot returns the snapshot. -func (h *HistogramSnapshot) Snapshot() Histogram { return h } - -// StdDev returns the standard deviation of the values in the sample at the -// time the snapshot was taken. -func (h *HistogramSnapshot) StdDev() float64 { return h.sample.StdDev() } - -// Sum returns the sum in the sample at the time the snapshot was taken. -func (h *HistogramSnapshot) Sum() int64 { return h.sample.Sum() } - -// Update panics. -func (*HistogramSnapshot) Update(int64) { - panic("Update called on a HistogramSnapshot") -} - -// Variance returns the variance of inputs at the time the snapshot was taken. -func (h *HistogramSnapshot) Variance() float64 { return h.sample.Variance() } - // NilHistogram is a no-op Histogram. type NilHistogram struct{}   -// Clear is a no-op. -func (NilHistogram) Clear() {} - -// Count is a no-op. -func (NilHistogram) Count() int64 { return 0 } - -// Max is a no-op. -func (NilHistogram) Max() int64 { return 0 } - -// Mean is a no-op. -func (NilHistogram) Mean() float64 { return 0.0 } - -// Min is a no-op. -func (NilHistogram) Min() int64 { return 0 } - -// Percentile is a no-op. -func (NilHistogram) Percentile(p float64) float64 { return 0.0 } - -// Percentiles is a no-op. -func (NilHistogram) Percentiles(ps []float64) []float64 { - return make([]float64, len(ps)) -} - -// Sample is a no-op. -func (NilHistogram) Sample() Sample { return NilSample{} } - -// Snapshot is a no-op. -func (NilHistogram) Snapshot() Histogram { return NilHistogram{} } - -// StdDev is a no-op. -func (NilHistogram) StdDev() float64 { return 0.0 } - -// Sum is a no-op. -func (NilHistogram) Sum() int64 { return 0 } - -// Update is a no-op. -func (NilHistogram) Update(v int64) {} - -// Variance is a no-op. -func (NilHistogram) Variance() float64 { return 0.0 } +func (NilHistogram) Clear() {} +func (NilHistogram) Snapshot() HistogramSnapshot { return (*emptySnapshot)(nil) } +func (NilHistogram) Update(v int64) {}   // StandardHistogram is the standard implementation of a Histogram and uses a // Sample to bound its memory use. @@ -166,46 +64,10 @@ // Clear clears the histogram and its sample. func (h *StandardHistogram) Clear() { h.sample.Clear() }   -// Count returns the number of samples recorded since the histogram was last -// cleared. -func (h *StandardHistogram) Count() int64 { return h.sample.Count() } - -// Max returns the maximum value in the sample. -func (h *StandardHistogram) Max() int64 { return h.sample.Max() } - -// Mean returns the mean of the values in the sample. -func (h *StandardHistogram) Mean() float64 { return h.sample.Mean() } - -// Min returns the minimum value in the sample. -func (h *StandardHistogram) Min() int64 { return h.sample.Min() } - -// Percentile returns an arbitrary percentile of the values in the sample. -func (h *StandardHistogram) Percentile(p float64) float64 { - return h.sample.Percentile(p) -} - -// Percentiles returns a slice of arbitrary percentiles of the values in the -// sample. -func (h *StandardHistogram) Percentiles(ps []float64) []float64 { - return h.sample.Percentiles(ps) -} - -// Sample returns the Sample underlying the histogram. -func (h *StandardHistogram) Sample() Sample { return h.sample } - // Snapshot returns a read-only copy of the histogram. -func (h *StandardHistogram) Snapshot() Histogram { - return &HistogramSnapshot{sample: h.sample.Snapshot().(*SampleSnapshot)} +func (h *StandardHistogram) Snapshot() HistogramSnapshot { + return h.sample.Snapshot() }   -// StdDev returns the standard deviation of the values in the sample. -func (h *StandardHistogram) StdDev() float64 { return h.sample.StdDev() } - -// Sum returns the sum in the sample. -func (h *StandardHistogram) Sum() int64 { return h.sample.Sum() } - // Update samples a new value. func (h *StandardHistogram) Update(v int64) { h.sample.Update(v) } - -// Variance returns the variance of the values in the sample. -func (h *StandardHistogram) Variance() float64 { return h.sample.Variance() }
diff --git ethereum/go-ethereum/metrics/histogram_test.go taikoxyz/taiko-geth/metrics/histogram_test.go index 7c9f42fcec962904eb5c53b1eb3eedc5c3d0e887..22fc5468b0b5dc1697d4650b384448f6229046b5 100644 --- ethereum/go-ethereum/metrics/histogram_test.go +++ taikoxyz/taiko-geth/metrics/histogram_test.go @@ -14,7 +14,7 @@ func TestGetOrRegisterHistogram(t *testing.T) { r := NewRegistry() s := NewUniformSample(100) NewRegisteredHistogram("foo", r, s).Update(47) - if h := GetOrRegisterHistogram("foo", r, s); h.Count() != 1 { + if h := GetOrRegisterHistogram("foo", r, s).Snapshot(); h.Count() != 1 { t.Fatal(h) } } @@ -24,11 +24,11 @@ h := NewHistogram(NewUniformSample(100000)) for i := 1; i <= 10000; i++ { h.Update(int64(i)) } - testHistogram10000(t, h) + testHistogram10000(t, h.Snapshot()) }   func TestHistogramEmpty(t *testing.T) { - h := NewHistogram(NewUniformSample(100)) + h := NewHistogram(NewUniformSample(100)).Snapshot() if count := h.Count(); count != 0 { t.Errorf("h.Count(): 0 != %v\n", count) } @@ -66,7 +66,7 @@ h.Update(0) testHistogram10000(t, snapshot) }   -func testHistogram10000(t *testing.T, h Histogram) { +func testHistogram10000(t *testing.T, h HistogramSnapshot) { if count := h.Count(); count != 10000 { t.Errorf("h.Count(): 10000 != %v\n", count) }
diff --git ethereum/go-ethereum/metrics/inactive.go taikoxyz/taiko-geth/metrics/inactive.go new file mode 100644 index 0000000000000000000000000000000000000000..1f47f0210af30ddc0fe5c550901e33cdc39b3dea --- /dev/null +++ taikoxyz/taiko-geth/metrics/inactive.go @@ -0,0 +1,48 @@ +// Copyright 2023 The go-ethereum Authors +// This file is part of the go-ethereum library. +// +// The go-ethereum library is free software: you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// The go-ethereum library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>. + +package metrics + +// compile-time checks that interfaces are implemented. +var ( + _ SampleSnapshot = (*emptySnapshot)(nil) + _ HistogramSnapshot = (*emptySnapshot)(nil) + _ CounterSnapshot = (*emptySnapshot)(nil) + _ GaugeSnapshot = (*emptySnapshot)(nil) + _ MeterSnapshot = (*emptySnapshot)(nil) + _ EWMASnapshot = (*emptySnapshot)(nil) + _ TimerSnapshot = (*emptySnapshot)(nil) +) + +type emptySnapshot struct{} + +func (*emptySnapshot) Count() int64 { return 0 } +func (*emptySnapshot) Max() int64 { return 0 } +func (*emptySnapshot) Mean() float64 { return 0.0 } +func (*emptySnapshot) Min() int64 { return 0 } +func (*emptySnapshot) Percentile(p float64) float64 { return 0.0 } +func (*emptySnapshot) Percentiles(ps []float64) []float64 { return make([]float64, len(ps)) } +func (*emptySnapshot) Size() int { return 0 } +func (*emptySnapshot) StdDev() float64 { return 0.0 } +func (*emptySnapshot) Sum() int64 { return 0 } +func (*emptySnapshot) Values() []int64 { return []int64{} } +func (*emptySnapshot) Variance() float64 { return 0.0 } +func (*emptySnapshot) Value() int64 { return 0 } +func (*emptySnapshot) Rate() float64 { return 0.0 } +func (*emptySnapshot) Rate1() float64 { return 0.0 } +func (*emptySnapshot) Rate5() float64 { return 0.0 } +func (*emptySnapshot) Rate15() float64 { return 0.0 } +func (*emptySnapshot) RateMean() float64 { return 0.0 }
diff --git ethereum/go-ethereum/metrics/influxdb/influxdb.go taikoxyz/taiko-geth/metrics/influxdb/influxdb.go index 5dfbbab3edeb6b4ad2271e93c617e8ddbac41ce5..bbc4fc024b34fe6df61f64871a42efa2e7ffdab7 100644 --- ethereum/go-ethereum/metrics/influxdb/influxdb.go +++ taikoxyz/taiko-geth/metrics/influxdb/influxdb.go @@ -11,13 +11,13 @@ switch metric := i.(type) { case metrics.Counter: measurement := fmt.Sprintf("%s%s.count", namespace, name) fields := map[string]interface{}{ - "value": metric.Count(), + "value": metric.Snapshot().Count(), } return measurement, fields case metrics.CounterFloat64: measurement := fmt.Sprintf("%s%s.count", namespace, name) fields := map[string]interface{}{ - "value": metric.Count(), + "value": metric.Snapshot().Count(), } return measurement, fields case metrics.Gauge: @@ -30,6 +30,13 @@ case metrics.GaugeFloat64: measurement := fmt.Sprintf("%s%s.gauge", namespace, name) fields := map[string]interface{}{ "value": metric.Snapshot().Value(), + } + return measurement, fields + case metrics.GaugeInfo: + ms := metric.Snapshot() + measurement := fmt.Sprintf("%s%s.gauge", namespace, name) + fields := map[string]interface{}{ + "value": ms.Value().String(), } return measurement, fields case metrics.Histogram: @@ -92,20 +99,19 @@ } return measurement, fields case metrics.ResettingTimer: t := metric.Snapshot() - if len(t.Values()) == 0 { + if t.Count() == 0 { break } - ps := t.Percentiles([]float64{50, 95, 99}) - val := t.Values() + ps := t.Percentiles([]float64{0.50, 0.95, 0.99}) measurement := fmt.Sprintf("%s%s.span", namespace, name) fields := map[string]interface{}{ - "count": len(val), - "max": val[len(val)-1], + "count": t.Count(), + "max": t.Max(), "mean": t.Mean(), - "min": val[0], - "p50": ps[0], - "p95": ps[1], - "p99": ps[2], + "min": t.Min(), + "p50": int(ps[0]), + "p95": int(ps[1]), + "p99": int(ps[2]), } return measurement, fields }
diff --git ethereum/go-ethereum/metrics/influxdb/influxdb_test.go taikoxyz/taiko-geth/metrics/influxdb/influxdb_test.go new file mode 100644 index 0000000000000000000000000000000000000000..c6f2eeac62771186603424165133a5dc884a8f8d --- /dev/null +++ taikoxyz/taiko-geth/metrics/influxdb/influxdb_test.go @@ -0,0 +1,114 @@ +// Copyright 2023 The go-ethereum Authors +// This file is part of the go-ethereum library. +// +// The go-ethereum library is free software: you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// The go-ethereum library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>. + +package influxdb + +import ( + "fmt" + "io" + "net/http" + "net/http/httptest" + "net/url" + "os" + "strings" + "testing" + + "github.com/ethereum/go-ethereum/metrics" + "github.com/ethereum/go-ethereum/metrics/internal" + influxdb2 "github.com/influxdata/influxdb-client-go/v2" +) + +func TestMain(m *testing.M) { + metrics.Enabled = true + os.Exit(m.Run()) +} + +func TestExampleV1(t *testing.T) { + r := internal.ExampleMetrics() + var have, want string + ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + haveB, _ := io.ReadAll(r.Body) + have = string(haveB) + r.Body.Close() + })) + defer ts.Close() + u, _ := url.Parse(ts.URL) + rep := &reporter{ + reg: r, + url: *u, + namespace: "goth.", + } + if err := rep.makeClient(); err != nil { + t.Fatal(err) + } + if err := rep.send(978307200); err != nil { + t.Fatal(err) + } + if wantB, err := os.ReadFile("./testdata/influxdbv1.want"); err != nil { + t.Fatal(err) + } else { + want = string(wantB) + } + if have != want { + t.Errorf("\nhave:\n%v\nwant:\n%v\n", have, want) + t.Logf("have vs want:\n%v", findFirstDiffPos(have, want)) + } +} + +func TestExampleV2(t *testing.T) { + r := internal.ExampleMetrics() + var have, want string + ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + haveB, _ := io.ReadAll(r.Body) + have = string(haveB) + r.Body.Close() + })) + defer ts.Close() + + rep := &v2Reporter{ + reg: r, + endpoint: ts.URL, + namespace: "goth.", + } + rep.client = influxdb2.NewClient(rep.endpoint, rep.token) + defer rep.client.Close() + rep.write = rep.client.WriteAPI(rep.organization, rep.bucket) + + rep.send(978307200) + + if wantB, err := os.ReadFile("./testdata/influxdbv2.want"); err != nil { + t.Fatal(err) + } else { + want = string(wantB) + } + if have != want { + t.Errorf("\nhave:\n%v\nwant:\n%v\n", have, want) + t.Logf("have vs want:\n%v", findFirstDiffPos(have, want)) + } +} + +func findFirstDiffPos(a, b string) string { + yy := strings.Split(b, "\n") + for i, x := range strings.Split(a, "\n") { + if i >= len(yy) { + return fmt.Sprintf("have:%d: %s\nwant:%d: <EOF>", i, x, i) + } + if y := yy[i]; x != y { + return fmt.Sprintf("have:%d: %s\nwant:%d: %s", i, x, i, y) + } + } + return "" +}
diff --git ethereum/go-ethereum/metrics/influxdb/influxdbv1.go taikoxyz/taiko-geth/metrics/influxdb/influxdbv1.go index f65d30ef959097cab6530f46acc5694a0e4e86b0..ac58280803bb16eb425538fee57f073f829661a2 100644 --- ethereum/go-ethereum/metrics/influxdb/influxdbv1.go +++ taikoxyz/taiko-geth/metrics/influxdb/influxdbv1.go @@ -79,7 +79,7 @@ if err := rep.makeClient(); err != nil { return fmt.Errorf("unable to make InfluxDB client. err: %v", err) }   - if err := rep.send(); err != nil { + if err := rep.send(0); err != nil { return fmt.Errorf("unable to send to InfluxDB. err: %v", err) }   @@ -107,7 +107,7 @@ for { select { case <-intervalTicker.C: - if err := r.send(); err != nil { + if err := r.send(0); err != nil { log.Warn("Unable to send to InfluxDB", "err", err) } case <-pingTicker.C: @@ -123,7 +123,9 @@ } } }   -func (r *reporter) send() error { +// send sends the measurements. If provided tstamp is >0, it is used. Otherwise, +// a 'fresh' timestamp is used. +func (r *reporter) send(tstamp int64) error { bps, err := client.NewBatchPoints( client.BatchPointsConfig{ Database: r.database, @@ -132,7 +134,12 @@ if err != nil { return err } r.reg.Each(func(name string, i interface{}) { - now := time.Now() + var now time.Time + if tstamp <= 0 { + now = time.Now() + } else { + now = time.Unix(tstamp, 0) + } measurement, fields := readMeter(r.namespace, name, i) if fields == nil { return
diff --git ethereum/go-ethereum/metrics/influxdb/influxdbv2.go taikoxyz/taiko-geth/metrics/influxdb/influxdbv2.go index 7984898f32594c5481a69032083aec1c94fabbea..0be5137d5ee14b0d3575e378138adb4b5811247e 100644 --- ethereum/go-ethereum/metrics/influxdb/influxdbv2.go +++ taikoxyz/taiko-geth/metrics/influxdb/influxdbv2.go @@ -64,7 +64,7 @@ for { select { case <-intervalTicker.C: - r.send() + r.send(0) case <-pingTicker.C: _, err := r.client.Health(context.Background()) if err != nil { @@ -74,9 +74,16 @@ } } }   -func (r *v2Reporter) send() { +// send sends the measurements. If provided tstamp is >0, it is used. Otherwise, +// a 'fresh' timestamp is used. +func (r *v2Reporter) send(tstamp int64) { r.reg.Each(func(name string, i interface{}) { - now := time.Now() + var now time.Time + if tstamp <= 0 { + now = time.Now() + } else { + now = time.Unix(tstamp, 0) + } measurement, fields := readMeter(r.namespace, name, i) if fields == nil { return
diff --git ethereum/go-ethereum/metrics/influxdb/testdata/influxdbv1.want taikoxyz/taiko-geth/metrics/influxdb/testdata/influxdbv1.want new file mode 100644 index 0000000000000000000000000000000000000000..9443faedc5a2b3d3b5726670c7ecc126756fba2b --- /dev/null +++ taikoxyz/taiko-geth/metrics/influxdb/testdata/influxdbv1.want @@ -0,0 +1,11 @@ +goth.system/cpu/schedlatency.histogram count=5645i,max=41943040i,mean=1819544.0410983171,min=0i,p25=0,p50=0,p75=7168,p95=16777216,p99=29360128,p999=33554432,p9999=33554432,stddev=6393570.217198883,variance=40877740122252.57 978307200000000000 +goth.system/memory/pauses.histogram count=14i,max=229376i,mean=50066.28571428572,min=5120i,p25=10240,p50=32768,p75=57344,p95=196608,p99=196608,p999=196608,p9999=196608,stddev=54726.062410783874,variance=2994941906.9890113 978307200000000000 +goth.test/counter.count value=12345 978307200000000000 +goth.test/counter_float64.count value=54321.98 978307200000000000 +goth.test/gauge.gauge value=23456i 978307200000000000 +goth.test/gauge_float64.gauge value=34567.89 978307200000000000 +goth.test/gauge_info.gauge value="{\"arch\":\"amd64\",\"commit\":\"7caa2d8163ae3132c1c2d6978c76610caee2d949\",\"os\":\"linux\",\"protocol_versions\":\"64 65 66\",\"version\":\"1.10.18-unstable\"}" 978307200000000000 +goth.test/histogram.histogram count=3i,max=3i,mean=2,min=1i,p25=1,p50=2,p75=3,p95=3,p99=3,p999=3,p9999=3,stddev=0.816496580927726,variance=0.6666666666666666 978307200000000000 +goth.test/meter.meter count=0i,m1=0,m15=0,m5=0,mean=0 978307200000000000 +goth.test/resetting_timer.span count=6i,max=120000000i,mean=30000000,min=10000000i,p50=12500000i,p95=120000000i,p99=120000000i 978307200000000000 +goth.test/timer.timer count=6i,m1=0,m15=0,m5=0,max=120000000i,mean=38333333.333333336,meanrate=0,min=20000000i,p50=22500000,p75=48000000,p95=120000000,p99=120000000,p999=120000000,p9999=120000000,stddev=36545253.529775314,variance=1335555555555555.2 978307200000000000
diff --git ethereum/go-ethereum/metrics/influxdb/testdata/influxdbv2.want taikoxyz/taiko-geth/metrics/influxdb/testdata/influxdbv2.want new file mode 100644 index 0000000000000000000000000000000000000000..9443faedc5a2b3d3b5726670c7ecc126756fba2b --- /dev/null +++ taikoxyz/taiko-geth/metrics/influxdb/testdata/influxdbv2.want @@ -0,0 +1,11 @@ +goth.system/cpu/schedlatency.histogram count=5645i,max=41943040i,mean=1819544.0410983171,min=0i,p25=0,p50=0,p75=7168,p95=16777216,p99=29360128,p999=33554432,p9999=33554432,stddev=6393570.217198883,variance=40877740122252.57 978307200000000000 +goth.system/memory/pauses.histogram count=14i,max=229376i,mean=50066.28571428572,min=5120i,p25=10240,p50=32768,p75=57344,p95=196608,p99=196608,p999=196608,p9999=196608,stddev=54726.062410783874,variance=2994941906.9890113 978307200000000000 +goth.test/counter.count value=12345 978307200000000000 +goth.test/counter_float64.count value=54321.98 978307200000000000 +goth.test/gauge.gauge value=23456i 978307200000000000 +goth.test/gauge_float64.gauge value=34567.89 978307200000000000 +goth.test/gauge_info.gauge value="{\"arch\":\"amd64\",\"commit\":\"7caa2d8163ae3132c1c2d6978c76610caee2d949\",\"os\":\"linux\",\"protocol_versions\":\"64 65 66\",\"version\":\"1.10.18-unstable\"}" 978307200000000000 +goth.test/histogram.histogram count=3i,max=3i,mean=2,min=1i,p25=1,p50=2,p75=3,p95=3,p99=3,p999=3,p9999=3,stddev=0.816496580927726,variance=0.6666666666666666 978307200000000000 +goth.test/meter.meter count=0i,m1=0,m15=0,m5=0,mean=0 978307200000000000 +goth.test/resetting_timer.span count=6i,max=120000000i,mean=30000000,min=10000000i,p50=12500000i,p95=120000000i,p99=120000000i 978307200000000000 +goth.test/timer.timer count=6i,m1=0,m15=0,m5=0,max=120000000i,mean=38333333.333333336,meanrate=0,min=20000000i,p50=22500000,p75=48000000,p95=120000000,p99=120000000,p999=120000000,p9999=120000000,stddev=36545253.529775314,variance=1335555555555555.2 978307200000000000
diff --git ethereum/go-ethereum/metrics/internal/sampledata.go taikoxyz/taiko-geth/metrics/internal/sampledata.go new file mode 100644 index 0000000000000000000000000000000000000000..de9b207b6d4ad903069717fe8f5bd3d6270006a9 --- /dev/null +++ taikoxyz/taiko-geth/metrics/internal/sampledata.go @@ -0,0 +1,95 @@ +// Copyright 2023 The go-ethereum Authors +// This file is part of the go-ethereum library. +// +// The go-ethereum library is free software: you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// The go-ethereum library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>. + +package internal + +import ( + "bytes" + "encoding/gob" + metrics2 "runtime/metrics" + "time" + + "github.com/ethereum/go-ethereum/metrics" +) + +// ExampleMetrics returns an ordered registry populated with a sample of metrics. +func ExampleMetrics() metrics.Registry { + var registry = metrics.NewOrderedRegistry() + + metrics.NewRegisteredCounterFloat64("test/counter", registry).Inc(12345) + metrics.NewRegisteredCounterFloat64("test/counter_float64", registry).Inc(54321.98) + metrics.NewRegisteredGauge("test/gauge", registry).Update(23456) + metrics.NewRegisteredGaugeFloat64("test/gauge_float64", registry).Update(34567.89) + metrics.NewRegisteredGaugeInfo("test/gauge_info", registry).Update( + metrics.GaugeInfoValue{ + "version": "1.10.18-unstable", + "arch": "amd64", + "os": "linux", + "commit": "7caa2d8163ae3132c1c2d6978c76610caee2d949", + "protocol_versions": "64 65 66", + }) + + { + s := metrics.NewUniformSample(3) + s.Update(1) + s.Update(2) + s.Update(3) + //metrics.NewRegisteredHistogram("test/histogram", registry, metrics.NewSampleSnapshot(3, []int64{1, 2, 3})) + metrics.NewRegisteredHistogram("test/histogram", registry, s) + } + registry.Register("test/meter", metrics.NewInactiveMeter()) + { + timer := metrics.NewRegisteredResettingTimer("test/resetting_timer", registry) + timer.Update(10 * time.Millisecond) + timer.Update(11 * time.Millisecond) + timer.Update(12 * time.Millisecond) + timer.Update(120 * time.Millisecond) + timer.Update(13 * time.Millisecond) + timer.Update(14 * time.Millisecond) + } + { + timer := metrics.NewRegisteredTimer("test/timer", registry) + timer.Update(20 * time.Millisecond) + timer.Update(21 * time.Millisecond) + timer.Update(22 * time.Millisecond) + timer.Update(120 * time.Millisecond) + timer.Update(23 * time.Millisecond) + timer.Update(24 * time.Millisecond) + timer.Stop() + } + registry.Register("test/empty_resetting_timer", metrics.NewResettingTimer().Snapshot()) + + { // go runtime metrics + var sLatency = "7\xff\x81\x03\x01\x01\x10Float64Histogram\x01\xff\x82\x00\x01\x02\x01\x06Counts\x01\xff\x84\x00\x01\aBuckets\x01\xff\x86\x00\x00\x00\x16\xff\x83\x02\x01\x01\b[]uint64\x01\xff\x84\x00\x01\x06\x00\x00\x17\xff\x85\x02\x01\x01\t[]float64\x01\xff\x86\x00\x01\b\x00\x00\xfe\x06T\xff\x82\x01\xff\xa2\x00\xfe\r\xef\x00\x01\x02\x02\x04\x05\x04\b\x15\x17 B?6.L;$!2) \x1a? \x190aH7FY6#\x190\x1d\x14\x10\x1b\r\t\x04\x03\x01\x01\x00\x03\x02\x00\x03\x05\x05\x02\x02\x06\x04\v\x06\n\x15\x18\x13'&.\x12=H/L&\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\xff\xa3\xfe\xf0\xff\x00\xf8\x95\xd6&\xe8\v.q>\xf8\x95\xd6&\xe8\v.\x81>\xf8\xdfA:\xdc\x11ʼn>\xf8\x95\xd6&\xe8\v.\x91>\xf8:\x8c0\xe2\x8ey\x95>\xf8\xdfA:\xdc\x11ř>\xf8\x84\xf7C֔\x10\x9e>\xf8\x95\xd6&\xe8\v.\xa1>\xf8:\x8c0\xe2\x8ey\xa5>\xf8\xdfA:\xdc\x11ũ>\xf8\x84\xf7C֔\x10\xae>\xf8\x95\xd6&\xe8\v.\xb1>\xf8:\x8c0\xe2\x8ey\xb5>\xf8\xdfA:\xdc\x11Ź>\xf8\x84\xf7C֔\x10\xbe>\xf8\x95\xd6&\xe8\v.\xc1>\xf8:\x8c0\xe2\x8ey\xc5>\xf8\xdfA:\xdc\x11\xc5\xc9>\xf8\x84\xf7C֔\x10\xce>\xf8\x95\xd6&\xe8\v.\xd1>\xf8:\x8c0\xe2\x8ey\xd5>\xf8\xdfA:\xdc\x11\xc5\xd9>\xf8\x84\xf7C֔\x10\xde>\xf8\x95\xd6&\xe8\v.\xe1>\xf8:\x8c0\xe2\x8ey\xe5>\xf8\xdfA:\xdc\x11\xc5\xe9>\xf8\x84\xf7C֔\x10\xee>\xf8\x95\xd6&\xe8\v.\xf1>\xf8:\x8c0\xe2\x8ey\xf5>\xf8\xdfA:\xdc\x11\xc5\xf9>\xf8\x84\xf7C֔\x10\xfe>\xf8\x95\xd6&\xe8\v.\x01?\xf8:\x8c0\xe2\x8ey\x05?\xf8\xdfA:\xdc\x11\xc5\t?\xf8\x84\xf7C֔\x10\x0e?\xf8\x95\xd6&\xe8\v.\x11?\xf8:\x8c0\xe2\x8ey\x15?\xf8\xdfA:\xdc\x11\xc5\x19?\xf8\x84\xf7C֔\x10\x1e?\xf8\x95\xd6&\xe8\v.!?\xf8:\x8c0\xe2\x8ey%?\xf8\xdfA:\xdc\x11\xc5)?\xf8\x84\xf7C֔\x10.?\xf8\x95\xd6&\xe8\v.1?\xf8:\x8c0\xe2\x8ey5?\xf8\xdfA:\xdc\x11\xc59?\xf8\x84\xf7C֔\x10>?\xf8\x95\xd6&\xe8\v.A?\xf8:\x8c0\xe2\x8eyE?\xf8\xdfA:\xdc\x11\xc5I?\xf8\x84\xf7C֔\x10N?\xf8\x95\xd6&\xe8\v.Q?\xf8:\x8c0\xe2\x8eyU?\xf8\xdfA:\xdc\x11\xc5Y?\xf8\x84\xf7C֔\x10^?\xf8\x95\xd6&\xe8\v.a?\xf8:\x8c0\xe2\x8eye?\xf8\xdfA:\xdc\x11\xc5i?\xf8\x84\xf7C֔\x10n?\xf8\x95\xd6&\xe8\v.q?\xf8:\x8c0\xe2\x8eyu?\xf8\xdfA:\xdc\x11\xc5y?\xf8\x84\xf7C֔\x10~?\xf8\x95\xd6&\xe8\v.\x81?\xf8:\x8c0\xe2\x8ey\x85?\xf8\xdfA:\xdc\x11ʼn?\xf8\x84\xf7C֔\x10\x8e?\xf8\x95\xd6&\xe8\v.\x91?\xf8:\x8c0\xe2\x8ey\x95?\xf8\xdfA:\xdc\x11ř?\xf8\x84\xf7C֔\x10\x9e?\xf8\x95\xd6&\xe8\v.\xa1?\xf8:\x8c0\xe2\x8ey\xa5?\xf8\xdfA:\xdc\x11ũ?\xf8\x84\xf7C֔\x10\xae?\xf8\x95\xd6&\xe8\v.\xb1?\xf8:\x8c0\xe2\x8ey\xb5?\xf8\xdfA:\xdc\x11Ź?\xf8\x84\xf7C֔\x10\xbe?\xf8\x95\xd6&\xe8\v.\xc1?\xf8:\x8c0\xe2\x8ey\xc5?\xf8\xdfA:\xdc\x11\xc5\xc9?\xf8\x84\xf7C֔\x10\xce?\xf8\x95\xd6&\xe8\v.\xd1?\xf8:\x8c0\xe2\x8ey\xd5?\xf8\xdfA:\xdc\x11\xc5\xd9?\xf8\x84\xf7C֔\x10\xde?\xf8\x95\xd6&\xe8\v.\xe1?\xf8:\x8c0\xe2\x8ey\xe5?\xf8\xdfA:\xdc\x11\xc5\xe9?\xf8\x84\xf7C֔\x10\xee?\xf8\x95\xd6&\xe8\v.\xf1?\xf8:\x8c0\xe2\x8ey\xf5?\xf8\xdfA:\xdc\x11\xc5\xf9?\xf8\x84\xf7C֔\x10\xfe?\xf8\x95\xd6&\xe8\v.\x01@\xf8:\x8c0\xe2\x8ey\x05@\xf8\xdfA:\xdc\x11\xc5\t@\xf8\x84\xf7C֔\x10\x0e@\xf8\x95\xd6&\xe8\v.\x11@\xf8:\x8c0\xe2\x8ey\x15@\xf8\xdfA:\xdc\x11\xc5\x19@\xf8\x84\xf7C֔\x10\x1e@\xf8\x95\xd6&\xe8\v.!@\xf8:\x8c0\xe2\x8ey%@\xf8\xdfA:\xdc\x11\xc5)@\xf8\x84\xf7C֔\x10.@\xf8\x95\xd6&\xe8\v.1@\xf8:\x8c0\xe2\x8ey5@\xf8\xdfA:\xdc\x11\xc59@\xf8\x84\xf7C֔\x10>@\xf8\x95\xd6&\xe8\v.A@\xf8:\x8c0\xe2\x8eyE@\xf8\xdfA:\xdc\x11\xc5I@\xf8\x84\xf7C֔\x10N@\xf8\x95\xd6&\xe8\v.Q@\xf8:\x8c0\xe2\x8eyU@\xf8\xdfA:\xdc\x11\xc5Y@\xf8\x84\xf7C֔\x10^@\xf8\x95\xd6&\xe8\v.a@\xf8:\x8c0\xe2\x8eye@\xf8\xdfA:\xdc\x11\xc5i@\xf8\x84\xf7C֔\x10n@\xf8\x95\xd6&\xe8\v.q@\xf8:\x8c0\xe2\x8eyu@\xf8\xdfA:\xdc\x11\xc5y@\xf8\x84\xf7C֔\x10~@\xf8\x95\xd6&\xe8\v.\x81@\xf8:\x8c0\xe2\x8ey\x85@\xf8\xdfA:\xdc\x11ʼn@\xf8\x84\xf7C֔\x10\x8e@\xf8\x95\xd6&\xe8\v.\x91@\xf8:\x8c0\xe2\x8ey\x95@\xf8\xdfA:\xdc\x11ř@\xf8\x84\xf7C֔\x10\x9e@\xf8\x95\xd6&\xe8\v.\xa1@\xf8:\x8c0\xe2\x8ey\xa5@\xf8\xdfA:\xdc\x11ũ@\xf8\x84\xf7C֔\x10\xae@\xf8\x95\xd6&\xe8\v.\xb1@\xf8:\x8c0\xe2\x8ey\xb5@\xf8\xdfA:\xdc\x11Ź@\xf8\x84\xf7C֔\x10\xbe@\xf8\x95\xd6&\xe8\v.\xc1@\xf8:\x8c0\xe2\x8ey\xc5@\xf8\xdfA:\xdc\x11\xc5\xc9@\xf8\x84\xf7C֔\x10\xce@\xf8\x95\xd6&\xe8\v.\xd1@\xf8:\x8c0\xe2\x8ey\xd5@\xf8\xdfA:\xdc\x11\xc5\xd9@\xf8\x84\xf7C֔\x10\xde@\xf8\x95\xd6&\xe8\v.\xe1@\xf8:\x8c0\xe2\x8ey\xe5@\xf8\xdfA:\xdc\x11\xc5\xe9@\xf8\x84\xf7C֔\x10\xee@\xf8\x95\xd6&\xe8\v.\xf1@\xf8:\x8c0\xe2\x8ey\xf5@\xf8\xdfA:\xdc\x11\xc5\xf9@\xf8\x84\xf7C֔\x10\xfe@\xf8\x95\xd6&\xe8\v.\x01A\xfe\xf0\x7f\x00" + var gcPauses = "7\xff\x81\x03\x01\x01\x10Float64Histogram\x01\xff\x82\x00\x01\x02\x01\x06Counts\x01\xff\x84\x00\x01\aBuckets\x01\xff\x86\x00\x00\x00\x16\xff\x83\x02\x01\x01\b[]uint64\x01\xff\x84\x00\x01\x06\x00\x00\x17\xff\x85\x02\x01\x01\t[]float64\x01\xff\x86\x00\x01\b\x00\x00\xfe\x06R\xff\x82\x01\xff\xa2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x01\x01\x00\x01\x00\x00\x00\x01\x01\x01\x01\x01\x01\x01\x00\x02\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\xff\xa3\xfe\xf0\xff\x00\xf8\x95\xd6&\xe8\v.q>\xf8\x95\xd6&\xe8\v.\x81>\xf8\xdfA:\xdc\x11ʼn>\xf8\x95\xd6&\xe8\v.\x91>\xf8:\x8c0\xe2\x8ey\x95>\xf8\xdfA:\xdc\x11ř>\xf8\x84\xf7C֔\x10\x9e>\xf8\x95\xd6&\xe8\v.\xa1>\xf8:\x8c0\xe2\x8ey\xa5>\xf8\xdfA:\xdc\x11ũ>\xf8\x84\xf7C֔\x10\xae>\xf8\x95\xd6&\xe8\v.\xb1>\xf8:\x8c0\xe2\x8ey\xb5>\xf8\xdfA:\xdc\x11Ź>\xf8\x84\xf7C֔\x10\xbe>\xf8\x95\xd6&\xe8\v.\xc1>\xf8:\x8c0\xe2\x8ey\xc5>\xf8\xdfA:\xdc\x11\xc5\xc9>\xf8\x84\xf7C֔\x10\xce>\xf8\x95\xd6&\xe8\v.\xd1>\xf8:\x8c0\xe2\x8ey\xd5>\xf8\xdfA:\xdc\x11\xc5\xd9>\xf8\x84\xf7C֔\x10\xde>\xf8\x95\xd6&\xe8\v.\xe1>\xf8:\x8c0\xe2\x8ey\xe5>\xf8\xdfA:\xdc\x11\xc5\xe9>\xf8\x84\xf7C֔\x10\xee>\xf8\x95\xd6&\xe8\v.\xf1>\xf8:\x8c0\xe2\x8ey\xf5>\xf8\xdfA:\xdc\x11\xc5\xf9>\xf8\x84\xf7C֔\x10\xfe>\xf8\x95\xd6&\xe8\v.\x01?\xf8:\x8c0\xe2\x8ey\x05?\xf8\xdfA:\xdc\x11\xc5\t?\xf8\x84\xf7C֔\x10\x0e?\xf8\x95\xd6&\xe8\v.\x11?\xf8:\x8c0\xe2\x8ey\x15?\xf8\xdfA:\xdc\x11\xc5\x19?\xf8\x84\xf7C֔\x10\x1e?\xf8\x95\xd6&\xe8\v.!?\xf8:\x8c0\xe2\x8ey%?\xf8\xdfA:\xdc\x11\xc5)?\xf8\x84\xf7C֔\x10.?\xf8\x95\xd6&\xe8\v.1?\xf8:\x8c0\xe2\x8ey5?\xf8\xdfA:\xdc\x11\xc59?\xf8\x84\xf7C֔\x10>?\xf8\x95\xd6&\xe8\v.A?\xf8:\x8c0\xe2\x8eyE?\xf8\xdfA:\xdc\x11\xc5I?\xf8\x84\xf7C֔\x10N?\xf8\x95\xd6&\xe8\v.Q?\xf8:\x8c0\xe2\x8eyU?\xf8\xdfA:\xdc\x11\xc5Y?\xf8\x84\xf7C֔\x10^?\xf8\x95\xd6&\xe8\v.a?\xf8:\x8c0\xe2\x8eye?\xf8\xdfA:\xdc\x11\xc5i?\xf8\x84\xf7C֔\x10n?\xf8\x95\xd6&\xe8\v.q?\xf8:\x8c0\xe2\x8eyu?\xf8\xdfA:\xdc\x11\xc5y?\xf8\x84\xf7C֔\x10~?\xf8\x95\xd6&\xe8\v.\x81?\xf8:\x8c0\xe2\x8ey\x85?\xf8\xdfA:\xdc\x11ʼn?\xf8\x84\xf7C֔\x10\x8e?\xf8\x95\xd6&\xe8\v.\x91?\xf8:\x8c0\xe2\x8ey\x95?\xf8\xdfA:\xdc\x11ř?\xf8\x84\xf7C֔\x10\x9e?\xf8\x95\xd6&\xe8\v.\xa1?\xf8:\x8c0\xe2\x8ey\xa5?\xf8\xdfA:\xdc\x11ũ?\xf8\x84\xf7C֔\x10\xae?\xf8\x95\xd6&\xe8\v.\xb1?\xf8:\x8c0\xe2\x8ey\xb5?\xf8\xdfA:\xdc\x11Ź?\xf8\x84\xf7C֔\x10\xbe?\xf8\x95\xd6&\xe8\v.\xc1?\xf8:\x8c0\xe2\x8ey\xc5?\xf8\xdfA:\xdc\x11\xc5\xc9?\xf8\x84\xf7C֔\x10\xce?\xf8\x95\xd6&\xe8\v.\xd1?\xf8:\x8c0\xe2\x8ey\xd5?\xf8\xdfA:\xdc\x11\xc5\xd9?\xf8\x84\xf7C֔\x10\xde?\xf8\x95\xd6&\xe8\v.\xe1?\xf8:\x8c0\xe2\x8ey\xe5?\xf8\xdfA:\xdc\x11\xc5\xe9?\xf8\x84\xf7C֔\x10\xee?\xf8\x95\xd6&\xe8\v.\xf1?\xf8:\x8c0\xe2\x8ey\xf5?\xf8\xdfA:\xdc\x11\xc5\xf9?\xf8\x84\xf7C֔\x10\xfe?\xf8\x95\xd6&\xe8\v.\x01@\xf8:\x8c0\xe2\x8ey\x05@\xf8\xdfA:\xdc\x11\xc5\t@\xf8\x84\xf7C֔\x10\x0e@\xf8\x95\xd6&\xe8\v.\x11@\xf8:\x8c0\xe2\x8ey\x15@\xf8\xdfA:\xdc\x11\xc5\x19@\xf8\x84\xf7C֔\x10\x1e@\xf8\x95\xd6&\xe8\v.!@\xf8:\x8c0\xe2\x8ey%@\xf8\xdfA:\xdc\x11\xc5)@\xf8\x84\xf7C֔\x10.@\xf8\x95\xd6&\xe8\v.1@\xf8:\x8c0\xe2\x8ey5@\xf8\xdfA:\xdc\x11\xc59@\xf8\x84\xf7C֔\x10>@\xf8\x95\xd6&\xe8\v.A@\xf8:\x8c0\xe2\x8eyE@\xf8\xdfA:\xdc\x11\xc5I@\xf8\x84\xf7C֔\x10N@\xf8\x95\xd6&\xe8\v.Q@\xf8:\x8c0\xe2\x8eyU@\xf8\xdfA:\xdc\x11\xc5Y@\xf8\x84\xf7C֔\x10^@\xf8\x95\xd6&\xe8\v.a@\xf8:\x8c0\xe2\x8eye@\xf8\xdfA:\xdc\x11\xc5i@\xf8\x84\xf7C֔\x10n@\xf8\x95\xd6&\xe8\v.q@\xf8:\x8c0\xe2\x8eyu@\xf8\xdfA:\xdc\x11\xc5y@\xf8\x84\xf7C֔\x10~@\xf8\x95\xd6&\xe8\v.\x81@\xf8:\x8c0\xe2\x8ey\x85@\xf8\xdfA:\xdc\x11ʼn@\xf8\x84\xf7C֔\x10\x8e@\xf8\x95\xd6&\xe8\v.\x91@\xf8:\x8c0\xe2\x8ey\x95@\xf8\xdfA:\xdc\x11ř@\xf8\x84\xf7C֔\x10\x9e@\xf8\x95\xd6&\xe8\v.\xa1@\xf8:\x8c0\xe2\x8ey\xa5@\xf8\xdfA:\xdc\x11ũ@\xf8\x84\xf7C֔\x10\xae@\xf8\x95\xd6&\xe8\v.\xb1@\xf8:\x8c0\xe2\x8ey\xb5@\xf8\xdfA:\xdc\x11Ź@\xf8\x84\xf7C֔\x10\xbe@\xf8\x95\xd6&\xe8\v.\xc1@\xf8:\x8c0\xe2\x8ey\xc5@\xf8\xdfA:\xdc\x11\xc5\xc9@\xf8\x84\xf7C֔\x10\xce@\xf8\x95\xd6&\xe8\v.\xd1@\xf8:\x8c0\xe2\x8ey\xd5@\xf8\xdfA:\xdc\x11\xc5\xd9@\xf8\x84\xf7C֔\x10\xde@\xf8\x95\xd6&\xe8\v.\xe1@\xf8:\x8c0\xe2\x8ey\xe5@\xf8\xdfA:\xdc\x11\xc5\xe9@\xf8\x84\xf7C֔\x10\xee@\xf8\x95\xd6&\xe8\v.\xf1@\xf8:\x8c0\xe2\x8ey\xf5@\xf8\xdfA:\xdc\x11\xc5\xf9@\xf8\x84\xf7C֔\x10\xfe@\xf8\x95\xd6&\xe8\v.\x01A\xfe\xf0\x7f\x00" + + var secondsToNs = float64(time.Second) + + dserialize := func(data string) *metrics2.Float64Histogram { + var res metrics2.Float64Histogram + if err := gob.NewDecoder(bytes.NewReader([]byte(data))).Decode(&res); err != nil { + panic(err) + } + return &res + } + cpuSchedLatency := metrics.RuntimeHistogramFromData(secondsToNs, dserialize(sLatency)) + registry.Register("system/cpu/schedlatency", cpuSchedLatency) + + memPauses := metrics.RuntimeHistogramFromData(secondsToNs, dserialize(gcPauses)) + registry.Register("system/memory/pauses", memPauses) + } + return registry +}
diff --git ethereum/go-ethereum/metrics/internal/sampledata_test.go taikoxyz/taiko-geth/metrics/internal/sampledata_test.go new file mode 100644 index 0000000000000000000000000000000000000000..00132994064e36f4ca88f38bb4ad197b1facc37f --- /dev/null +++ taikoxyz/taiko-geth/metrics/internal/sampledata_test.go @@ -0,0 +1,27 @@ +package internal + +import ( + "bytes" + "encoding/gob" + "fmt" + metrics2 "runtime/metrics" + "testing" + "time" + + "github.com/ethereum/go-ethereum/metrics" +) + +func TestCollectRuntimeMetrics(t *testing.T) { + t.Skip("Only used for generating testdata") + serialize := func(path string, histogram *metrics2.Float64Histogram) { + var f = new(bytes.Buffer) + if err := gob.NewEncoder(f).Encode(histogram); err != nil { + panic(err) + } + fmt.Printf("var %v = %q\n", path, f.Bytes()) + } + time.Sleep(2 * time.Second) + stats := metrics.ReadRuntimeStats() + serialize("schedlatency", stats.SchedLatency) + serialize("gcpauses", stats.GCPauses) +}
diff --git ethereum/go-ethereum/metrics/librato/librato.go taikoxyz/taiko-geth/metrics/librato/librato.go index 3d45f4c7be1be69cf9e8643590237dde01448a78..a86f758637869f15e7372ba1f684119c07586763 100644 --- ethereum/go-ethereum/metrics/librato/librato.go +++ taikoxyz/taiko-geth/metrics/librato/librato.go @@ -61,16 +61,16 @@ }   // calculate sum of squares from data provided by metrics.Histogram // see http://en.wikipedia.org/wiki/Standard_deviation#Rapid_calculation_methods -func sumSquares(s metrics.Sample) float64 { - count := float64(s.Count()) - sumSquared := math.Pow(count*s.Mean(), 2) - sumSquares := math.Pow(count*s.StdDev(), 2) + sumSquared/count +func sumSquares(icount int64, mean, stDev float64) float64 { + count := float64(icount) + sumSquared := math.Pow(count*mean, 2) + sumSquares := math.Pow(count*stDev, 2) + sumSquared/count if math.IsNaN(sumSquares) { return 0.0 } return sumSquares } -func sumSquaresTimer(t metrics.Timer) float64 { +func sumSquaresTimer(t metrics.TimerSnapshot) float64 { count := float64(t.Count()) sumSquared := math.Pow(count*t.Mean(), 2) sumSquares := math.Pow(count*t.StdDev(), 2) + sumSquared/count @@ -97,9 +97,10 @@ measurement := Measurement{} measurement[Period] = rep.Interval.Seconds() switch m := metric.(type) { case metrics.Counter: - if m.Count() > 0 { + ms := m.Snapshot() + if ms.Count() > 0 { measurement[Name] = fmt.Sprintf("%s.%s", name, "count") - measurement[Value] = float64(m.Count()) + measurement[Value] = float64(ms.Count()) measurement[Attributes] = map[string]interface{}{ DisplayUnitsLong: Operations, DisplayUnitsShort: OperationsShort, @@ -108,9 +109,9 @@ } snapshot.Counters = append(snapshot.Counters, measurement) } case metrics.CounterFloat64: - if m.Count() > 0 { + if count := m.Snapshot().Count(); count > 0 { measurement[Name] = fmt.Sprintf("%s.%s", name, "count") - measurement[Value] = m.Count() + measurement[Value] = count measurement[Attributes] = map[string]interface{}{ DisplayUnitsLong: Operations, DisplayUnitsShort: OperationsShort, @@ -120,40 +121,45 @@ snapshot.Counters = append(snapshot.Counters, measurement) } case metrics.Gauge: measurement[Name] = name - measurement[Value] = float64(m.Value()) + measurement[Value] = float64(m.Snapshot().Value()) snapshot.Gauges = append(snapshot.Gauges, measurement) case metrics.GaugeFloat64: measurement[Name] = name - measurement[Value] = m.Value() + measurement[Value] = m.Snapshot().Value() + snapshot.Gauges = append(snapshot.Gauges, measurement) + case metrics.GaugeInfo: + measurement[Name] = name + measurement[Value] = m.Snapshot().Value() snapshot.Gauges = append(snapshot.Gauges, measurement) case metrics.Histogram: - if m.Count() > 0 { + ms := m.Snapshot() + if ms.Count() > 0 { gauges := make([]Measurement, histogramGaugeCount) - s := m.Sample() measurement[Name] = fmt.Sprintf("%s.%s", name, "hist") - measurement[Count] = uint64(s.Count()) - measurement[Max] = float64(s.Max()) - measurement[Min] = float64(s.Min()) - measurement[Sum] = float64(s.Sum()) - measurement[SumSquares] = sumSquares(s) + measurement[Count] = uint64(ms.Count()) + measurement[Max] = float64(ms.Max()) + measurement[Min] = float64(ms.Min()) + measurement[Sum] = float64(ms.Sum()) + measurement[SumSquares] = sumSquares(ms.Count(), ms.Mean(), ms.StdDev()) gauges[0] = measurement for i, p := range rep.Percentiles { gauges[i+1] = Measurement{ Name: fmt.Sprintf("%s.%.2f", measurement[Name], p), - Value: s.Percentile(p), + Value: ms.Percentile(p), Period: measurement[Period], } } snapshot.Gauges = append(snapshot.Gauges, gauges...) } case metrics.Meter: + ms := m.Snapshot() measurement[Name] = name - measurement[Value] = float64(m.Count()) + measurement[Value] = float64(ms.Count()) snapshot.Counters = append(snapshot.Counters, measurement) snapshot.Gauges = append(snapshot.Gauges, Measurement{ Name: fmt.Sprintf("%s.%s", name, "1min"), - Value: m.Rate1(), + Value: ms.Rate1(), Period: int64(rep.Interval.Seconds()), Attributes: map[string]interface{}{ DisplayUnitsLong: Operations, @@ -163,7 +169,7 @@ }, }, Measurement{ Name: fmt.Sprintf("%s.%s", name, "5min"), - Value: m.Rate5(), + Value: ms.Rate5(), Period: int64(rep.Interval.Seconds()), Attributes: map[string]interface{}{ DisplayUnitsLong: Operations, @@ -173,7 +179,7 @@ }, }, Measurement{ Name: fmt.Sprintf("%s.%s", name, "15min"), - Value: m.Rate15(), + Value: ms.Rate15(), Period: int64(rep.Interval.Seconds()), Attributes: map[string]interface{}{ DisplayUnitsLong: Operations, @@ -183,26 +189,27 @@ }, }, ) case metrics.Timer: + ms := m.Snapshot() measurement[Name] = name - measurement[Value] = float64(m.Count()) + measurement[Value] = float64(ms.Count()) snapshot.Counters = append(snapshot.Counters, measurement) - if m.Count() > 0 { + if ms.Count() > 0 { libratoName := fmt.Sprintf("%s.%s", name, "timer.mean") gauges := make([]Measurement, histogramGaugeCount) gauges[0] = Measurement{ Name: libratoName, - Count: uint64(m.Count()), - Sum: m.Mean() * float64(m.Count()), - Max: float64(m.Max()), - Min: float64(m.Min()), - SumSquares: sumSquaresTimer(m), + Count: uint64(ms.Count()), + Sum: ms.Mean() * float64(ms.Count()), + Max: float64(ms.Max()), + Min: float64(ms.Min()), + SumSquares: sumSquaresTimer(ms), Period: int64(rep.Interval.Seconds()), Attributes: rep.TimerAttributes, } for i, p := range rep.Percentiles { gauges[i+1] = Measurement{ Name: fmt.Sprintf("%s.timer.%2.0f", name, p*100), - Value: m.Percentile(p), + Value: ms.Percentile(p), Period: int64(rep.Interval.Seconds()), Attributes: rep.TimerAttributes, } @@ -211,7 +218,7 @@ snapshot.Gauges = append(snapshot.Gauges, gauges...) snapshot.Gauges = append(snapshot.Gauges, Measurement{ Name: fmt.Sprintf("%s.%s", name, "rate.1min"), - Value: m.Rate1(), + Value: ms.Rate1(), Period: int64(rep.Interval.Seconds()), Attributes: map[string]interface{}{ DisplayUnitsLong: Operations, @@ -221,7 +228,7 @@ }, }, Measurement{ Name: fmt.Sprintf("%s.%s", name, "rate.5min"), - Value: m.Rate5(), + Value: ms.Rate5(), Period: int64(rep.Interval.Seconds()), Attributes: map[string]interface{}{ DisplayUnitsLong: Operations, @@ -231,7 +238,7 @@ }, }, Measurement{ Name: fmt.Sprintf("%s.%s", name, "rate.15min"), - Value: m.Rate15(), + Value: ms.Rate15(), Period: int64(rep.Interval.Seconds()), Attributes: map[string]interface{}{ DisplayUnitsLong: Operations,
diff --git ethereum/go-ethereum/metrics/log.go taikoxyz/taiko-geth/metrics/log.go index d1ce627a8378ba164cf592aac40711269645efe0..3b9773faa7287d23fa47501f8f253677a48a4b86 100644 --- ethereum/go-ethereum/metrics/log.go +++ taikoxyz/taiko-geth/metrics/log.go @@ -23,16 +23,19 @@ r.Each(func(name string, i interface{}) { switch metric := i.(type) { case Counter: l.Printf("counter %s\n", name) - l.Printf(" count: %9d\n", metric.Count()) + l.Printf(" count: %9d\n", metric.Snapshot().Count()) case CounterFloat64: l.Printf("counter %s\n", name) - l.Printf(" count: %f\n", metric.Count()) + l.Printf(" count: %f\n", metric.Snapshot().Count()) case Gauge: l.Printf("gauge %s\n", name) - l.Printf(" value: %9d\n", metric.Value()) + l.Printf(" value: %9d\n", metric.Snapshot().Value()) case GaugeFloat64: l.Printf("gauge %s\n", name) - l.Printf(" value: %f\n", metric.Value()) + l.Printf(" value: %f\n", metric.Snapshot().Value()) + case GaugeInfo: + l.Printf("gauge %s\n", name) + l.Printf(" value: %s\n", metric.Snapshot().Value()) case Healthcheck: metric.Check() l.Printf("healthcheck %s\n", name)
diff --git ethereum/go-ethereum/metrics/meter.go taikoxyz/taiko-geth/metrics/meter.go index e8564d6a5e76f1615b8ea0decf65f1aa821efeb6..22475ef6ebee8863af3277534eaedf0a17cf126f 100644 --- ethereum/go-ethereum/metrics/meter.go +++ taikoxyz/taiko-geth/metrics/meter.go @@ -1,21 +1,25 @@ package metrics   import ( + "math" "sync" "sync/atomic" "time" )   -// Meters count events to produce exponentially-weighted moving average rates -// at one-, five-, and fifteen-minutes and a mean rate. -type Meter interface { +type MeterSnapshot interface { Count() int64 - Mark(int64) Rate1() float64 Rate5() float64 Rate15() float64 RateMean() float64 - Snapshot() Meter +} + +// Meters count events to produce exponentially-weighted moving average rates +// at one-, five-, and fifteen-minutes and a mean rate. +type Meter interface { + Mark(int64) + Snapshot() MeterSnapshot Stop() }   @@ -30,17 +34,6 @@ } return r.GetOrRegister(name, NewMeter).(Meter) }   -// GetOrRegisterMeterForced returns an existing Meter or constructs and registers a -// new StandardMeter no matter the global switch is enabled or not. -// Be sure to unregister the meter from the registry once it is of no use to -// allow for garbage collection. -func GetOrRegisterMeterForced(name string, r Registry) Meter { - if nil == r { - r = DefaultRegistry - } - return r.GetOrRegister(name, NewMeterForced).(Meter) -} - // NewMeter constructs a new StandardMeter and launches a goroutine. // Be sure to call Stop() once the meter is of no use to allow for garbage collection. func NewMeter() Meter { @@ -58,18 +51,13 @@ } return m }   -// NewMeterForced constructs a new StandardMeter and launches a goroutine no matter -// the global switch is enabled or not. -// Be sure to call Stop() once the meter is of no use to allow for garbage collection. -func NewMeterForced() Meter { - m := newStandardMeter() - arbiter.Lock() - defer arbiter.Unlock() - arbiter.meters[m] = struct{}{} - if !arbiter.started { - arbiter.started = true - go arbiter.tick() +// NewInactiveMeter returns a meter but does not start any goroutines. This +// method is mainly intended for testing. +func NewInactiveMeter() Meter { + if !Enabled { + return NilMeter{} } + m := newStandardMeter() return m }   @@ -78,95 +66,48 @@ // and launches a goroutine. // Be sure to unregister the meter from the registry once it is of no use to // allow for garbage collection. func NewRegisteredMeter(name string, r Registry) Meter { - c := NewMeter() - if nil == r { - r = DefaultRegistry - } - r.Register(name, c) - return c + return GetOrRegisterMeter(name, r) }   -// NewRegisteredMeterForced constructs and registers a new StandardMeter -// and launches a goroutine no matter the global switch is enabled or not. -// Be sure to unregister the meter from the registry once it is of no use to -// allow for garbage collection. -func NewRegisteredMeterForced(name string, r Registry) Meter { - c := NewMeterForced() - if nil == r { - r = DefaultRegistry - } - r.Register(name, c) - return c -} - -// MeterSnapshot is a read-only copy of another Meter. -type MeterSnapshot struct { - temp atomic.Int64 +// meterSnapshot is a read-only copy of the meter's internal values. +type meterSnapshot struct { count int64 rate1, rate5, rate15, rateMean float64 }   // Count returns the count of events at the time the snapshot was taken. -func (m *MeterSnapshot) Count() int64 { return m.count } - -// Mark panics. -func (*MeterSnapshot) Mark(n int64) { - panic("Mark called on a MeterSnapshot") -} +func (m *meterSnapshot) Count() int64 { return m.count }   // Rate1 returns the one-minute moving average rate of events per second at the // time the snapshot was taken. -func (m *MeterSnapshot) Rate1() float64 { return m.rate1 } +func (m *meterSnapshot) Rate1() float64 { return m.rate1 }   // Rate5 returns the five-minute moving average rate of events per second at // the time the snapshot was taken. -func (m *MeterSnapshot) Rate5() float64 { return m.rate5 } +func (m *meterSnapshot) Rate5() float64 { return m.rate5 }   // Rate15 returns the fifteen-minute moving average rate of events per second // at the time the snapshot was taken. -func (m *MeterSnapshot) Rate15() float64 { return m.rate15 } +func (m *meterSnapshot) Rate15() float64 { return m.rate15 }   // RateMean returns the meter's mean rate of events per second at the time the // snapshot was taken. -func (m *MeterSnapshot) RateMean() float64 { return m.rateMean } - -// Snapshot returns the snapshot. -func (m *MeterSnapshot) Snapshot() Meter { return m } - -// Stop is a no-op. -func (m *MeterSnapshot) Stop() {} +func (m *meterSnapshot) RateMean() float64 { return m.rateMean }   // NilMeter is a no-op Meter. type NilMeter struct{}   -// Count is a no-op. -func (NilMeter) Count() int64 { return 0 } - -// Mark is a no-op. -func (NilMeter) Mark(n int64) {} - -// Rate1 is a no-op. -func (NilMeter) Rate1() float64 { return 0.0 } - -// Rate5 is a no-op. -func (NilMeter) Rate5() float64 { return 0.0 } - -// Rate15 is a no-op. -func (NilMeter) Rate15() float64 { return 0.0 } - -// RateMean is a no-op. -func (NilMeter) RateMean() float64 { return 0.0 } - -// Snapshot is a no-op. -func (NilMeter) Snapshot() Meter { return NilMeter{} } - -// Stop is a no-op. -func (NilMeter) Stop() {} +func (NilMeter) Count() int64 { return 0 } +func (NilMeter) Mark(n int64) {} +func (NilMeter) Snapshot() MeterSnapshot { return (*emptySnapshot)(nil) } +func (NilMeter) Stop() {}   // StandardMeter is the standard implementation of a Meter. type StandardMeter struct { - lock sync.RWMutex - snapshot *MeterSnapshot + count atomic.Int64 + uncounted atomic.Int64 // not yet added to the EWMAs + rateMean atomic.Uint64 + a1, a5, a15 EWMA startTime time.Time stopped atomic.Bool @@ -174,7 +115,6 @@ }   func newStandardMeter() *StandardMeter { return &StandardMeter{ - snapshot: &MeterSnapshot{}, a1: NewEWMA1(), a5: NewEWMA5(), a15: NewEWMA15(), @@ -184,97 +124,42 @@ }   // Stop stops the meter, Mark() will be a no-op if you use it after being stopped. func (m *StandardMeter) Stop() { - stopped := m.stopped.Swap(true) - if !stopped { + if stopped := m.stopped.Swap(true); !stopped { arbiter.Lock() delete(arbiter.meters, m) arbiter.Unlock() } }   -// Count returns the number of events recorded. -// It updates the meter to be as accurate as possible -func (m *StandardMeter) Count() int64 { - m.lock.Lock() - defer m.lock.Unlock() - m.updateMeter() - return m.snapshot.count -} - // Mark records the occurrence of n events. func (m *StandardMeter) Mark(n int64) { - m.snapshot.temp.Add(n) -} - -// Rate1 returns the one-minute moving average rate of events per second. -func (m *StandardMeter) Rate1() float64 { - m.lock.RLock() - defer m.lock.RUnlock() - return m.snapshot.rate1 -} - -// Rate5 returns the five-minute moving average rate of events per second. -func (m *StandardMeter) Rate5() float64 { - m.lock.RLock() - defer m.lock.RUnlock() - return m.snapshot.rate5 -} - -// Rate15 returns the fifteen-minute moving average rate of events per second. -func (m *StandardMeter) Rate15() float64 { - m.lock.RLock() - defer m.lock.RUnlock() - return m.snapshot.rate15 -} - -// RateMean returns the meter's mean rate of events per second. -func (m *StandardMeter) RateMean() float64 { - m.lock.RLock() - defer m.lock.RUnlock() - return m.snapshot.rateMean + m.uncounted.Add(n) }   // Snapshot returns a read-only copy of the meter. -func (m *StandardMeter) Snapshot() Meter { - m.lock.RLock() - snapshot := MeterSnapshot{ - count: m.snapshot.count, - rate1: m.snapshot.rate1, - rate5: m.snapshot.rate5, - rate15: m.snapshot.rate15, - rateMean: m.snapshot.rateMean, +func (m *StandardMeter) Snapshot() MeterSnapshot { + return &meterSnapshot{ + count: m.count.Load() + m.uncounted.Load(), + rate1: m.a1.Snapshot().Rate(), + rate5: m.a5.Snapshot().Rate(), + rate15: m.a15.Snapshot().Rate(), + rateMean: math.Float64frombits(m.rateMean.Load()), } - snapshot.temp.Store(m.snapshot.temp.Load()) - m.lock.RUnlock() - return &snapshot }   -func (m *StandardMeter) updateSnapshot() { - // should run with write lock held on m.lock - snapshot := m.snapshot - snapshot.rate1 = m.a1.Rate() - snapshot.rate5 = m.a5.Rate() - snapshot.rate15 = m.a15.Rate() - snapshot.rateMean = float64(snapshot.count) / time.Since(m.startTime).Seconds() -} - -func (m *StandardMeter) updateMeter() { - // should only run with write lock held on m.lock - n := m.snapshot.temp.Swap(0) - m.snapshot.count += n +func (m *StandardMeter) tick() { + // Take the uncounted values, add to count + n := m.uncounted.Swap(0) + count := m.count.Add(n) + m.rateMean.Store(math.Float64bits(float64(count) / time.Since(m.startTime).Seconds())) + // Update the EWMA's internal state m.a1.Update(n) m.a5.Update(n) m.a15.Update(n) -} - -func (m *StandardMeter) tick() { - m.lock.Lock() - defer m.lock.Unlock() - m.updateMeter() + // And trigger them to calculate the rates m.a1.Tick() m.a5.Tick() m.a15.Tick() - m.updateSnapshot() }   // meterArbiter ticks meters every 5s from a single goroutine.
diff --git ethereum/go-ethereum/metrics/meter_test.go taikoxyz/taiko-geth/metrics/meter_test.go index b3f6cb8c0c97e07752e7574d977f421859256db5..019c4d765b526abd56dbf7a87b83f5a7a84d346e 100644 --- ethereum/go-ethereum/metrics/meter_test.go +++ taikoxyz/taiko-geth/metrics/meter_test.go @@ -12,11 +12,17 @@ for i := 0; i < b.N; i++ { m.Mark(1) } } - +func TestMeter(t *testing.T) { + m := NewMeter() + m.Mark(47) + if v := m.Snapshot().Count(); v != 47 { + t.Fatalf("have %d want %d", v, 47) + } +} func TestGetOrRegisterMeter(t *testing.T) { r := NewRegistry() NewRegisteredMeter("foo", r).Mark(47) - if m := GetOrRegisterMeter("foo", r); m.Count() != 47 { + if m := GetOrRegisterMeter("foo", r).Snapshot(); m.Count() != 47 { t.Fatal(m.Count()) } } @@ -31,10 +37,10 @@ m := newStandardMeter() ma.meters[m] = struct{}{} m.Mark(1) ma.tickMeters() - rateMean := m.RateMean() + rateMean := m.Snapshot().RateMean() time.Sleep(100 * time.Millisecond) ma.tickMeters() - if m.RateMean() >= rateMean { + if m.Snapshot().RateMean() >= rateMean { t.Error("m.RateMean() didn't decrease") } } @@ -42,7 +48,7 @@ func TestMeterNonzero(t *testing.T) { m := NewMeter() m.Mark(3) - if count := m.Count(); count != 3 { + if count := m.Snapshot().Count(); count != 3 { t.Errorf("m.Count(): 3 != %v\n", count) } } @@ -59,16 +65,8 @@ t.Errorf("arbiter.meters: %d != %d\n", l, len(arbiter.meters)) } }   -func TestMeterSnapshot(t *testing.T) { - m := NewMeter() - m.Mark(1) - if snapshot := m.Snapshot(); m.RateMean() != snapshot.RateMean() { - t.Fatal(snapshot) - } -} - func TestMeterZero(t *testing.T) { - m := NewMeter() + m := NewMeter().Snapshot() if count := m.Count(); count != 0 { t.Errorf("m.Count(): 0 != %v\n", count) } @@ -79,13 +77,13 @@ m := NewMeter() for i := 0; i < 101; i++ { m.Mark(int64(i)) } - if count := m.Count(); count != 5050 { + if count := m.Snapshot().Count(); count != 5050 { t.Errorf("m.Count(): 5050 != %v\n", count) } for i := 0; i < 101; i++ { m.Mark(int64(i)) } - if count := m.Count(); count != 10100 { + if count := m.Snapshot().Count(); count != 10100 { t.Errorf("m.Count(): 10100 != %v\n", count) } }
diff --git ethereum/go-ethereum/metrics/metrics.go taikoxyz/taiko-geth/metrics/metrics.go index c206f1692407db306c75995aa37ffa9a0ba55a95..9ca8f115c0f789cfa2b7ab52069b7e0e4cb08d3a 100644 --- ethereum/go-ethereum/metrics/metrics.go +++ taikoxyz/taiko-geth/metrics/metrics.go @@ -9,7 +9,9 @@ import ( "os" "runtime/metrics" "runtime/pprof" + "strconv" "strings" + "syscall" "time"   "github.com/ethereum/go-ethereum/log" @@ -30,13 +32,35 @@ // enablerFlags is the CLI flag names to use to enable metrics collections. var enablerFlags = []string{"metrics"}   +// enablerEnvVars is the env var names to use to enable metrics collections. +var enablerEnvVars = []string{"GETH_METRICS"} + // expensiveEnablerFlags is the CLI flag names to use to enable metrics collections. var expensiveEnablerFlags = []string{"metrics.expensive"} + +// expensiveEnablerEnvVars is the env var names to use to enable metrics collections. +var expensiveEnablerEnvVars = []string{"GETH_METRICS_EXPENSIVE"}   // Init enables or disables the metrics system. Since we need this to run before // any other code gets to create meters and timers, we'll actually do an ugly hack // and peek into the command line args for the metrics flag. func init() { + for _, enabler := range enablerEnvVars { + if val, found := syscall.Getenv(enabler); found && !Enabled { + if enable, _ := strconv.ParseBool(val); enable { // ignore error, flag parser will choke on it later + log.Info("Enabling metrics collection") + Enabled = true + } + } + } + for _, enabler := range expensiveEnablerEnvVars { + if val, found := syscall.Getenv(enabler); found && !EnabledExpensive { + if enable, _ := strconv.ParseBool(val); enable { // ignore error, flag parser will choke on it later + log.Info("Enabling expensive metrics collection") + EnabledExpensive = true + } + } + } for _, arg := range os.Args { flag := strings.TrimLeft(arg, "-")   @@ -83,6 +107,12 @@ {Name: "/memory/classes/heap/released:bytes"}, {Name: "/memory/classes/heap/unused:bytes"}, {Name: "/sched/goroutines:goroutines"}, {Name: "/sched/latencies:seconds"}, // histogram +} + +func ReadRuntimeStats() *runtimeStats { + r := new(runtimeStats) + readRuntimeStats(r) + return r }   func readRuntimeStats(v *runtimeStats) {
diff --git ethereum/go-ethereum/metrics/metrics_test.go taikoxyz/taiko-geth/metrics/metrics_test.go index 534c44139b360031e1b228b2025cb351f90535db..2861d5f2caf61e051277d20e87342e704b0f461c 100644 --- ethereum/go-ethereum/metrics/metrics_test.go +++ taikoxyz/taiko-geth/metrics/metrics_test.go @@ -98,8 +98,8 @@ t := GetOrRegisterTimer("db.get.latency", nil) t.Time(func() { time.Sleep(10 * time.Millisecond) }) t.Update(1)   - fmt.Println(c.Count()) - fmt.Println(t.Min()) + fmt.Println(c.Snapshot().Count()) + fmt.Println(t.Snapshot().Min()) // Output: 17 // 1 }
diff --git ethereum/go-ethereum/metrics/opentsdb.go taikoxyz/taiko-geth/metrics/opentsdb.go index c9fd2e75d5e53600bdc5c4437144a7b5c4381747..e81690f94340eedf69afb19be393b8225f364092 100644 --- ethereum/go-ethereum/metrics/opentsdb.go +++ taikoxyz/taiko-geth/metrics/opentsdb.go @@ -3,6 +3,7 @@ import ( "bufio" "fmt" + "io" "log" "net" "os" @@ -57,26 +58,22 @@ } return shortHostName }   -func openTSDB(c *OpenTSDBConfig) error { - shortHostname := getShortHostname() - now := time.Now().Unix() +// writeRegistry writes the registry-metrics on the opentsb format. +func (c *OpenTSDBConfig) writeRegistry(w io.Writer, now int64, shortHostname string) { du := float64(c.DurationUnit) - conn, err := net.DialTCP("tcp", nil, c.Addr) - if nil != err { - return err - } - defer conn.Close() - w := bufio.NewWriter(conn) + c.Registry.Each(func(name string, i interface{}) { switch metric := i.(type) { case Counter: - fmt.Fprintf(w, "put %s.%s.count %d %d host=%s\n", c.Prefix, name, now, metric.Count(), shortHostname) + fmt.Fprintf(w, "put %s.%s.count %d %d host=%s\n", c.Prefix, name, now, metric.Snapshot().Count(), shortHostname) case CounterFloat64: - fmt.Fprintf(w, "put %s.%s.count %d %f host=%s\n", c.Prefix, name, now, metric.Count(), shortHostname) + fmt.Fprintf(w, "put %s.%s.count %d %f host=%s\n", c.Prefix, name, now, metric.Snapshot().Count(), shortHostname) case Gauge: - fmt.Fprintf(w, "put %s.%s.value %d %d host=%s\n", c.Prefix, name, now, metric.Value(), shortHostname) + fmt.Fprintf(w, "put %s.%s.value %d %d host=%s\n", c.Prefix, name, now, metric.Snapshot().Value(), shortHostname) case GaugeFloat64: - fmt.Fprintf(w, "put %s.%s.value %d %f host=%s\n", c.Prefix, name, now, metric.Value(), shortHostname) + fmt.Fprintf(w, "put %s.%s.value %d %f host=%s\n", c.Prefix, name, now, metric.Snapshot().Value(), shortHostname) + case GaugeInfo: + fmt.Fprintf(w, "put %s.%s.value %d %s host=%s\n", c.Prefix, name, now, metric.Snapshot().Value().String(), shortHostname) case Histogram: h := metric.Snapshot() ps := h.Percentiles([]float64{0.5, 0.75, 0.95, 0.99, 0.999}) @@ -115,7 +112,17 @@ fmt.Fprintf(w, "put %s.%s.five-minute %d %.2f host=%s\n", c.Prefix, name, now, t.Rate5(), shortHostname) fmt.Fprintf(w, "put %s.%s.fifteen-minute %d %.2f host=%s\n", c.Prefix, name, now, t.Rate15(), shortHostname) fmt.Fprintf(w, "put %s.%s.mean-rate %d %.2f host=%s\n", c.Prefix, name, now, t.RateMean(), shortHostname) } - w.Flush() }) +} + +func openTSDB(c *OpenTSDBConfig) error { + conn, err := net.DialTCP("tcp", nil, c.Addr) + if nil != err { + return err + } + defer conn.Close() + w := bufio.NewWriter(conn) + c.writeRegistry(w, time.Now().Unix(), getShortHostname()) + w.Flush() return nil }
diff --git ethereum/go-ethereum/metrics/opentsdb_test.go taikoxyz/taiko-geth/metrics/opentsdb_test.go index c43728960ed5cd3d7f5292c725c214ca7a8e3866..4548309f9c23d08c2a9b832ca71b091d6707e718 100644 --- ethereum/go-ethereum/metrics/opentsdb_test.go +++ taikoxyz/taiko-geth/metrics/opentsdb_test.go @@ -1,7 +1,11 @@ package metrics   import ( + "fmt" "net" + "os" + "strings" + "testing" "time" )   @@ -19,3 +23,44 @@ FlushInterval: 1 * time.Second, DurationUnit: time.Millisecond, }) } + +func TestExampleOpenTSB(t *testing.T) { + r := NewOrderedRegistry() + NewRegisteredGaugeInfo("foo", r).Update(GaugeInfoValue{"chain_id": "5"}) + NewRegisteredGaugeFloat64("pi", r).Update(3.14) + NewRegisteredCounter("months", r).Inc(12) + NewRegisteredCounterFloat64("tau", r).Inc(1.57) + NewRegisteredMeter("elite", r).Mark(1337) + NewRegisteredTimer("second", r).Update(time.Second) + NewRegisteredCounterFloat64("tau", r).Inc(1.57) + NewRegisteredCounterFloat64("tau", r).Inc(1.57) + + w := new(strings.Builder) + (&OpenTSDBConfig{ + Registry: r, + DurationUnit: time.Millisecond, + Prefix: "pre", + }).writeRegistry(w, 978307200, "hal9000") + + wantB, err := os.ReadFile("./testdata/opentsb.want") + if err != nil { + t.Fatal(err) + } + if have, want := w.String(), string(wantB); have != want { + t.Errorf("\nhave:\n%v\nwant:\n%v\n", have, want) + t.Logf("have vs want:\n%v", findFirstDiffPos(have, want)) + } +} + +func findFirstDiffPos(a, b string) string { + yy := strings.Split(b, "\n") + for i, x := range strings.Split(a, "\n") { + if i >= len(yy) { + return fmt.Sprintf("have:%d: %s\nwant:%d: <EOF>", i, x, i) + } + if y := yy[i]; x != y { + return fmt.Sprintf("have:%d: %s\nwant:%d: %s", i, x, i, y) + } + } + return "" +}
diff --git ethereum/go-ethereum/metrics/prometheus/collector.go taikoxyz/taiko-geth/metrics/prometheus/collector.go index 2bd9bf22ccae03fdb122401c9d3ffd1ad20419ce..25b258d56ab125d22f9a884720fd58afc1ee0a83 100644 --- ethereum/go-ethereum/metrics/prometheus/collector.go +++ taikoxyz/taiko-geth/metrics/prometheus/collector.go @@ -19,6 +19,7 @@ import ( "bytes" "fmt" + "sort" "strconv" "strings"   @@ -46,23 +47,55 @@ buff: &bytes.Buffer{}, } }   -func (c *collector) addCounter(name string, m metrics.Counter) { +// Add adds the metric i to the collector. This method returns an error if the +// metric type is not supported/known. +func (c *collector) Add(name string, i any) error { + switch m := i.(type) { + case metrics.Counter: + c.addCounter(name, m.Snapshot()) + case metrics.CounterFloat64: + c.addCounterFloat64(name, m.Snapshot()) + case metrics.Gauge: + c.addGauge(name, m.Snapshot()) + case metrics.GaugeFloat64: + c.addGaugeFloat64(name, m.Snapshot()) + case metrics.GaugeInfo: + c.addGaugeInfo(name, m.Snapshot()) + case metrics.Histogram: + c.addHistogram(name, m.Snapshot()) + case metrics.Meter: + c.addMeter(name, m.Snapshot()) + case metrics.Timer: + c.addTimer(name, m.Snapshot()) + case metrics.ResettingTimer: + c.addResettingTimer(name, m.Snapshot()) + default: + return fmt.Errorf("unknown prometheus metric type %T", i) + } + return nil +} + +func (c *collector) addCounter(name string, m metrics.CounterSnapshot) { c.writeGaugeCounter(name, m.Count()) }   -func (c *collector) addCounterFloat64(name string, m metrics.CounterFloat64) { +func (c *collector) addCounterFloat64(name string, m metrics.CounterFloat64Snapshot) { c.writeGaugeCounter(name, m.Count()) }   -func (c *collector) addGauge(name string, m metrics.Gauge) { +func (c *collector) addGauge(name string, m metrics.GaugeSnapshot) { c.writeGaugeCounter(name, m.Value()) }   -func (c *collector) addGaugeFloat64(name string, m metrics.GaugeFloat64) { +func (c *collector) addGaugeFloat64(name string, m metrics.GaugeFloat64Snapshot) { c.writeGaugeCounter(name, m.Value()) }   -func (c *collector) addHistogram(name string, m metrics.Histogram) { +func (c *collector) addGaugeInfo(name string, m metrics.GaugeInfoSnapshot) { + c.writeGaugeInfo(name, m.Value()) +} + +func (c *collector) addHistogram(name string, m metrics.HistogramSnapshot) { pv := []float64{0.5, 0.75, 0.95, 0.99, 0.999, 0.9999} ps := m.Percentiles(pv) c.writeSummaryCounter(name, m.Count()) @@ -73,11 +106,11 @@ } c.buff.WriteRune('\n') }   -func (c *collector) addMeter(name string, m metrics.Meter) { +func (c *collector) addMeter(name string, m metrics.MeterSnapshot) { c.writeGaugeCounter(name, m.Count()) }   -func (c *collector) addTimer(name string, m metrics.Timer) { +func (c *collector) addTimer(name string, m metrics.TimerSnapshot) { pv := []float64{0.5, 0.75, 0.95, 0.99, 0.999, 0.9999} ps := m.Percentiles(pv) c.writeSummaryCounter(name, m.Count()) @@ -88,18 +121,30 @@ } c.buff.WriteRune('\n') }   -func (c *collector) addResettingTimer(name string, m metrics.ResettingTimer) { - if len(m.Values()) <= 0 { +func (c *collector) addResettingTimer(name string, m metrics.ResettingTimerSnapshot) { + if m.Count() <= 0 { return } - ps := m.Percentiles([]float64{50, 95, 99}) - val := m.Values() - c.writeSummaryCounter(name, len(val)) + ps := m.Percentiles([]float64{0.50, 0.95, 0.99}) + c.writeSummaryCounter(name, m.Count()) c.buff.WriteString(fmt.Sprintf(typeSummaryTpl, mutateKey(name))) c.writeSummaryPercentile(name, "0.50", ps[0]) c.writeSummaryPercentile(name, "0.95", ps[1]) c.writeSummaryPercentile(name, "0.99", ps[2]) c.buff.WriteRune('\n') +} + +func (c *collector) writeGaugeInfo(name string, value metrics.GaugeInfoValue) { + name = mutateKey(name) + c.buff.WriteString(fmt.Sprintf(typeGaugeTpl, name)) + c.buff.WriteString(name) + c.buff.WriteString(" ") + var kvs []string + for k, v := range value { + kvs = append(kvs, fmt.Sprintf("%v=%q", k, v)) + } + sort.Strings(kvs) + c.buff.WriteString(fmt.Sprintf("{%v} 1\n\n", strings.Join(kvs, ", "))) }   func (c *collector) writeGaugeCounter(name string, value interface{}) {
diff --git ethereum/go-ethereum/metrics/prometheus/collector_test.go taikoxyz/taiko-geth/metrics/prometheus/collector_test.go index ff87c8e765e16a6b3e1ce55d98a86215ffa7e570..ea17aac4585fd8688f9d2734435265ab7dc20ece 100644 --- ethereum/go-ethereum/metrics/prometheus/collector_test.go +++ taikoxyz/taiko-geth/metrics/prometheus/collector_test.go @@ -1,11 +1,29 @@ +// Copyright 2023 The go-ethereum Authors +// This file is part of the go-ethereum library. +// +// The go-ethereum library is free software: you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// The go-ethereum library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>. + package prometheus   import ( + "fmt" "os" + "strings" "testing" - "time"   "github.com/ethereum/go-ethereum/metrics" + "github.com/ethereum/go-ethereum/metrics/internal" )   func TestMain(m *testing.M) { @@ -14,104 +32,34 @@ os.Exit(m.Run()) }   func TestCollector(t *testing.T) { - c := newCollector() - - counter := metrics.NewCounter() - counter.Inc(12345) - c.addCounter("test/counter", counter) - - counterfloat64 := metrics.NewCounterFloat64() - counterfloat64.Inc(54321.98) - c.addCounterFloat64("test/counter_float64", counterfloat64) - - gauge := metrics.NewGauge() - gauge.Update(23456) - c.addGauge("test/gauge", gauge) - - gaugeFloat64 := metrics.NewGaugeFloat64() - gaugeFloat64.Update(34567.89) - c.addGaugeFloat64("test/gauge_float64", gaugeFloat64) - - histogram := metrics.NewHistogram(&metrics.NilSample{}) - c.addHistogram("test/histogram", histogram) - - meter := metrics.NewMeter() - defer meter.Stop() - meter.Mark(9999999) - c.addMeter("test/meter", meter) - - timer := metrics.NewTimer() - defer timer.Stop() - timer.Update(20 * time.Millisecond) - timer.Update(21 * time.Millisecond) - timer.Update(22 * time.Millisecond) - timer.Update(120 * time.Millisecond) - timer.Update(23 * time.Millisecond) - timer.Update(24 * time.Millisecond) - c.addTimer("test/timer", timer) - - resettingTimer := metrics.NewResettingTimer() - resettingTimer.Update(10 * time.Millisecond) - resettingTimer.Update(11 * time.Millisecond) - resettingTimer.Update(12 * time.Millisecond) - resettingTimer.Update(120 * time.Millisecond) - resettingTimer.Update(13 * time.Millisecond) - resettingTimer.Update(14 * time.Millisecond) - c.addResettingTimer("test/resetting_timer", resettingTimer.Snapshot()) - - emptyResettingTimer := metrics.NewResettingTimer().Snapshot() - c.addResettingTimer("test/empty_resetting_timer", emptyResettingTimer) - - const expectedOutput = `# TYPE test_counter gauge -test_counter 12345 - -# TYPE test_counter_float64 gauge -test_counter_float64 54321.98 + var ( + c = newCollector() + want string + ) + internal.ExampleMetrics().Each(func(name string, i interface{}) { + c.Add(name, i) + }) + if wantB, err := os.ReadFile("./testdata/prometheus.want"); err != nil { + t.Fatal(err) + } else { + want = string(wantB) + } + if have := c.buff.String(); have != want { + t.Logf("have\n%v", have) + t.Logf("have vs want:\n%v", findFirstDiffPos(have, want)) + t.Fatalf("unexpected collector output") + } +}   -# TYPE test_gauge gauge -test_gauge 23456 - -# TYPE test_gauge_float64 gauge -test_gauge_float64 34567.89 - -# TYPE test_histogram_count counter -test_histogram_count 0 - -# TYPE test_histogram summary -test_histogram {quantile="0.5"} 0 -test_histogram {quantile="0.75"} 0 -test_histogram {quantile="0.95"} 0 -test_histogram {quantile="0.99"} 0 -test_histogram {quantile="0.999"} 0 -test_histogram {quantile="0.9999"} 0 - -# TYPE test_meter gauge -test_meter 9999999 - -# TYPE test_timer_count counter -test_timer_count 6 - -# TYPE test_timer summary -test_timer {quantile="0.5"} 2.25e+07 -test_timer {quantile="0.75"} 4.8e+07 -test_timer {quantile="0.95"} 1.2e+08 -test_timer {quantile="0.99"} 1.2e+08 -test_timer {quantile="0.999"} 1.2e+08 -test_timer {quantile="0.9999"} 1.2e+08 - -# TYPE test_resetting_timer_count counter -test_resetting_timer_count 6 - -# TYPE test_resetting_timer summary -test_resetting_timer {quantile="0.50"} 12000000 -test_resetting_timer {quantile="0.95"} 120000000 -test_resetting_timer {quantile="0.99"} 120000000 - -` - exp := c.buff.String() - if exp != expectedOutput { - t.Log("Expected Output:\n", expectedOutput) - t.Log("Actual Output:\n", exp) - t.Fatal("unexpected collector output") +func findFirstDiffPos(a, b string) string { + yy := strings.Split(b, "\n") + for i, x := range strings.Split(a, "\n") { + if i >= len(yy) { + return fmt.Sprintf("have:%d: %s\nwant:%d: <EOF>", i, x, i) + } + if y := yy[i]; x != y { + return fmt.Sprintf("have:%d: %s\nwant:%d: %s", i, x, i, y) + } } + return "" }
diff --git ethereum/go-ethereum/metrics/prometheus/prometheus.go taikoxyz/taiko-geth/metrics/prometheus/prometheus.go index d966fa9a86662c3c1480fc81a5a015a36d1f7b54..dbdeae6c7f7d3b1450e28c816432f9eca07e3953 100644 --- ethereum/go-ethereum/metrics/prometheus/prometheus.go +++ taikoxyz/taiko-geth/metrics/prometheus/prometheus.go @@ -41,25 +41,7 @@ c := newCollector()   for _, name := range names { i := reg.Get(name) - - switch m := i.(type) { - case metrics.Counter: - c.addCounter(name, m.Snapshot()) - case metrics.CounterFloat64: - c.addCounterFloat64(name, m.Snapshot()) - case metrics.Gauge: - c.addGauge(name, m.Snapshot()) - case metrics.GaugeFloat64: - c.addGaugeFloat64(name, m.Snapshot()) - case metrics.Histogram: - c.addHistogram(name, m.Snapshot()) - case metrics.Meter: - c.addMeter(name, m.Snapshot()) - case metrics.Timer: - c.addTimer(name, m.Snapshot()) - case metrics.ResettingTimer: - c.addResettingTimer(name, m.Snapshot()) - default: + if err := c.Add(name, i); err != nil { log.Warn("Unknown Prometheus metric type", "type", fmt.Sprintf("%T", i)) } }
diff --git ethereum/go-ethereum/metrics/prometheus/testdata/prometheus.want taikoxyz/taiko-geth/metrics/prometheus/testdata/prometheus.want new file mode 100644 index 0000000000000000000000000000000000000000..861c5f5cf0878883455a6ed449dd8de81cc1ff17 --- /dev/null +++ taikoxyz/taiko-geth/metrics/prometheus/testdata/prometheus.want @@ -0,0 +1,70 @@ +# TYPE system_cpu_schedlatency_count counter +system_cpu_schedlatency_count 5645 + +# TYPE system_cpu_schedlatency summary +system_cpu_schedlatency {quantile="0.5"} 0 +system_cpu_schedlatency {quantile="0.75"} 7168 +system_cpu_schedlatency {quantile="0.95"} 1.6777216e+07 +system_cpu_schedlatency {quantile="0.99"} 2.9360128e+07 +system_cpu_schedlatency {quantile="0.999"} 3.3554432e+07 +system_cpu_schedlatency {quantile="0.9999"} 3.3554432e+07 + +# TYPE system_memory_pauses_count counter +system_memory_pauses_count 14 + +# TYPE system_memory_pauses summary +system_memory_pauses {quantile="0.5"} 32768 +system_memory_pauses {quantile="0.75"} 57344 +system_memory_pauses {quantile="0.95"} 196608 +system_memory_pauses {quantile="0.99"} 196608 +system_memory_pauses {quantile="0.999"} 196608 +system_memory_pauses {quantile="0.9999"} 196608 + +# TYPE test_counter gauge +test_counter 12345 + +# TYPE test_counter_float64 gauge +test_counter_float64 54321.98 + +# TYPE test_gauge gauge +test_gauge 23456 + +# TYPE test_gauge_float64 gauge +test_gauge_float64 34567.89 + +# TYPE test_gauge_info gauge +test_gauge_info {arch="amd64", commit="7caa2d8163ae3132c1c2d6978c76610caee2d949", os="linux", protocol_versions="64 65 66", version="1.10.18-unstable"} 1 + +# TYPE test_histogram_count counter +test_histogram_count 3 + +# TYPE test_histogram summary +test_histogram {quantile="0.5"} 2 +test_histogram {quantile="0.75"} 3 +test_histogram {quantile="0.95"} 3 +test_histogram {quantile="0.99"} 3 +test_histogram {quantile="0.999"} 3 +test_histogram {quantile="0.9999"} 3 + +# TYPE test_meter gauge +test_meter 0 + +# TYPE test_resetting_timer_count counter +test_resetting_timer_count 6 + +# TYPE test_resetting_timer summary +test_resetting_timer {quantile="0.50"} 1.25e+07 +test_resetting_timer {quantile="0.95"} 1.2e+08 +test_resetting_timer {quantile="0.99"} 1.2e+08 + +# TYPE test_timer_count counter +test_timer_count 6 + +# TYPE test_timer summary +test_timer {quantile="0.5"} 2.25e+07 +test_timer {quantile="0.75"} 4.8e+07 +test_timer {quantile="0.95"} 1.2e+08 +test_timer {quantile="0.99"} 1.2e+08 +test_timer {quantile="0.999"} 1.2e+08 +test_timer {quantile="0.9999"} 1.2e+08 +
diff --git ethereum/go-ethereum/metrics/registry.go taikoxyz/taiko-geth/metrics/registry.go index ec6e37c54ffe5beb43f5d960f65a0f93ed5a0d40..8bfbc080420f0b66b80364bd45f2f900caede4e7 100644 --- ethereum/go-ethereum/metrics/registry.go +++ taikoxyz/taiko-geth/metrics/registry.go @@ -3,6 +3,7 @@ import ( "fmt" "reflect" + "sort" "strings" "sync" ) @@ -47,15 +48,37 @@ // Unregister the metric with the given name. Unregister(string) }   +type orderedRegistry struct { + StandardRegistry +} + +// Call the given function for each registered metric. +func (r *orderedRegistry) Each(f func(string, interface{})) { + var names []string + reg := r.registered() + for name := range reg { + names = append(names, name) + } + sort.Strings(names) + for _, name := range names { + f(name, reg[name]) + } +} + +// NewRegistry creates a new registry. +func NewRegistry() Registry { + return new(StandardRegistry) +} + +// NewOrderedRegistry creates a new ordered registry (for testing). +func NewOrderedRegistry() Registry { + return new(orderedRegistry) +} + // The standard implementation of a Registry uses sync.map // of names to metrics. type StandardRegistry struct { metrics sync.Map -} - -// Create a new registry. -func NewRegistry() Registry { - return &StandardRegistry{} }   // Call the given function for each registered metric. @@ -127,13 +150,13 @@ r.Each(func(name string, i interface{}) { values := make(map[string]interface{}) switch metric := i.(type) { case Counter: - values["count"] = metric.Count() + values["count"] = metric.Snapshot().Count() case CounterFloat64: - values["count"] = metric.Count() + values["count"] = metric.Snapshot().Count() case Gauge: - values["value"] = metric.Value() + values["value"] = metric.Snapshot().Value() case GaugeFloat64: - values["value"] = metric.Value() + values["value"] = metric.Snapshot().Value() case Healthcheck: values["error"] = nil metric.Check() @@ -191,7 +214,7 @@ }   func (r *StandardRegistry) loadOrRegister(name string, i interface{}) (interface{}, bool, bool) { switch i.(type) { - case Counter, CounterFloat64, Gauge, GaugeFloat64, Healthcheck, Histogram, Meter, Timer, ResettingTimer: + case Counter, CounterFloat64, Gauge, GaugeFloat64, GaugeInfo, Healthcheck, Histogram, Meter, Timer, ResettingTimer: default: return nil, false, false }
diff --git ethereum/go-ethereum/metrics/registry_test.go taikoxyz/taiko-geth/metrics/registry_test.go index 7cc5cf14fe557d77834098a24f195c9bd0fc91dc..75012dd4ac00a18b41feb424697e82856536a6d8 100644 --- ethereum/go-ethereum/metrics/registry_test.go +++ taikoxyz/taiko-geth/metrics/registry_test.go @@ -85,11 +85,11 @@ func TestRegistryGet(t *testing.T) { r := NewRegistry() r.Register("foo", NewCounter()) - if count := r.Get("foo").(Counter).Count(); count != 0 { + if count := r.Get("foo").(Counter).Snapshot().Count(); count != 0 { t.Fatal(count) } r.Get("foo").(Counter).Inc(1) - if count := r.Get("foo").(Counter).Count(); count != 1 { + if count := r.Get("foo").(Counter).Snapshot().Count(); count != 1 { t.Fatal(count) } }
diff --git ethereum/go-ethereum/metrics/resetting_sample.go taikoxyz/taiko-geth/metrics/resetting_sample.go index 43c1129cd0bc921c1ea10ed69ee2f63591f6ac01..c38ffcd3ec32af5c110c68015569d1dc2a2f328f 100644 --- ethereum/go-ethereum/metrics/resetting_sample.go +++ taikoxyz/taiko-geth/metrics/resetting_sample.go @@ -17,7 +17,7 @@ Sample }   // Snapshot returns a read-only copy of the sample with the original reset. -func (rs *resettingSample) Snapshot() Sample { +func (rs *resettingSample) Snapshot() SampleSnapshot { s := rs.Sample.Snapshot() rs.Sample.Clear() return s
diff --git ethereum/go-ethereum/metrics/resetting_timer.go taikoxyz/taiko-geth/metrics/resetting_timer.go index 8e23c8eeeaaa953906cad6cdebe8b3e41fee9b8b..6802e3fcea980bf4a17a0880aff8348a27c271f7 100644 --- ethereum/go-ethereum/metrics/resetting_timer.go +++ taikoxyz/taiko-geth/metrics/resetting_timer.go @@ -1,22 +1,24 @@ package metrics   import ( - "math" "sync" "time" - - "golang.org/x/exp/slices" )   // Initial slice capacity for the values stored in a ResettingTimer const InitialResettingTimerSliceCap = 10   +type ResettingTimerSnapshot interface { + Count() int + Mean() float64 + Max() int64 + Min() int64 + Percentiles([]float64) []float64 +} + // ResettingTimer is used for storing aggregated values for timers, which are reset on every flush interval. type ResettingTimer interface { - Values() []int64 - Snapshot() ResettingTimer - Percentiles([]float64) []int64 - Mean() float64 + Snapshot() ResettingTimerSnapshot Time(func()) Update(time.Duration) UpdateSince(time.Time) @@ -52,70 +54,40 @@ } }   // NilResettingTimer is a no-op ResettingTimer. -type NilResettingTimer struct { -} - -// Values is a no-op. -func (NilResettingTimer) Values() []int64 { return nil } - -// Snapshot is a no-op. -func (NilResettingTimer) Snapshot() ResettingTimer { - return &ResettingTimerSnapshot{ - values: []int64{}, - } -} +type NilResettingTimer struct{}   -// Time is a no-op. -func (NilResettingTimer) Time(f func()) { f() } - -// Update is a no-op. -func (NilResettingTimer) Update(time.Duration) {} - -// Percentiles panics. -func (NilResettingTimer) Percentiles([]float64) []int64 { - panic("Percentiles called on a NilResettingTimer") -} - -// Mean panics. -func (NilResettingTimer) Mean() float64 { - panic("Mean called on a NilResettingTimer") -} - -// UpdateSince is a no-op. -func (NilResettingTimer) UpdateSince(time.Time) {} +func (NilResettingTimer) Values() []int64 { return nil } +func (n NilResettingTimer) Snapshot() ResettingTimerSnapshot { return n } +func (NilResettingTimer) Time(f func()) { f() } +func (NilResettingTimer) Update(time.Duration) {} +func (NilResettingTimer) Percentiles([]float64) []float64 { return nil } +func (NilResettingTimer) Mean() float64 { return 0.0 } +func (NilResettingTimer) Max() int64 { return 0 } +func (NilResettingTimer) Min() int64 { return 0 } +func (NilResettingTimer) UpdateSince(time.Time) {} +func (NilResettingTimer) Count() int { return 0 }   // StandardResettingTimer is the standard implementation of a ResettingTimer. // and Meter. type StandardResettingTimer struct { values []int64 - mutex sync.Mutex -} + sum int64 // sum is a running count of the total sum, used later to calculate mean   -// Values returns a slice with all measurements. -func (t *StandardResettingTimer) Values() []int64 { - return t.values + mutex sync.Mutex }   // Snapshot resets the timer and returns a read-only copy of its contents. -func (t *StandardResettingTimer) Snapshot() ResettingTimer { +func (t *StandardResettingTimer) Snapshot() ResettingTimerSnapshot { t.mutex.Lock() defer t.mutex.Unlock() - currentValues := t.values - t.values = make([]int64, 0, InitialResettingTimerSliceCap) - - return &ResettingTimerSnapshot{ - values: currentValues, + snapshot := &resettingTimerSnapshot{} + if len(t.values) > 0 { + snapshot.mean = float64(t.sum) / float64(len(t.values)) + snapshot.values = t.values + t.values = make([]int64, 0, InitialResettingTimerSliceCap) } -} - -// Percentiles panics. -func (t *StandardResettingTimer) Percentiles([]float64) []int64 { - panic("Percentiles called on a StandardResettingTimer") -} - -// Mean panics. -func (t *StandardResettingTimer) Mean() float64 { - panic("Mean called on a StandardResettingTimer") + t.sum = 0 + return snapshot }   // Record the duration of the execution of the given function. @@ -130,106 +102,70 @@ func (t *StandardResettingTimer) Update(d time.Duration) { t.mutex.Lock() defer t.mutex.Unlock() t.values = append(t.values, int64(d)) + t.sum += int64(d) }   // Record the duration of an event that started at a time and ends now. func (t *StandardResettingTimer) UpdateSince(ts time.Time) { - t.mutex.Lock() - defer t.mutex.Unlock() - t.values = append(t.values, int64(time.Since(ts))) + t.Update(time.Since(ts)) }   -// ResettingTimerSnapshot is a point-in-time copy of another ResettingTimer. -type ResettingTimerSnapshot struct { +// resettingTimerSnapshot is a point-in-time copy of another ResettingTimer. +type resettingTimerSnapshot struct { values []int64 mean float64 - thresholdBoundaries []int64 + max int64 + min int64 + thresholdBoundaries []float64 calculated bool }   -// Snapshot returns the snapshot. -func (t *ResettingTimerSnapshot) Snapshot() ResettingTimer { return t } - -// Time panics. -func (*ResettingTimerSnapshot) Time(func()) { - panic("Time called on a ResettingTimerSnapshot") -} - -// Update panics. -func (*ResettingTimerSnapshot) Update(time.Duration) { - panic("Update called on a ResettingTimerSnapshot") -} - -// UpdateSince panics. -func (*ResettingTimerSnapshot) UpdateSince(time.Time) { - panic("UpdateSince called on a ResettingTimerSnapshot") -} - -// Values returns all values from snapshot. -func (t *ResettingTimerSnapshot) Values() []int64 { - return t.values +// Count return the length of the values from snapshot. +func (t *resettingTimerSnapshot) Count() int { + return len(t.values) }   // Percentiles returns the boundaries for the input percentiles. -func (t *ResettingTimerSnapshot) Percentiles(percentiles []float64) []int64 { +// note: this method is not thread safe +func (t *resettingTimerSnapshot) Percentiles(percentiles []float64) []float64 { t.calc(percentiles) - return t.thresholdBoundaries }   // Mean returns the mean of the snapshotted values -func (t *ResettingTimerSnapshot) Mean() float64 { +// note: this method is not thread safe +func (t *resettingTimerSnapshot) Mean() float64 { if !t.calculated { - t.calc([]float64{}) + t.calc(nil) }   return t.mean }   -func (t *ResettingTimerSnapshot) calc(percentiles []float64) { - slices.Sort(t.values) - - count := len(t.values) - if count > 0 { - min := t.values[0] - max := t.values[count-1] - - cumulativeValues := make([]int64, count) - cumulativeValues[0] = min - for i := 1; i < count; i++ { - cumulativeValues[i] = t.values[i] + cumulativeValues[i-1] - } - - t.thresholdBoundaries = make([]int64, len(percentiles)) - - thresholdBoundary := max - - for i, pct := range percentiles { - if count > 1 { - var abs float64 - if pct >= 0 { - abs = pct - } else { - abs = 100 + pct - } - // poor man's math.Round(x): - // math.Floor(x + 0.5) - indexOfPerc := int(math.Floor(((abs / 100.0) * float64(count)) + 0.5)) - if pct >= 0 && indexOfPerc > 0 { - indexOfPerc -= 1 // index offset=0 - } - thresholdBoundary = t.values[indexOfPerc] - } - - t.thresholdBoundaries[i] = thresholdBoundary - } +// Max returns the max of the snapshotted values +// note: this method is not thread safe +func (t *resettingTimerSnapshot) Max() int64 { + if !t.calculated { + t.calc(nil) + } + return t.max +}   - sum := cumulativeValues[count-1] - t.mean = float64(sum) / float64(count) - } else { - t.thresholdBoundaries = make([]int64, len(percentiles)) - t.mean = 0 +// Min returns the min of the snapshotted values +// note: this method is not thread safe +func (t *resettingTimerSnapshot) Min() int64 { + if !t.calculated { + t.calc(nil) } + return t.min +}   - t.calculated = true +func (t *resettingTimerSnapshot) calc(percentiles []float64) { + scores := CalculatePercentiles(t.values, percentiles) + t.thresholdBoundaries = scores + if len(t.values) == 0 { + return + } + t.min = t.values[0] + t.max = t.values[len(t.values)-1] }
diff --git ethereum/go-ethereum/metrics/resetting_timer_test.go taikoxyz/taiko-geth/metrics/resetting_timer_test.go index 77c49dc3866aaead7be3703c9b2b7c0e267e9b4e..4571fc8eb052b6b3babcf166fc009a1eab03b683 100644 --- ethereum/go-ethereum/metrics/resetting_timer_test.go +++ taikoxyz/taiko-geth/metrics/resetting_timer_test.go @@ -10,9 +10,9 @@ tests := []struct { values []int64 start int end int - wantP50 int64 - wantP95 int64 - wantP99 int64 + wantP50 float64 + wantP95 float64 + wantP99 float64 wantMean float64 wantMin int64 wantMax int64 @@ -21,14 +21,14 @@ { values: []int64{}, start: 1, end: 11, - wantP50: 5, wantP95: 10, wantP99: 10, + wantP50: 5.5, wantP95: 10, wantP99: 10, wantMin: 1, wantMax: 10, wantMean: 5.5, }, { values: []int64{}, start: 1, end: 101, - wantP50: 50, wantP95: 95, wantP99: 99, + wantP50: 50.5, wantP95: 95.94999999999999, wantP99: 99.99, wantMin: 1, wantMax: 100, wantMean: 50.5, }, { @@ -56,11 +56,11 @@ { values: []int64{1, 10}, start: 0, end: 0, - wantP50: 1, wantP95: 10, wantP99: 10, + wantP50: 5.5, wantP95: 10, wantP99: 10, wantMin: 1, wantMax: 10, wantMean: 5.5, }, } - for ind, tt := range tests { + for i, tt := range tests { timer := NewResettingTimer()   for i := tt.start; i < tt.end; i++ { @@ -70,37 +70,27 @@ for _, v := range tt.values { timer.Update(time.Duration(v)) } - snap := timer.Snapshot()   - ps := snap.Percentiles([]float64{50, 95, 99}) + ps := snap.Percentiles([]float64{0.50, 0.95, 0.99})   - val := snap.Values() - - if len(val) > 0 { - if tt.wantMin != val[0] { - t.Fatalf("%d: min: got %d, want %d", ind, val[0], tt.wantMin) - } - - if tt.wantMax != val[len(val)-1] { - t.Fatalf("%d: max: got %d, want %d", ind, val[len(val)-1], tt.wantMax) - } + if have, want := snap.Min(), tt.wantMin; have != want { + t.Fatalf("%d: min: have %d, want %d", i, have, want) + } + if have, want := snap.Max(), tt.wantMax; have != want { + t.Fatalf("%d: max: have %d, want %d", i, have, want) } - - if tt.wantMean != snap.Mean() { - t.Fatalf("%d: mean: got %.2f, want %.2f", ind, snap.Mean(), tt.wantMean) + if have, want := snap.Mean(), tt.wantMean; have != want { + t.Fatalf("%d: mean: have %v, want %v", i, have, want) } - - if tt.wantP50 != ps[0] { - t.Fatalf("%d: p50: got %d, want %d", ind, ps[0], tt.wantP50) + if have, want := ps[0], tt.wantP50; have != want { + t.Errorf("%d: p50: have %v, want %v", i, have, want) } - - if tt.wantP95 != ps[1] { - t.Fatalf("%d: p95: got %d, want %d", ind, ps[1], tt.wantP95) + if have, want := ps[1], tt.wantP95; have != want { + t.Errorf("%d: p95: have %v, want %v", i, have, want) } - - if tt.wantP99 != ps[2] { - t.Fatalf("%d: p99: got %d, want %d", ind, ps[2], tt.wantP99) + if have, want := ps[2], tt.wantP99; have != want { + t.Errorf("%d: p99: have %v, want %v", i, have, want) } } } @@ -110,11 +100,11 @@ tests := []struct { values []int64 start int end int - wantP05 int64 - wantP20 int64 - wantP50 int64 - wantP95 int64 - wantP99 int64 + wantP05 float64 + wantP20 float64 + wantP50 float64 + wantP95 float64 + wantP99 float64 wantMean float64 wantMin int64 wantMax int64 @@ -123,14 +113,14 @@ { values: []int64{}, start: 1, end: 11, - wantP05: 1, wantP20: 2, wantP50: 5, wantP95: 10, wantP99: 10, + wantP05: 1, wantP20: 2.2, wantP50: 5.5, wantP95: 10, wantP99: 10, wantMin: 1, wantMax: 10, wantMean: 5.5, }, { values: []int64{}, start: 1, end: 101, - wantP05: 5, wantP20: 20, wantP50: 50, wantP95: 95, wantP99: 99, + wantP05: 5.050000000000001, wantP20: 20.200000000000003, wantP50: 50.5, wantP95: 95.94999999999999, wantP99: 99.99, wantMin: 1, wantMax: 100, wantMean: 50.5, }, { @@ -158,7 +148,7 @@ { values: []int64{1, 10}, start: 0, end: 0, - wantP05: 1, wantP20: 1, wantP50: 1, wantP95: 10, wantP99: 10, + wantP05: 1, wantP20: 1, wantP50: 5.5, wantP95: 10, wantP99: 10, wantMin: 1, wantMax: 10, wantMean: 5.5, }, } @@ -175,42 +165,33 @@ }   snap := timer.Snapshot()   - ps := snap.Percentiles([]float64{5, 20, 50, 95, 99}) - - val := snap.Values() + ps := snap.Percentiles([]float64{0.05, 0.20, 0.50, 0.95, 0.99})   - if len(val) > 0 { - if tt.wantMin != val[0] { - t.Fatalf("%d: min: got %d, want %d", ind, val[0], tt.wantMin) - } + if tt.wantMin != snap.Min() { + t.Errorf("%d: min: got %d, want %d", ind, snap.Min(), tt.wantMin) + }   - if tt.wantMax != val[len(val)-1] { - t.Fatalf("%d: max: got %d, want %d", ind, val[len(val)-1], tt.wantMax) - } + if tt.wantMax != snap.Max() { + t.Errorf("%d: max: got %d, want %d", ind, snap.Max(), tt.wantMax) }   if tt.wantMean != snap.Mean() { - t.Fatalf("%d: mean: got %.2f, want %.2f", ind, snap.Mean(), tt.wantMean) + t.Errorf("%d: mean: got %.2f, want %.2f", ind, snap.Mean(), tt.wantMean) } - if tt.wantP05 != ps[0] { - t.Fatalf("%d: p05: got %d, want %d", ind, ps[0], tt.wantP05) + t.Errorf("%d: p05: got %v, want %v", ind, ps[0], tt.wantP05) } - if tt.wantP20 != ps[1] { - t.Fatalf("%d: p20: got %d, want %d", ind, ps[1], tt.wantP20) + t.Errorf("%d: p20: got %v, want %v", ind, ps[1], tt.wantP20) } - if tt.wantP50 != ps[2] { - t.Fatalf("%d: p50: got %d, want %d", ind, ps[2], tt.wantP50) + t.Errorf("%d: p50: got %v, want %v", ind, ps[2], tt.wantP50) } - if tt.wantP95 != ps[3] { - t.Fatalf("%d: p95: got %d, want %d", ind, ps[3], tt.wantP95) + t.Errorf("%d: p95: got %v, want %v", ind, ps[3], tt.wantP95) } - if tt.wantP99 != ps[4] { - t.Fatalf("%d: p99: got %d, want %d", ind, ps[4], tt.wantP99) + t.Errorf("%d: p99: got %v, want %v", ind, ps[4], tt.wantP99) } } }
diff --git ethereum/go-ethereum/metrics/runtimehistogram.go taikoxyz/taiko-geth/metrics/runtimehistogram.go index c68939af1ef7278feb875deecb2e56f29d681541..92fcbcc2814c21030dad3e34044cf8849c0c8033 100644 --- ethereum/go-ethereum/metrics/runtimehistogram.go +++ taikoxyz/taiko-geth/metrics/runtimehistogram.go @@ -17,13 +17,19 @@ }   // runtimeHistogram wraps a runtime/metrics histogram. type runtimeHistogram struct { - v atomic.Value + v atomic.Value // v is a pointer to a metrics.Float64Histogram scaleFactor float64 }   func newRuntimeHistogram(scale float64) *runtimeHistogram { h := &runtimeHistogram{scaleFactor: scale} - h.update(&metrics.Float64Histogram{}) + h.update(new(metrics.Float64Histogram)) + return h +} + +func RuntimeHistogramFromData(scale float64, hist *metrics.Float64Histogram) *runtimeHistogram { + h := &runtimeHistogram{scaleFactor: scale} + h.update(hist) return h }   @@ -35,130 +41,107 @@ // conditionals everywhere. return }   - s := runtimeHistogramSnapshot{ + s := metrics.Float64Histogram{ Counts: make([]uint64, len(mh.Counts)), Buckets: make([]float64, len(mh.Buckets)), } copy(s.Counts, mh.Counts) - copy(s.Buckets, mh.Buckets) - for i, b := range s.Buckets { + for i, b := range mh.Buckets { s.Buckets[i] = b * h.scaleFactor } h.v.Store(&s) }   -func (h *runtimeHistogram) load() *runtimeHistogramSnapshot { - return h.v.Load().(*runtimeHistogramSnapshot) -} - func (h *runtimeHistogram) Clear() { panic("runtimeHistogram does not support Clear") } func (h *runtimeHistogram) Update(int64) { panic("runtimeHistogram does not support Update") } -func (h *runtimeHistogram) Sample() Sample { - return NilSample{} -}   -// Snapshot returns a non-changing cop of the histogram. -func (h *runtimeHistogram) Snapshot() Histogram { - return h.load() +// Snapshot returns a non-changing copy of the histogram. +func (h *runtimeHistogram) Snapshot() HistogramSnapshot { + hist := h.v.Load().(*metrics.Float64Histogram) + return newRuntimeHistogramSnapshot(hist) }   -// Count returns the sample count. -func (h *runtimeHistogram) Count() int64 { - return h.load().Count() +type runtimeHistogramSnapshot struct { + internal *metrics.Float64Histogram + calculated bool + // The following fields are (lazily) calculated based on 'internal' + mean float64 + count int64 + min int64 // min is the lowest sample value. + max int64 // max is the highest sample value. + variance float64 }   -// Mean returns an approximation of the mean. -func (h *runtimeHistogram) Mean() float64 { - return h.load().Mean() +func newRuntimeHistogramSnapshot(h *metrics.Float64Histogram) *runtimeHistogramSnapshot { + return &runtimeHistogramSnapshot{ + internal: h, + } }   -// StdDev approximates the standard deviation of the histogram. -func (h *runtimeHistogram) StdDev() float64 { - return h.load().StdDev() -} - -// Variance approximates the variance of the histogram. -func (h *runtimeHistogram) Variance() float64 { - return h.load().Variance() -} - -// Percentile computes the p'th percentile value. -func (h *runtimeHistogram) Percentile(p float64) float64 { - return h.load().Percentile(p) -} - -// Percentiles computes all requested percentile values. -func (h *runtimeHistogram) Percentiles(ps []float64) []float64 { - return h.load().Percentiles(ps) -} - -// Max returns the highest sample value. -func (h *runtimeHistogram) Max() int64 { - return h.load().Max() -} - -// Min returns the lowest sample value. -func (h *runtimeHistogram) Min() int64 { - return h.load().Min() -} - -// Sum returns the sum of all sample values. -func (h *runtimeHistogram) Sum() int64 { - return h.load().Sum() -} - -type runtimeHistogramSnapshot metrics.Float64Histogram - -func (h *runtimeHistogramSnapshot) Clear() { - panic("runtimeHistogram does not support Clear") -} -func (h *runtimeHistogramSnapshot) Update(int64) { - panic("runtimeHistogram does not support Update") -} -func (h *runtimeHistogramSnapshot) Sample() Sample { - return NilSample{} -} - -func (h *runtimeHistogramSnapshot) Snapshot() Histogram { - return h +// calc calculates the values for the snapshot. This method is not threadsafe. +func (h *runtimeHistogramSnapshot) calc() { + h.calculated = true + var ( + count int64 // number of samples + sum float64 // approx sum of all sample values + min int64 + max float64 + ) + if len(h.internal.Counts) == 0 { + return + } + for i, c := range h.internal.Counts { + if c == 0 { + continue + } + if count == 0 { // Set min only first loop iteration + min = int64(math.Floor(h.internal.Buckets[i])) + } + count += int64(c) + sum += h.midpoint(i) * float64(c) + // Set max on every iteration + edge := h.internal.Buckets[i+1] + if math.IsInf(edge, 1) { + edge = h.internal.Buckets[i] + } + if edge > max { + max = edge + } + } + h.min = min + h.max = int64(max) + h.mean = sum / float64(count) + h.count = count }   // Count returns the sample count. func (h *runtimeHistogramSnapshot) Count() int64 { - var count int64 - for _, c := range h.Counts { - count += int64(c) + if !h.calculated { + h.calc() } - return count + return h.count +} + +// Size returns the size of the sample at the time the snapshot was taken. +func (h *runtimeHistogramSnapshot) Size() int { + return len(h.internal.Counts) }   // Mean returns an approximation of the mean. func (h *runtimeHistogramSnapshot) Mean() float64 { - if len(h.Counts) == 0 { - return 0 + if !h.calculated { + h.calc() } - mean, _ := h.mean() - return mean -} - -// mean computes the mean and also the total sample count. -func (h *runtimeHistogramSnapshot) mean() (mean, totalCount float64) { - var sum float64 - for i, c := range h.Counts { - midpoint := h.midpoint(i) - sum += midpoint * float64(c) - totalCount += float64(c) - } - return sum / totalCount, totalCount + return h.mean }   func (h *runtimeHistogramSnapshot) midpoint(bucket int) float64 { - high := h.Buckets[bucket+1] - low := h.Buckets[bucket] + high := h.internal.Buckets[bucket+1] + low := h.internal.Buckets[bucket] if math.IsInf(high, 1) { // The edge of the highest bucket can be +Inf, and it's supposed to mean that this // bucket contains all remaining samples > low. We can't get the middle of an @@ -180,23 +163,31 @@ }   // Variance approximates the variance of the histogram. func (h *runtimeHistogramSnapshot) Variance() float64 { - if len(h.Counts) == 0 { + if len(h.internal.Counts) == 0 { return 0 } - - mean, totalCount := h.mean() - if totalCount <= 1 { + if !h.calculated { + h.calc() + } + if h.count <= 1 { // There is no variance when there are zero or one items. return 0 } - + // Variance is not calculated in 'calc', because it requires a second iteration. + // Therefore we calculate it lazily in this method, triggered either by + // a direct call to Variance or via StdDev. + if h.variance != 0.0 { + return h.variance + } var sum float64 - for i, c := range h.Counts { + + for i, c := range h.internal.Counts { midpoint := h.midpoint(i) - d := midpoint - mean + d := midpoint - h.mean sum += float64(c) * (d * d) } - return sum / (totalCount - 1) + h.variance = sum / float64(h.count-1) + return h.variance }   // Percentile computes the p'th percentile value. @@ -231,11 +222,11 @@ }   func (h *runtimeHistogramSnapshot) computePercentiles(thresh []float64) { var totalCount float64 - for i, count := range h.Counts { + for i, count := range h.internal.Counts { totalCount += float64(count)   for len(thresh) > 0 && thresh[0] < totalCount { - thresh[0] = h.Buckets[i] + thresh[0] = h.internal.Buckets[i] thresh = thresh[1:] } if len(thresh) == 0 { @@ -250,34 +241,25 @@ // also doesn't keep track of individual samples, so results are approximated.   // Max returns the highest sample value. func (h *runtimeHistogramSnapshot) Max() int64 { - for i := len(h.Counts) - 1; i >= 0; i-- { - count := h.Counts[i] - if count > 0 { - edge := h.Buckets[i+1] - if math.IsInf(edge, 1) { - edge = h.Buckets[i] - } - return int64(math.Ceil(edge)) - } + if !h.calculated { + h.calc() } - return 0 + return h.max }   // Min returns the lowest sample value. func (h *runtimeHistogramSnapshot) Min() int64 { - for i, count := range h.Counts { - if count > 0 { - return int64(math.Floor(h.Buckets[i])) - } + if !h.calculated { + h.calc() } - return 0 + return h.min }   // Sum returns the sum of all sample values. func (h *runtimeHistogramSnapshot) Sum() int64 { var sum float64 - for i := range h.Counts { - sum += h.Buckets[i] * float64(h.Counts[i]) + for i := range h.internal.Counts { + sum += h.internal.Buckets[i] * float64(h.internal.Counts[i]) } return int64(math.Ceil(sum)) }
diff --git ethereum/go-ethereum/metrics/runtimehistogram_test.go taikoxyz/taiko-geth/metrics/runtimehistogram_test.go index d53a01438311bbd5e58e7102b858c34dc397a1b6..cf7e36420ae9240ad88e031969f2986684362748 100644 --- ethereum/go-ethereum/metrics/runtimehistogram_test.go +++ taikoxyz/taiko-geth/metrics/runtimehistogram_test.go @@ -1,11 +1,14 @@ package metrics   import ( + "bytes" + "encoding/gob" "fmt" "math" "reflect" "runtime/metrics" "testing" + "time" )   var _ Histogram = (*runtimeHistogram)(nil) @@ -74,7 +77,7 @@ }   for i, test := range tests { t.Run(fmt.Sprint(i), func(t *testing.T) { - s := runtimeHistogramSnapshot(test.h) + s := RuntimeHistogramFromData(1.0, &test.h).Snapshot()   if v := s.Count(); v != test.Count { t.Errorf("Count() = %v, want %v", v, test.Count) @@ -121,13 +124,39 @@ // This test verifies that requesting Percentiles in unsorted order // returns them in the requested order. func TestRuntimeHistogramStatsPercentileOrder(t *testing.T) { - p := runtimeHistogramSnapshot{ + s := RuntimeHistogramFromData(1.0, &metrics.Float64Histogram{ Counts: []uint64{1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, Buckets: []float64{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10}, - } - result := p.Percentiles([]float64{1, 0.2, 0.5, 0.1, 0.2}) + }).Snapshot() + result := s.Percentiles([]float64{1, 0.2, 0.5, 0.1, 0.2}) expected := []float64{10, 2, 5, 1, 2} if !reflect.DeepEqual(result, expected) { t.Fatal("wrong result:", result) } } + +func BenchmarkRuntimeHistogramSnapshotRead(b *testing.B) { + var sLatency = "7\xff\x81\x03\x01\x01\x10Float64Histogram\x01\xff\x82\x00\x01\x02\x01\x06Counts\x01\xff\x84\x00\x01\aBuckets\x01\xff\x86\x00\x00\x00\x16\xff\x83\x02\x01\x01\b[]uint64\x01\xff\x84\x00\x01\x06\x00\x00\x17\xff\x85\x02\x01\x01\t[]float64\x01\xff\x86\x00\x01\b\x00\x00\xfe\x06T\xff\x82\x01\xff\xa2\x00\xfe\r\xef\x00\x01\x02\x02\x04\x05\x04\b\x15\x17 B?6.L;$!2) \x1a? \x190aH7FY6#\x190\x1d\x14\x10\x1b\r\t\x04\x03\x01\x01\x00\x03\x02\x00\x03\x05\x05\x02\x02\x06\x04\v\x06\n\x15\x18\x13'&.\x12=H/L&\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\xff\xa3\xfe\xf0\xff\x00\xf8\x95\xd6&\xe8\v.q>\xf8\x95\xd6&\xe8\v.\x81>\xf8\xdfA:\xdc\x11ʼn>\xf8\x95\xd6&\xe8\v.\x91>\xf8:\x8c0\xe2\x8ey\x95>\xf8\xdfA:\xdc\x11Å™>\xf8\x84\xf7CÖ”\x10\x9e>\xf8\x95\xd6&\xe8\v.\xa1>\xf8:\x8c0\xe2\x8ey\xa5>\xf8\xdfA:\xdc\x11Å©>\xf8\x84\xf7CÖ”\x10\xae>\xf8\x95\xd6&\xe8\v.\xb1>\xf8:\x8c0\xe2\x8ey\xb5>\xf8\xdfA:\xdc\x11Ź>\xf8\x84\xf7CÖ”\x10\xbe>\xf8\x95\xd6&\xe8\v.\xc1>\xf8:\x8c0\xe2\x8ey\xc5>\xf8\xdfA:\xdc\x11\xc5\xc9>\xf8\x84\xf7CÖ”\x10\xce>\xf8\x95\xd6&\xe8\v.\xd1>\xf8:\x8c0\xe2\x8ey\xd5>\xf8\xdfA:\xdc\x11\xc5\xd9>\xf8\x84\xf7CÖ”\x10\xde>\xf8\x95\xd6&\xe8\v.\xe1>\xf8:\x8c0\xe2\x8ey\xe5>\xf8\xdfA:\xdc\x11\xc5\xe9>\xf8\x84\xf7CÖ”\x10\xee>\xf8\x95\xd6&\xe8\v.\xf1>\xf8:\x8c0\xe2\x8ey\xf5>\xf8\xdfA:\xdc\x11\xc5\xf9>\xf8\x84\xf7CÖ”\x10\xfe>\xf8\x95\xd6&\xe8\v.\x01?\xf8:\x8c0\xe2\x8ey\x05?\xf8\xdfA:\xdc\x11\xc5\t?\xf8\x84\xf7CÖ”\x10\x0e?\xf8\x95\xd6&\xe8\v.\x11?\xf8:\x8c0\xe2\x8ey\x15?\xf8\xdfA:\xdc\x11\xc5\x19?\xf8\x84\xf7CÖ”\x10\x1e?\xf8\x95\xd6&\xe8\v.!?\xf8:\x8c0\xe2\x8ey%?\xf8\xdfA:\xdc\x11\xc5)?\xf8\x84\xf7CÖ”\x10.?\xf8\x95\xd6&\xe8\v.1?\xf8:\x8c0\xe2\x8ey5?\xf8\xdfA:\xdc\x11\xc59?\xf8\x84\xf7CÖ”\x10>?\xf8\x95\xd6&\xe8\v.A?\xf8:\x8c0\xe2\x8eyE?\xf8\xdfA:\xdc\x11\xc5I?\xf8\x84\xf7CÖ”\x10N?\xf8\x95\xd6&\xe8\v.Q?\xf8:\x8c0\xe2\x8eyU?\xf8\xdfA:\xdc\x11\xc5Y?\xf8\x84\xf7CÖ”\x10^?\xf8\x95\xd6&\xe8\v.a?\xf8:\x8c0\xe2\x8eye?\xf8\xdfA:\xdc\x11\xc5i?\xf8\x84\xf7CÖ”\x10n?\xf8\x95\xd6&\xe8\v.q?\xf8:\x8c0\xe2\x8eyu?\xf8\xdfA:\xdc\x11\xc5y?\xf8\x84\xf7CÖ”\x10~?\xf8\x95\xd6&\xe8\v.\x81?\xf8:\x8c0\xe2\x8ey\x85?\xf8\xdfA:\xdc\x11ʼn?\xf8\x84\xf7CÖ”\x10\x8e?\xf8\x95\xd6&\xe8\v.\x91?\xf8:\x8c0\xe2\x8ey\x95?\xf8\xdfA:\xdc\x11Å™?\xf8\x84\xf7CÖ”\x10\x9e?\xf8\x95\xd6&\xe8\v.\xa1?\xf8:\x8c0\xe2\x8ey\xa5?\xf8\xdfA:\xdc\x11Å©?\xf8\x84\xf7CÖ”\x10\xae?\xf8\x95\xd6&\xe8\v.\xb1?\xf8:\x8c0\xe2\x8ey\xb5?\xf8\xdfA:\xdc\x11Ź?\xf8\x84\xf7CÖ”\x10\xbe?\xf8\x95\xd6&\xe8\v.\xc1?\xf8:\x8c0\xe2\x8ey\xc5?\xf8\xdfA:\xdc\x11\xc5\xc9?\xf8\x84\xf7CÖ”\x10\xce?\xf8\x95\xd6&\xe8\v.\xd1?\xf8:\x8c0\xe2\x8ey\xd5?\xf8\xdfA:\xdc\x11\xc5\xd9?\xf8\x84\xf7CÖ”\x10\xde?\xf8\x95\xd6&\xe8\v.\xe1?\xf8:\x8c0\xe2\x8ey\xe5?\xf8\xdfA:\xdc\x11\xc5\xe9?\xf8\x84\xf7CÖ”\x10\xee?\xf8\x95\xd6&\xe8\v.\xf1?\xf8:\x8c0\xe2\x8ey\xf5?\xf8\xdfA:\xdc\x11\xc5\xf9?\xf8\x84\xf7CÖ”\x10\xfe?\xf8\x95\xd6&\xe8\v.\x01@\xf8:\x8c0\xe2\x8ey\x05@\xf8\xdfA:\xdc\x11\xc5\t@\xf8\x84\xf7CÖ”\x10\x0e@\xf8\x95\xd6&\xe8\v.\x11@\xf8:\x8c0\xe2\x8ey\x15@\xf8\xdfA:\xdc\x11\xc5\x19@\xf8\x84\xf7CÖ”\x10\x1e@\xf8\x95\xd6&\xe8\v.!@\xf8:\x8c0\xe2\x8ey%@\xf8\xdfA:\xdc\x11\xc5)@\xf8\x84\xf7CÖ”\x10.@\xf8\x95\xd6&\xe8\v.1@\xf8:\x8c0\xe2\x8ey5@\xf8\xdfA:\xdc\x11\xc59@\xf8\x84\xf7CÖ”\x10>@\xf8\x95\xd6&\xe8\v.A@\xf8:\x8c0\xe2\x8eyE@\xf8\xdfA:\xdc\x11\xc5I@\xf8\x84\xf7CÖ”\x10N@\xf8\x95\xd6&\xe8\v.Q@\xf8:\x8c0\xe2\x8eyU@\xf8\xdfA:\xdc\x11\xc5Y@\xf8\x84\xf7CÖ”\x10^@\xf8\x95\xd6&\xe8\v.a@\xf8:\x8c0\xe2\x8eye@\xf8\xdfA:\xdc\x11\xc5i@\xf8\x84\xf7CÖ”\x10n@\xf8\x95\xd6&\xe8\v.q@\xf8:\x8c0\xe2\x8eyu@\xf8\xdfA:\xdc\x11\xc5y@\xf8\x84\xf7CÖ”\x10~@\xf8\x95\xd6&\xe8\v.\x81@\xf8:\x8c0\xe2\x8ey\x85@\xf8\xdfA:\xdc\x11ʼn@\xf8\x84\xf7CÖ”\x10\x8e@\xf8\x95\xd6&\xe8\v.\x91@\xf8:\x8c0\xe2\x8ey\x95@\xf8\xdfA:\xdc\x11Å™@\xf8\x84\xf7CÖ”\x10\x9e@\xf8\x95\xd6&\xe8\v.\xa1@\xf8:\x8c0\xe2\x8ey\xa5@\xf8\xdfA:\xdc\x11Å©@\xf8\x84\xf7CÖ”\x10\xae@\xf8\x95\xd6&\xe8\v.\xb1@\xf8:\x8c0\xe2\x8ey\xb5@\xf8\xdfA:\xdc\x11Ź@\xf8\x84\xf7CÖ”\x10\xbe@\xf8\x95\xd6&\xe8\v.\xc1@\xf8:\x8c0\xe2\x8ey\xc5@\xf8\xdfA:\xdc\x11\xc5\xc9@\xf8\x84\xf7CÖ”\x10\xce@\xf8\x95\xd6&\xe8\v.\xd1@\xf8:\x8c0\xe2\x8ey\xd5@\xf8\xdfA:\xdc\x11\xc5\xd9@\xf8\x84\xf7CÖ”\x10\xde@\xf8\x95\xd6&\xe8\v.\xe1@\xf8:\x8c0\xe2\x8ey\xe5@\xf8\xdfA:\xdc\x11\xc5\xe9@\xf8\x84\xf7CÖ”\x10\xee@\xf8\x95\xd6&\xe8\v.\xf1@\xf8:\x8c0\xe2\x8ey\xf5@\xf8\xdfA:\xdc\x11\xc5\xf9@\xf8\x84\xf7CÖ”\x10\xfe@\xf8\x95\xd6&\xe8\v.\x01A\xfe\xf0\x7f\x00" + + dserialize := func(data string) *metrics.Float64Histogram { + var res metrics.Float64Histogram + if err := gob.NewDecoder(bytes.NewReader([]byte(data))).Decode(&res); err != nil { + panic(err) + } + return &res + } + latency := RuntimeHistogramFromData(float64(time.Second), dserialize(sLatency)) + b.ResetTimer() + b.ReportAllocs() + for i := 0; i < b.N; i++ { + snap := latency.Snapshot() + // These are the fields that influxdb accesses + _ = snap.Count() + _ = snap.Max() + _ = snap.Mean() + _ = snap.Min() + _ = snap.StdDev() + _ = snap.Variance() + _ = snap.Percentiles([]float64{0.25, 0.5, 0.75, 0.95, 0.99, 0.999, 0.9999}) + } +}
diff --git ethereum/go-ethereum/metrics/sample.go taikoxyz/taiko-geth/metrics/sample.go index 252a878f581ba3697668a818e97709c6ebaebf50..5398dd42d5de28675e981d8003933ccd64dc245a 100644 --- ethereum/go-ethereum/metrics/sample.go +++ taikoxyz/taiko-geth/metrics/sample.go @@ -11,10 +11,7 @@ )   const rescaleThreshold = time.Hour   -// Samples maintain a statistically-significant selection of values from -// a stream. -type Sample interface { - Clear() +type SampleSnapshot interface { Count() int64 Max() int64 Mean() float64 @@ -22,12 +19,17 @@ Min() int64 Percentile(float64) float64 Percentiles([]float64) []float64 Size() int - Snapshot() Sample StdDev() float64 Sum() int64 - Update(int64) - Values() []int64 Variance() float64 +} + +// Samples maintain a statistically-significant selection of values from +// a stream. +type Sample interface { + Snapshot() SampleSnapshot + Clear() + Update(int64) }   // ExpDecaySample is an exponentially-decaying sample using a forward-decaying @@ -77,72 +79,29 @@ s.t1 = s.t0.Add(rescaleThreshold) s.values.Clear() }   -// Count returns the number of samples recorded, which may exceed the -// reservoir size. -func (s *ExpDecaySample) Count() int64 { - s.mutex.Lock() - defer s.mutex.Unlock() - return s.count -} - -// Max returns the maximum value in the sample, which may not be the maximum -// value ever to be part of the sample. -func (s *ExpDecaySample) Max() int64 { - return SampleMax(s.Values()) -} - -// Mean returns the mean of the values in the sample. -func (s *ExpDecaySample) Mean() float64 { - return SampleMean(s.Values()) -} - -// Min returns the minimum value in the sample, which may not be the minimum -// value ever to be part of the sample. -func (s *ExpDecaySample) Min() int64 { - return SampleMin(s.Values()) -} - -// Percentile returns an arbitrary percentile of values in the sample. -func (s *ExpDecaySample) Percentile(p float64) float64 { - return SamplePercentile(s.Values(), p) -} - -// Percentiles returns a slice of arbitrary percentiles of values in the -// sample. -func (s *ExpDecaySample) Percentiles(ps []float64) []float64 { - return SamplePercentiles(s.Values(), ps) -} - -// Size returns the size of the sample, which is at most the reservoir size. -func (s *ExpDecaySample) Size() int { - s.mutex.Lock() - defer s.mutex.Unlock() - return s.values.Size() -} - // Snapshot returns a read-only copy of the sample. -func (s *ExpDecaySample) Snapshot() Sample { +func (s *ExpDecaySample) Snapshot() SampleSnapshot { s.mutex.Lock() defer s.mutex.Unlock() - vals := s.values.Values() - values := make([]int64, len(vals)) - for i, v := range vals { - values[i] = v.v - } - return &SampleSnapshot{ - count: s.count, - values: values, + var ( + samples = s.values.Values() + values = make([]int64, len(samples)) + max int64 = math.MinInt64 + min int64 = math.MaxInt64 + sum int64 + ) + for i, item := range samples { + v := item.v + values[i] = v + sum += v + if v > max { + max = v + } + if v < min { + min = v + } } -} - -// StdDev returns the standard deviation of the values in the sample. -func (s *ExpDecaySample) StdDev() float64 { - return SampleStdDev(s.Values()) -} - -// Sum returns the sum of the values in the sample. -func (s *ExpDecaySample) Sum() int64 { - return SampleSum(s.Values()) + return newSampleSnapshotPrecalculated(s.count, values, min, max, sum) }   // Update samples a new value. @@ -150,23 +109,6 @@ func (s *ExpDecaySample) Update(v int64) { s.update(time.Now(), v) }   -// Values returns a copy of the values in the sample. -func (s *ExpDecaySample) Values() []int64 { - s.mutex.Lock() - defer s.mutex.Unlock() - vals := s.values.Values() - values := make([]int64, len(vals)) - for i, v := range vals { - values[i] = v.v - } - return values -} - -// Variance returns the variance of the values in the sample. -func (s *ExpDecaySample) Variance() float64 { - return SampleVariance(s.Values()) -} - // update samples a new value at a particular timestamp. This is a method all // its own to facilitate testing. func (s *ExpDecaySample) update(t time.Time, v int64) { @@ -202,207 +144,160 @@ // NilSample is a no-op Sample. type NilSample struct{}   -// Clear is a no-op. -func (NilSample) Clear() {} - -// Count is a no-op. -func (NilSample) Count() int64 { return 0 } - -// Max is a no-op. -func (NilSample) Max() int64 { return 0 } - -// Mean is a no-op. -func (NilSample) Mean() float64 { return 0.0 } - -// Min is a no-op. -func (NilSample) Min() int64 { return 0 } - -// Percentile is a no-op. -func (NilSample) Percentile(p float64) float64 { return 0.0 } - -// Percentiles is a no-op. -func (NilSample) Percentiles(ps []float64) []float64 { - return make([]float64, len(ps)) -} - -// Size is a no-op. -func (NilSample) Size() int { return 0 } - -// Sample is a no-op. -func (NilSample) Snapshot() Sample { return NilSample{} } - -// StdDev is a no-op. -func (NilSample) StdDev() float64 { return 0.0 } - -// Sum is a no-op. -func (NilSample) Sum() int64 { return 0 } - -// Update is a no-op. -func (NilSample) Update(v int64) {} - -// Values is a no-op. -func (NilSample) Values() []int64 { return []int64{} } - -// Variance is a no-op. -func (NilSample) Variance() float64 { return 0.0 } - -// SampleMax returns the maximum value of the slice of int64. -func SampleMax(values []int64) int64 { - if len(values) == 0 { - return 0 - } - var max int64 = math.MinInt64 - for _, v := range values { - if max < v { - max = v - } - } - return max -} - -// SampleMean returns the mean value of the slice of int64. -func SampleMean(values []int64) float64 { - if len(values) == 0 { - return 0.0 - } - return float64(SampleSum(values)) / float64(len(values)) -} - -// SampleMin returns the minimum value of the slice of int64. -func SampleMin(values []int64) int64 { - if len(values) == 0 { - return 0 - } - var min int64 = math.MaxInt64 - for _, v := range values { - if min > v { - min = v - } - } - return min -} +func (NilSample) Clear() {} +func (NilSample) Snapshot() SampleSnapshot { return (*emptySnapshot)(nil) } +func (NilSample) Update(v int64) {}   // SamplePercentiles returns an arbitrary percentile of the slice of int64. func SamplePercentile(values []int64, p float64) float64 { - return SamplePercentiles(values, []float64{p})[0] + return CalculatePercentiles(values, []float64{p})[0] }   -// SamplePercentiles returns a slice of arbitrary percentiles of the slice of -// int64. -func SamplePercentiles(values []int64, ps []float64) []float64 { +// CalculatePercentiles returns a slice of arbitrary percentiles of the slice of +// int64. This method returns interpolated results, so e.g if there are only two +// values, [0, 10], a 50% percentile will land between them. +// +// Note: As a side-effect, this method will also sort the slice of values. +// Note2: The input format for percentiles is NOT percent! To express 50%, use 0.5, not 50. +func CalculatePercentiles(values []int64, ps []float64) []float64 { scores := make([]float64, len(ps)) size := len(values) - if size > 0 { - slices.Sort(values) - for i, p := range ps { - pos := p * float64(size+1) - if pos < 1.0 { - scores[i] = float64(values[0]) - } else if pos >= float64(size) { - scores[i] = float64(values[size-1]) - } else { - lower := float64(values[int(pos)-1]) - upper := float64(values[int(pos)]) - scores[i] = lower + (pos-math.Floor(pos))*(upper-lower) - } + if size == 0 { + return scores + } + slices.Sort(values) + for i, p := range ps { + pos := p * float64(size+1) + + if pos < 1.0 { + scores[i] = float64(values[0]) + } else if pos >= float64(size) { + scores[i] = float64(values[size-1]) + } else { + lower := float64(values[int(pos)-1]) + upper := float64(values[int(pos)]) + scores[i] = lower + (pos-math.Floor(pos))*(upper-lower) } } return scores }   -// SampleSnapshot is a read-only copy of another Sample. -type SampleSnapshot struct { +// sampleSnapshot is a read-only copy of another Sample. +type sampleSnapshot struct { count int64 values []int64 + + max int64 + min int64 + mean float64 + sum int64 + variance float64 }   -func NewSampleSnapshot(count int64, values []int64) *SampleSnapshot { - return &SampleSnapshot{ +// newSampleSnapshotPrecalculated creates a read-only sampleSnapShot, using +// precalculated sums to avoid iterating the values +func newSampleSnapshotPrecalculated(count int64, values []int64, min, max, sum int64) *sampleSnapshot { + if len(values) == 0 { + return &sampleSnapshot{ + count: count, + values: values, + } + } + return &sampleSnapshot{ count: count, values: values, + max: max, + min: min, + mean: float64(sum) / float64(len(values)), + sum: sum, } }   -// Clear panics. -func (*SampleSnapshot) Clear() { - panic("Clear called on a SampleSnapshot") +// newSampleSnapshot creates a read-only sampleSnapShot, and calculates some +// numbers. +func newSampleSnapshot(count int64, values []int64) *sampleSnapshot { + var ( + max int64 = math.MinInt64 + min int64 = math.MaxInt64 + sum int64 + ) + for _, v := range values { + sum += v + if v > max { + max = v + } + if v < min { + min = v + } + } + return newSampleSnapshotPrecalculated(count, values, min, max, sum) }   // Count returns the count of inputs at the time the snapshot was taken. -func (s *SampleSnapshot) Count() int64 { return s.count } +func (s *sampleSnapshot) Count() int64 { return s.count }   // Max returns the maximal value at the time the snapshot was taken. -func (s *SampleSnapshot) Max() int64 { return SampleMax(s.values) } +func (s *sampleSnapshot) Max() int64 { return s.max }   // Mean returns the mean value at the time the snapshot was taken. -func (s *SampleSnapshot) Mean() float64 { return SampleMean(s.values) } +func (s *sampleSnapshot) Mean() float64 { return s.mean }   // Min returns the minimal value at the time the snapshot was taken. -func (s *SampleSnapshot) Min() int64 { return SampleMin(s.values) } +func (s *sampleSnapshot) Min() int64 { return s.min }   // Percentile returns an arbitrary percentile of values at the time the // snapshot was taken. -func (s *SampleSnapshot) Percentile(p float64) float64 { +func (s *sampleSnapshot) Percentile(p float64) float64 { return SamplePercentile(s.values, p) }   // Percentiles returns a slice of arbitrary percentiles of values at the time // the snapshot was taken. -func (s *SampleSnapshot) Percentiles(ps []float64) []float64 { - return SamplePercentiles(s.values, ps) +func (s *sampleSnapshot) Percentiles(ps []float64) []float64 { + return CalculatePercentiles(s.values, ps) }   // Size returns the size of the sample at the time the snapshot was taken. -func (s *SampleSnapshot) Size() int { return len(s.values) } +func (s *sampleSnapshot) Size() int { return len(s.values) }   // Snapshot returns the snapshot. -func (s *SampleSnapshot) Snapshot() Sample { return s } +func (s *sampleSnapshot) Snapshot() SampleSnapshot { return s }   // StdDev returns the standard deviation of values at the time the snapshot was // taken. -func (s *SampleSnapshot) StdDev() float64 { return SampleStdDev(s.values) } +func (s *sampleSnapshot) StdDev() float64 { + if s.variance == 0.0 { + s.variance = SampleVariance(s.mean, s.values) + } + return math.Sqrt(s.variance) +}   // Sum returns the sum of values at the time the snapshot was taken. -func (s *SampleSnapshot) Sum() int64 { return SampleSum(s.values) } - -// Update panics. -func (*SampleSnapshot) Update(int64) { - panic("Update called on a SampleSnapshot") -} +func (s *sampleSnapshot) Sum() int64 { return s.sum }   // Values returns a copy of the values in the sample. -func (s *SampleSnapshot) Values() []int64 { +func (s *sampleSnapshot) Values() []int64 { values := make([]int64, len(s.values)) copy(values, s.values) return values }   // Variance returns the variance of values at the time the snapshot was taken. -func (s *SampleSnapshot) Variance() float64 { return SampleVariance(s.values) } - -// SampleStdDev returns the standard deviation of the slice of int64. -func SampleStdDev(values []int64) float64 { - return math.Sqrt(SampleVariance(values)) -} - -// SampleSum returns the sum of the slice of int64. -func SampleSum(values []int64) int64 { - var sum int64 - for _, v := range values { - sum += v +func (s *sampleSnapshot) Variance() float64 { + if s.variance == 0.0 { + s.variance = SampleVariance(s.mean, s.values) } - return sum + return s.variance }   // SampleVariance returns the variance of the slice of int64. -func SampleVariance(values []int64) float64 { +func SampleVariance(mean float64, values []int64) float64 { if len(values) == 0 { return 0.0 } - m := SampleMean(values) var sum float64 for _, v := range values { - d := float64(v) - m + d := float64(v) - mean sum += d * d } return sum / float64(len(values)) @@ -445,83 +340,14 @@ s.count = 0 s.values = make([]int64, 0, s.reservoirSize) }   -// Count returns the number of samples recorded, which may exceed the -// reservoir size. -func (s *UniformSample) Count() int64 { - s.mutex.Lock() - defer s.mutex.Unlock() - return s.count -} - -// Max returns the maximum value in the sample, which may not be the maximum -// value ever to be part of the sample. -func (s *UniformSample) Max() int64 { - s.mutex.Lock() - defer s.mutex.Unlock() - return SampleMax(s.values) -} - -// Mean returns the mean of the values in the sample. -func (s *UniformSample) Mean() float64 { - s.mutex.Lock() - defer s.mutex.Unlock() - return SampleMean(s.values) -} - -// Min returns the minimum value in the sample, which may not be the minimum -// value ever to be part of the sample. -func (s *UniformSample) Min() int64 { - s.mutex.Lock() - defer s.mutex.Unlock() - return SampleMin(s.values) -} - -// Percentile returns an arbitrary percentile of values in the sample. -func (s *UniformSample) Percentile(p float64) float64 { - s.mutex.Lock() - defer s.mutex.Unlock() - return SamplePercentile(s.values, p) -} - -// Percentiles returns a slice of arbitrary percentiles of values in the -// sample. -func (s *UniformSample) Percentiles(ps []float64) []float64 { - s.mutex.Lock() - defer s.mutex.Unlock() - return SamplePercentiles(s.values, ps) -} - -// Size returns the size of the sample, which is at most the reservoir size. -func (s *UniformSample) Size() int { - s.mutex.Lock() - defer s.mutex.Unlock() - return len(s.values) -} - // Snapshot returns a read-only copy of the sample. -func (s *UniformSample) Snapshot() Sample { +func (s *UniformSample) Snapshot() SampleSnapshot { s.mutex.Lock() - defer s.mutex.Unlock() values := make([]int64, len(s.values)) copy(values, s.values) - return &SampleSnapshot{ - count: s.count, - values: values, - } -} - -// StdDev returns the standard deviation of the values in the sample. -func (s *UniformSample) StdDev() float64 { - s.mutex.Lock() - defer s.mutex.Unlock() - return SampleStdDev(s.values) -} - -// Sum returns the sum of the values in the sample. -func (s *UniformSample) Sum() int64 { - s.mutex.Lock() - defer s.mutex.Unlock() - return SampleSum(s.values) + count := s.count + s.mutex.Unlock() + return newSampleSnapshot(count, values) }   // Update samples a new value. @@ -542,22 +368,6 @@ if r < int64(len(s.values)) { s.values[int(r)] = v } } -} - -// Values returns a copy of the values in the sample. -func (s *UniformSample) Values() []int64 { - s.mutex.Lock() - defer s.mutex.Unlock() - values := make([]int64, len(s.values)) - copy(values, s.values) - return values -} - -// Variance returns the variance of the values in the sample. -func (s *UniformSample) Variance() float64 { - s.mutex.Lock() - defer s.mutex.Unlock() - return SampleVariance(s.values) }   // expDecaySample represents an individual sample in a heap.
diff --git ethereum/go-ethereum/metrics/sample_test.go taikoxyz/taiko-geth/metrics/sample_test.go index 3ae128d56f67074030818d1f8f1b6f653a9105de..79673570554cb4e681ec185321077027fdbed2bf 100644 --- ethereum/go-ethereum/metrics/sample_test.go +++ taikoxyz/taiko-geth/metrics/sample_test.go @@ -8,28 +8,36 @@ "testing" "time" )   +const epsilonPercentile = .00000000001 + // Benchmark{Compute,Copy}{1000,1000000} demonstrate that, even for relatively // expensive computations like Variance, the cost of copying the Sample, as // approximated by a make and copy, is much greater than the cost of the // computation for small samples and only slightly less for large samples. func BenchmarkCompute1000(b *testing.B) { s := make([]int64, 1000) + var sum int64 for i := 0; i < len(s); i++ { s[i] = int64(i) + sum += int64(i) } + mean := float64(sum) / float64(len(s)) b.ResetTimer() for i := 0; i < b.N; i++ { - SampleVariance(s) + SampleVariance(mean, s) } } func BenchmarkCompute1000000(b *testing.B) { s := make([]int64, 1000000) + var sum int64 for i := 0; i < len(s); i++ { s[i] = int64(i) + sum += int64(i) } + mean := float64(sum) / float64(len(s)) b.ResetTimer() for i := 0; i < b.N; i++ { - SampleVariance(s) + SampleVariance(mean, s) } } func BenchmarkCopy1000(b *testing.B) { @@ -79,65 +87,42 @@ func BenchmarkUniformSample1028(b *testing.B) { benchmarkSample(b, NewUniformSample(1028)) }   -func TestExpDecaySample10(t *testing.T) { - s := NewExpDecaySample(100, 0.99) - for i := 0; i < 10; i++ { - s.Update(int64(i)) - } - if size := s.Count(); size != 10 { - t.Errorf("s.Count(): 10 != %v\n", size) - } - if size := s.Size(); size != 10 { - t.Errorf("s.Size(): 10 != %v\n", size) - } - if l := len(s.Values()); l != 10 { - t.Errorf("len(s.Values()): 10 != %v\n", l) +func min(a, b int) int { + if a < b { + return a } - for _, v := range s.Values() { - if v > 10 || v < 0 { - t.Errorf("out of range [0, 10): %v\n", v) - } - } + return b }   -func TestExpDecaySample100(t *testing.T) { - s := NewExpDecaySample(1000, 0.01) - for i := 0; i < 100; i++ { - s.Update(int64(i)) - } - if size := s.Count(); size != 100 { - t.Errorf("s.Count(): 100 != %v\n", size) - } - if size := s.Size(); size != 100 { - t.Errorf("s.Size(): 100 != %v\n", size) - } - if l := len(s.Values()); l != 100 { - t.Errorf("len(s.Values()): 100 != %v\n", l) - } - for _, v := range s.Values() { - if v > 100 || v < 0 { - t.Errorf("out of range [0, 100): %v\n", v) +func TestExpDecaySample(t *testing.T) { + for _, tc := range []struct { + reservoirSize int + alpha float64 + updates int + }{ + {100, 0.99, 10}, + {1000, 0.01, 100}, + {100, 0.99, 1000}, + } { + sample := NewExpDecaySample(tc.reservoirSize, tc.alpha) + for i := 0; i < tc.updates; i++ { + sample.Update(int64(i)) } - } -} - -func TestExpDecaySample1000(t *testing.T) { - s := NewExpDecaySample(100, 0.99) - for i := 0; i < 1000; i++ { - s.Update(int64(i)) - } - if size := s.Count(); size != 1000 { - t.Errorf("s.Count(): 1000 != %v\n", size) - } - if size := s.Size(); size != 100 { - t.Errorf("s.Size(): 100 != %v\n", size) - } - if l := len(s.Values()); l != 100 { - t.Errorf("len(s.Values()): 100 != %v\n", l) - } - for _, v := range s.Values() { - if v > 1000 || v < 0 { - t.Errorf("out of range [0, 1000): %v\n", v) + snap := sample.Snapshot() + if have, want := int(snap.Count()), tc.updates; have != want { + t.Errorf("have %d want %d", have, want) + } + if have, want := snap.Size(), min(tc.updates, tc.reservoirSize); have != want { + t.Errorf("have %d want %d", have, want) + } + values := snap.(*sampleSnapshot).values + if have, want := len(values), min(tc.updates, tc.reservoirSize); have != want { + t.Errorf("have %d want %d", have, want) + } + for _, v := range values { + if v > int64(tc.updates) || v < 0 { + t.Errorf("out of range [0, %d): %v", tc.updates, v) + } } } } @@ -147,15 +132,16 @@ // nanosecond duration since start rather than second duration since start. // The priority becomes +Inf quickly after starting if this is done, // effectively freezing the set of samples until a rescale step happens. func TestExpDecaySampleNanosecondRegression(t *testing.T) { - s := NewExpDecaySample(100, 0.99) + sw := NewExpDecaySample(100, 0.99) for i := 0; i < 100; i++ { - s.Update(10) + sw.Update(10) } time.Sleep(1 * time.Millisecond) for i := 0; i < 100; i++ { - s.Update(20) + sw.Update(20) } - v := s.Values() + s := sw.Snapshot() + v := s.(*sampleSnapshot).values avg := float64(0) for i := 0; i < len(v); i++ { avg += float64(v[i]) @@ -194,24 +180,27 @@ s := NewExpDecaySample(100, 0.99).(*ExpDecaySample).SetRand(rand.New(rand.NewSource(1))) for i := 1; i <= 10000; i++ { s.(*ExpDecaySample).update(now.Add(time.Duration(i)), int64(i)) } - testExpDecaySampleStatistics(t, s) + testExpDecaySampleStatistics(t, s.Snapshot()) }   func TestUniformSample(t *testing.T) { - s := NewUniformSample(100) + sw := NewUniformSample(100) for i := 0; i < 1000; i++ { - s.Update(int64(i)) + sw.Update(int64(i)) } + s := sw.Snapshot() if size := s.Count(); size != 1000 { t.Errorf("s.Count(): 1000 != %v\n", size) } if size := s.Size(); size != 100 { t.Errorf("s.Size(): 100 != %v\n", size) } - if l := len(s.Values()); l != 100 { + values := s.(*sampleSnapshot).values + + if l := len(values); l != 100 { t.Errorf("len(s.Values()): 100 != %v\n", l) } - for _, v := range s.Values() { + for _, v := range values { if v > 1000 || v < 0 { t.Errorf("out of range [0, 100): %v\n", v) } @@ -219,12 +208,13 @@ } }   func TestUniformSampleIncludesTail(t *testing.T) { - s := NewUniformSample(100) + sw := NewUniformSample(100) max := 100 for i := 0; i < max; i++ { - s.Update(int64(i)) + sw.Update(int64(i)) } - v := s.Values() + s := sw.Snapshot() + v := s.(*sampleSnapshot).values sum := 0 exp := (max - 1) * max / 2 for i := 0; i < len(v); i++ { @@ -250,7 +240,7 @@ s := NewUniformSample(100).(*UniformSample).SetRand(rand.New(rand.NewSource(1))) for i := 1; i <= 10000; i++ { s.Update(int64(i)) } - testUniformSampleStatistics(t, s) + testUniformSampleStatistics(t, s.Snapshot()) }   func benchmarkSample(b *testing.B, s Sample) { @@ -267,7 +257,7 @@ runtime.ReadMemStats(&memStats) b.Logf("GC cost: %d ns/op", int(memStats.PauseTotalNs-pauseTotalNs)/b.N) }   -func testExpDecaySampleStatistics(t *testing.T, s Sample) { +func testExpDecaySampleStatistics(t *testing.T, s SampleSnapshot) { if count := s.Count(); count != 10000 { t.Errorf("s.Count(): 10000 != %v\n", count) } @@ -295,7 +285,7 @@ t.Errorf("99th percentile: 9998.99 != %v\n", ps[2]) } }   -func testUniformSampleStatistics(t *testing.T, s Sample) { +func testUniformSampleStatistics(t *testing.T, s SampleSnapshot) { if count := s.Count(); count != 10000 { t.Errorf("s.Count(): 10000 != %v\n", count) } @@ -349,8 +339,22 @@ } } }() for i := 0; i < 1000; i++ { - s.Count() + s.Snapshot().Count() time.Sleep(5 * time.Millisecond) } quit <- struct{}{} } + +func BenchmarkCalculatePercentiles(b *testing.B) { + pss := []float64{0.5, 0.75, 0.95, 0.99, 0.999, 0.9999} + var vals []int64 + for i := 0; i < 1000; i++ { + vals = append(vals, int64(rand.Int31())) + } + v := make([]int64, len(vals)) + b.ResetTimer() + for i := 0; i < b.N; i++ { + copy(v, vals) + _ = CalculatePercentiles(v, pss) + } +}
diff --git ethereum/go-ethereum/metrics/syslog.go taikoxyz/taiko-geth/metrics/syslog.go index f23b07e199f32d6e1c392404603fc30f140cb72c..fd856d69731616fc0e33d95069c8222fa7b1f8bf 100644 --- ethereum/go-ethereum/metrics/syslog.go +++ taikoxyz/taiko-geth/metrics/syslog.go @@ -16,13 +16,15 @@ for range time.Tick(d) { r.Each(func(name string, i interface{}) { switch metric := i.(type) { case Counter: - w.Info(fmt.Sprintf("counter %s: count: %d", name, metric.Count())) + w.Info(fmt.Sprintf("counter %s: count: %d", name, metric.Snapshot().Count())) case CounterFloat64: - w.Info(fmt.Sprintf("counter %s: count: %f", name, metric.Count())) + w.Info(fmt.Sprintf("counter %s: count: %f", name, metric.Snapshot().Count())) case Gauge: - w.Info(fmt.Sprintf("gauge %s: value: %d", name, metric.Value())) + w.Info(fmt.Sprintf("gauge %s: value: %d", name, metric.Snapshot().Value())) case GaugeFloat64: - w.Info(fmt.Sprintf("gauge %s: value: %f", name, metric.Value())) + w.Info(fmt.Sprintf("gauge %s: value: %f", name, metric.Snapshot().Value())) + case GaugeInfo: + w.Info(fmt.Sprintf("gauge %s: value: %s", name, metric.Snapshot().Value())) case Healthcheck: metric.Check() w.Info(fmt.Sprintf("healthcheck %s: error: %v", name, metric.Error()))
diff --git ethereum/go-ethereum/metrics/testdata/opentsb.want taikoxyz/taiko-geth/metrics/testdata/opentsb.want new file mode 100644 index 0000000000000000000000000000000000000000..43fe1b2ac27a82f9d140de6bf22415fe7db11dc8 --- /dev/null +++ taikoxyz/taiko-geth/metrics/testdata/opentsb.want @@ -0,0 +1,23 @@ +put pre.elite.count 978307200 1337 host=hal9000 +put pre.elite.one-minute 978307200 0.00 host=hal9000 +put pre.elite.five-minute 978307200 0.00 host=hal9000 +put pre.elite.fifteen-minute 978307200 0.00 host=hal9000 +put pre.elite.mean 978307200 0.00 host=hal9000 +put pre.foo.value 978307200 {"chain_id":"5"} host=hal9000 +put pre.months.count 978307200 12 host=hal9000 +put pre.pi.value 978307200 3.140000 host=hal9000 +put pre.second.count 978307200 1 host=hal9000 +put pre.second.min 978307200 1000 host=hal9000 +put pre.second.max 978307200 1000 host=hal9000 +put pre.second.mean 978307200 1000.00 host=hal9000 +put pre.second.std-dev 978307200 0.00 host=hal9000 +put pre.second.50-percentile 978307200 1000.00 host=hal9000 +put pre.second.75-percentile 978307200 1000.00 host=hal9000 +put pre.second.95-percentile 978307200 1000.00 host=hal9000 +put pre.second.99-percentile 978307200 1000.00 host=hal9000 +put pre.second.999-percentile 978307200 1000.00 host=hal9000 +put pre.second.one-minute 978307200 0.00 host=hal9000 +put pre.second.five-minute 978307200 0.00 host=hal9000 +put pre.second.fifteen-minute 978307200 0.00 host=hal9000 +put pre.second.mean-rate 978307200 0.00 host=hal9000 +put pre.tau.count 978307200 1.570000 host=hal9000
diff --git ethereum/go-ethereum/metrics/timer.go taikoxyz/taiko-geth/metrics/timer.go index 2e1a9be47295f082b0ebabd97f9b44f7a1f691d5..576ad8aa3e63f9cfc89f9904a74a7e264c337efa 100644 --- ethereum/go-ethereum/metrics/timer.go +++ taikoxyz/taiko-geth/metrics/timer.go @@ -5,26 +5,18 @@ "sync" "time" )   +type TimerSnapshot interface { + HistogramSnapshot + MeterSnapshot +} + // Timers capture the duration and rate of events. type Timer interface { - Count() int64 - Max() int64 - Mean() float64 - Min() int64 - Percentile(float64) float64 - Percentiles([]float64) []float64 - Rate1() float64 - Rate5() float64 - Rate15() float64 - RateMean() float64 - Snapshot() Timer - StdDev() float64 + Snapshot() TimerSnapshot Stop() - Sum() int64 Time(func()) + UpdateSince(time.Time) Update(time.Duration) - UpdateSince(time.Time) - Variance() float64 }   // GetOrRegisterTimer returns an existing Timer or constructs and registers a @@ -78,61 +70,11 @@ // NilTimer is a no-op Timer. type NilTimer struct{}   -// Count is a no-op. -func (NilTimer) Count() int64 { return 0 } - -// Max is a no-op. -func (NilTimer) Max() int64 { return 0 } - -// Mean is a no-op. -func (NilTimer) Mean() float64 { return 0.0 } - -// Min is a no-op. -func (NilTimer) Min() int64 { return 0 } - -// Percentile is a no-op. -func (NilTimer) Percentile(p float64) float64 { return 0.0 } - -// Percentiles is a no-op. -func (NilTimer) Percentiles(ps []float64) []float64 { - return make([]float64, len(ps)) -} - -// Rate1 is a no-op. -func (NilTimer) Rate1() float64 { return 0.0 } - -// Rate5 is a no-op. -func (NilTimer) Rate5() float64 { return 0.0 } - -// Rate15 is a no-op. -func (NilTimer) Rate15() float64 { return 0.0 } - -// RateMean is a no-op. -func (NilTimer) RateMean() float64 { return 0.0 } - -// Snapshot is a no-op. -func (NilTimer) Snapshot() Timer { return NilTimer{} } - -// StdDev is a no-op. -func (NilTimer) StdDev() float64 { return 0.0 } - -// Stop is a no-op. -func (NilTimer) Stop() {} - -// Sum is a no-op. -func (NilTimer) Sum() int64 { return 0 } - -// Time is a no-op. -func (NilTimer) Time(f func()) { f() } - -// Update is a no-op. -func (NilTimer) Update(time.Duration) {} - -// UpdateSince is a no-op. -func (NilTimer) UpdateSince(time.Time) {} - -// Variance is a no-op. -func (NilTimer) Variance() float64 { return 0.0 } +func (NilTimer) Snapshot() TimerSnapshot { return (*emptySnapshot)(nil) } +func (NilTimer) Stop() {} +func (NilTimer) Time(f func()) { f() } +func (NilTimer) Update(time.Duration) {} +func (NilTimer) UpdateSince(time.Time) {}   // StandardTimer is the standard implementation of a Timer and uses a Histogram // and Meter. @@ -142,82 +84,21 @@ meter Meter mutex sync.Mutex }   -// Count returns the number of events recorded. -func (t *StandardTimer) Count() int64 { - return t.histogram.Count() -} - -// Max returns the maximum value in the sample. -func (t *StandardTimer) Max() int64 { - return t.histogram.Max() -} - -// Mean returns the mean of the values in the sample. -func (t *StandardTimer) Mean() float64 { - return t.histogram.Mean() -} - -// Min returns the minimum value in the sample. -func (t *StandardTimer) Min() int64 { - return t.histogram.Min() -} - -// Percentile returns an arbitrary percentile of the values in the sample. -func (t *StandardTimer) Percentile(p float64) float64 { - return t.histogram.Percentile(p) -} - -// Percentiles returns a slice of arbitrary percentiles of the values in the -// sample. -func (t *StandardTimer) Percentiles(ps []float64) []float64 { - return t.histogram.Percentiles(ps) -} - -// Rate1 returns the one-minute moving average rate of events per second. -func (t *StandardTimer) Rate1() float64 { - return t.meter.Rate1() -} - -// Rate5 returns the five-minute moving average rate of events per second. -func (t *StandardTimer) Rate5() float64 { - return t.meter.Rate5() -} - -// Rate15 returns the fifteen-minute moving average rate of events per second. -func (t *StandardTimer) Rate15() float64 { - return t.meter.Rate15() -} - -// RateMean returns the meter's mean rate of events per second. -func (t *StandardTimer) RateMean() float64 { - return t.meter.RateMean() -} - // Snapshot returns a read-only copy of the timer. -func (t *StandardTimer) Snapshot() Timer { +func (t *StandardTimer) Snapshot() TimerSnapshot { t.mutex.Lock() defer t.mutex.Unlock() - return &TimerSnapshot{ - histogram: t.histogram.Snapshot().(*HistogramSnapshot), - meter: t.meter.Snapshot().(*MeterSnapshot), + return &timerSnapshot{ + histogram: t.histogram.Snapshot(), + meter: t.meter.Snapshot(), } }   -// StdDev returns the standard deviation of the values in the sample. -func (t *StandardTimer) StdDev() float64 { - return t.histogram.StdDev() -} - // Stop stops the meter. func (t *StandardTimer) Stop() { t.meter.Stop() }   -// Sum returns the sum in the sample. -func (t *StandardTimer) Sum() int64 { - return t.histogram.Sum() -} - // Record the duration of the execution of the given function. func (t *StandardTimer) Time(f func()) { ts := time.Now() @@ -241,86 +122,63 @@ t.histogram.Update(int64(time.Since(ts))) t.meter.Mark(1) }   -// Variance returns the variance of the values in the sample. -func (t *StandardTimer) Variance() float64 { - return t.histogram.Variance() -} - -// TimerSnapshot is a read-only copy of another Timer. -type TimerSnapshot struct { - histogram *HistogramSnapshot - meter *MeterSnapshot +// timerSnapshot is a read-only copy of another Timer. +type timerSnapshot struct { + histogram HistogramSnapshot + meter MeterSnapshot }   // Count returns the number of events recorded at the time the snapshot was // taken. -func (t *TimerSnapshot) Count() int64 { return t.histogram.Count() } +func (t *timerSnapshot) Count() int64 { return t.histogram.Count() }   // Max returns the maximum value at the time the snapshot was taken. -func (t *TimerSnapshot) Max() int64 { return t.histogram.Max() } +func (t *timerSnapshot) Max() int64 { return t.histogram.Max() } + +// Size returns the size of the sample at the time the snapshot was taken. +func (t *timerSnapshot) Size() int { return t.histogram.Size() }   // Mean returns the mean value at the time the snapshot was taken. -func (t *TimerSnapshot) Mean() float64 { return t.histogram.Mean() } +func (t *timerSnapshot) Mean() float64 { return t.histogram.Mean() }   // Min returns the minimum value at the time the snapshot was taken. -func (t *TimerSnapshot) Min() int64 { return t.histogram.Min() } +func (t *timerSnapshot) Min() int64 { return t.histogram.Min() }   // Percentile returns an arbitrary percentile of sampled values at the time the // snapshot was taken. -func (t *TimerSnapshot) Percentile(p float64) float64 { +func (t *timerSnapshot) Percentile(p float64) float64 { return t.histogram.Percentile(p) }   // Percentiles returns a slice of arbitrary percentiles of sampled values at // the time the snapshot was taken. -func (t *TimerSnapshot) Percentiles(ps []float64) []float64 { +func (t *timerSnapshot) Percentiles(ps []float64) []float64 { return t.histogram.Percentiles(ps) }   // Rate1 returns the one-minute moving average rate of events per second at the // time the snapshot was taken. -func (t *TimerSnapshot) Rate1() float64 { return t.meter.Rate1() } +func (t *timerSnapshot) Rate1() float64 { return t.meter.Rate1() }   // Rate5 returns the five-minute moving average rate of events per second at // the time the snapshot was taken. -func (t *TimerSnapshot) Rate5() float64 { return t.meter.Rate5() } +func (t *timerSnapshot) Rate5() float64 { return t.meter.Rate5() }   // Rate15 returns the fifteen-minute moving average rate of events per second // at the time the snapshot was taken. -func (t *TimerSnapshot) Rate15() float64 { return t.meter.Rate15() } +func (t *timerSnapshot) Rate15() float64 { return t.meter.Rate15() }   // RateMean returns the meter's mean rate of events per second at the time the // snapshot was taken. -func (t *TimerSnapshot) RateMean() float64 { return t.meter.RateMean() } - -// Snapshot returns the snapshot. -func (t *TimerSnapshot) Snapshot() Timer { return t } +func (t *timerSnapshot) RateMean() float64 { return t.meter.RateMean() }   // StdDev returns the standard deviation of the values at the time the snapshot // was taken. -func (t *TimerSnapshot) StdDev() float64 { return t.histogram.StdDev() } - -// Stop is a no-op. -func (t *TimerSnapshot) Stop() {} +func (t *timerSnapshot) StdDev() float64 { return t.histogram.StdDev() }   // Sum returns the sum at the time the snapshot was taken. -func (t *TimerSnapshot) Sum() int64 { return t.histogram.Sum() } - -// Time panics. -func (*TimerSnapshot) Time(func()) { - panic("Time called on a TimerSnapshot") -} - -// Update panics. -func (*TimerSnapshot) Update(time.Duration) { - panic("Update called on a TimerSnapshot") -} - -// UpdateSince panics. -func (*TimerSnapshot) UpdateSince(time.Time) { - panic("UpdateSince called on a TimerSnapshot") -} +func (t *timerSnapshot) Sum() int64 { return t.histogram.Sum() }   // Variance returns the variance of the values at the time the snapshot was // taken. -func (t *TimerSnapshot) Variance() float64 { return t.histogram.Variance() } +func (t *timerSnapshot) Variance() float64 { return t.histogram.Variance() }
diff --git ethereum/go-ethereum/metrics/timer_test.go taikoxyz/taiko-geth/metrics/timer_test.go index 903e8e8d496e7cbea9ec3a1a28dd9c659c4c88e9..f10de16c9c23d534891bf1ea97078c819bba67f3 100644 --- ethereum/go-ethereum/metrics/timer_test.go +++ taikoxyz/taiko-geth/metrics/timer_test.go @@ -18,7 +18,7 @@ func TestGetOrRegisterTimer(t *testing.T) { r := NewRegistry() NewRegisteredTimer("foo", r).Update(47) - if tm := GetOrRegisterTimer("foo", r); tm.Count() != 1 { + if tm := GetOrRegisterTimer("foo", r).Snapshot(); tm.Count() != 1 { t.Fatal(tm) } } @@ -27,7 +27,7 @@ func TestTimerExtremes(t *testing.T) { tm := NewTimer() tm.Update(math.MaxInt64) tm.Update(0) - if stdDev := tm.StdDev(); stdDev != 4.611686018427388e+18 { + if stdDev := tm.Snapshot().StdDev(); stdDev != 4.611686018427388e+18 { t.Errorf("tm.StdDev(): 4.611686018427388e+18 != %v\n", stdDev) } } @@ -56,7 +56,7 @@ actualTime = time.Since(testStart) }) var ( drift = time.Millisecond * 2 - measured = time.Duration(tm.Max()) + measured = time.Duration(tm.Snapshot().Max()) ceil = actualTime + drift floor = actualTime - drift ) @@ -66,7 +66,7 @@ } }   func TestTimerZero(t *testing.T) { - tm := NewTimer() + tm := NewTimer().Snapshot() if count := tm.Count(); count != 0 { t.Errorf("tm.Count(): 0 != %v\n", count) } @@ -110,5 +110,5 @@ func ExampleGetOrRegisterTimer() { m := "account.create.latency" t := GetOrRegisterTimer(m, nil) t.Update(47) - fmt.Println(t.Max()) // Output: 47 + fmt.Println(t.Snapshot().Max()) // Output: 47 }
diff --git ethereum/go-ethereum/metrics/writer.go taikoxyz/taiko-geth/metrics/writer.go index 82434e9d1d62a93a5363175fc0910e8d5c7c3224..098da45c27b2acbe0eeb0f92d7acbd0f43ca1a3f 100644 --- ethereum/go-ethereum/metrics/writer.go +++ taikoxyz/taiko-geth/metrics/writer.go @@ -29,16 +29,19 @@ for _, namedMetric := range namedMetrics { switch metric := namedMetric.m.(type) { case Counter: fmt.Fprintf(w, "counter %s\n", namedMetric.name) - fmt.Fprintf(w, " count: %9d\n", metric.Count()) + fmt.Fprintf(w, " count: %9d\n", metric.Snapshot().Count()) case CounterFloat64: fmt.Fprintf(w, "counter %s\n", namedMetric.name) - fmt.Fprintf(w, " count: %f\n", metric.Count()) + fmt.Fprintf(w, " count: %f\n", metric.Snapshot().Count()) case Gauge: fmt.Fprintf(w, "gauge %s\n", namedMetric.name) - fmt.Fprintf(w, " value: %9d\n", metric.Value()) + fmt.Fprintf(w, " value: %9d\n", metric.Snapshot().Value()) case GaugeFloat64: fmt.Fprintf(w, "gauge %s\n", namedMetric.name) - fmt.Fprintf(w, " value: %f\n", metric.Value()) + fmt.Fprintf(w, " value: %f\n", metric.Snapshot().Value()) + case GaugeInfo: + fmt.Fprintf(w, "gauge %s\n", namedMetric.name) + fmt.Fprintf(w, " value: %s\n", metric.Snapshot().Value().String()) case Healthcheck: metric.Check() fmt.Fprintf(w, "healthcheck %s\n", namedMetric.name)
diff --git ethereum/go-ethereum/miner/stress/clique/main.go taikoxyz/taiko-geth/miner/stress/clique/main.go index 53ff2450c55be859ed1dbb79be8011c3239b228e..7b29e63dfc699f5e19b80503cef48e4f75f4a84d 100644 --- ethereum/go-ethereum/miner/stress/clique/main.go +++ taikoxyz/taiko-geth/miner/stress/clique/main.go @@ -30,7 +30,6 @@ "github.com/ethereum/go-ethereum/accounts/keystore" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common/fdlimit" "github.com/ethereum/go-ethereum/core" - "github.com/ethereum/go-ethereum/core/txpool" "github.com/ethereum/go-ethereum/core/txpool/legacypool" "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/crypto" @@ -133,7 +132,7 @@ tx, err := types.SignTx(types.NewTransaction(nonces[index], crypto.PubkeyToAddress(faucets[index].PublicKey), new(big.Int), 21000, big.NewInt(100000000000), nil), types.HomesteadSigner{}, faucets[index]) if err != nil { panic(err) } - if err := backend.TxPool().Add([]*txpool.Transaction{{Tx: tx}}, true, false); err != nil { + if err := backend.TxPool().Add([]*types.Transaction{tx}, true, false); err != nil { panic(err) } nonces[index]++ @@ -148,7 +147,7 @@ // makeGenesis creates a custom Clique genesis block based on some pre-defined // signer and faucet accounts. func makeGenesis(faucets []*ecdsa.PrivateKey, sealers []*ecdsa.PrivateKey) *core.Genesis { - // Create a Clique network based off of the Seplia config + // Create a Clique network based off of the Sepolia config genesis := core.DefaultSepoliaGenesisBlock() genesis.GasLimit = 25000000
diff --git ethereum/go-ethereum/node/defaults.go taikoxyz/taiko-geth/node/defaults.go index d8f718121e80287e30cc2ce94ce38605cb726e61..42d9d4cde0fc9830cd33252926125eb5c48ae7da 100644 --- ethereum/go-ethereum/node/defaults.go +++ taikoxyz/taiko-geth/node/defaults.go @@ -36,6 +36,13 @@ DefaultAuthHost = "localhost" // Default host interface for the authenticated apis DefaultAuthPort = 8551 // Default port for the authenticated apis )   +const ( + // Engine API batch limits: these are not configurable by users, and should cover the + // needs of all CLs. + engineAPIBatchItemLimit = 2000 + engineAPIBatchResponseSizeLimit = 250 * 1000 * 1000 +) + var ( DefaultAuthCors = []string{"localhost"} // Default cors domain for the authenticated apis DefaultAuthVhosts = []string{"localhost"} // Default virtual hosts for the authenticated apis
diff --git ethereum/go-ethereum/node/node.go taikoxyz/taiko-geth/node/node.go index da41169c52b8676da59fb72ad54c7449680c1682..41c9971fe8e6de8fccd9d0a2a674957e217e81dd 100644 --- ethereum/go-ethereum/node/node.go +++ taikoxyz/taiko-geth/node/node.go @@ -449,8 +449,11 @@ server := n.httpAuth if err := server.setListenAddr(n.config.AuthAddr, port); err != nil { return err } - sharedConfig := rpcConfig - sharedConfig.jwtSecret = secret + sharedConfig := rpcEndpointConfig{ + jwtSecret: secret, + batchItemLimit: engineAPIBatchItemLimit, + batchResponseSizeLimit: engineAPIBatchResponseSizeLimit, + } if err := server.enableRPC(allAPIs, httpConfig{ CorsAllowedOrigins: DefaultAuthCors, Vhosts: n.config.AuthVirtualHosts,
diff --git ethereum/go-ethereum/p2p/discover/v4wire/v4wire.go taikoxyz/taiko-geth/p2p/discover/v4wire/v4wire.go index 3935068cd9dba811cab1496be9fb249eaca2a022..9c59359fb2c2e005503c3462f2305d58d260f24c 100644 --- ethereum/go-ethereum/p2p/discover/v4wire/v4wire.go +++ taikoxyz/taiko-geth/p2p/discover/v4wire/v4wire.go @@ -238,6 +238,8 @@ req = new(ENRResponse) default: return nil, fromKey, hash, fmt.Errorf("unknown type: %d", ptype) } + // Here we use NewStream to allow for additional data after the first + // RLP object (forward-compatibility). s := rlp.NewStream(bytes.NewReader(sigdata[1:]), 0) err = s.Decode(req) return req, fromKey, hash, err
diff --git ethereum/go-ethereum/rlp/decode.go taikoxyz/taiko-geth/rlp/decode.go index c9b50e8c18795ee3da5634d6184f36ffaafedaa8..9b17d2d810846b4c5473644bfda167bcca6593db 100644 --- ethereum/go-ethereum/rlp/decode.go +++ taikoxyz/taiko-geth/rlp/decode.go @@ -90,7 +90,7 @@ // DecodeBytes parses RLP data from b into val. Please see package-level documentation for // the decoding rules. The input must contain exactly one value and no trailing data. func DecodeBytes(b []byte, val interface{}) error { - r := bytes.NewReader(b) + r := (*sliceReader)(&b)   stream := streamPool.Get().(*Stream) defer streamPool.Put(stream) @@ -99,7 +99,7 @@ stream.Reset(r, uint64(len(b))) if err := stream.Decode(val); err != nil { return err } - if r.Len() > 0 { + if len(b) > 0 { return ErrMoreThanOneValue } return nil @@ -1182,3 +1182,23 @@ return false, 0 } return true, s.stack[len(s.stack)-1] } + +type sliceReader []byte + +func (sr *sliceReader) Read(b []byte) (int, error) { + if len(*sr) == 0 { + return 0, io.EOF + } + n := copy(b, *sr) + *sr = (*sr)[n:] + return n, nil +} + +func (sr *sliceReader) ReadByte() (byte, error) { + if len(*sr) == 0 { + return 0, io.EOF + } + b := (*sr)[0] + *sr = (*sr)[1:] + return b, nil +}
diff --git ethereum/go-ethereum/rlp/rlpgen/main.go taikoxyz/taiko-geth/rlp/rlpgen/main.go index 25d4393cc6561db2b6c750da21f03092181a9ac6..b3a74b9df13f817e33e6e9940e4e731fe1a0e4b6 100644 --- ethereum/go-ethereum/rlp/rlpgen/main.go +++ taikoxyz/taiko-geth/rlp/rlpgen/main.go @@ -73,9 +73,8 @@ // process generates the Go code. func (cfg *Config) process() (code []byte, err error) { // Load packages. pcfg := &packages.Config{ - Mode: packages.NeedName | packages.NeedTypes | packages.NeedImports | packages.NeedDeps, - Dir: cfg.Dir, - BuildFlags: []string{"-tags", "norlpgen"}, + Mode: packages.NeedName | packages.NeedTypes, + Dir: cfg.Dir, } ps, err := packages.Load(pcfg, pathOfPackageRLP, ".") if err != nil { @@ -117,8 +116,6 @@ // Add build comments. // This is done here to avoid processing these lines with gofmt. var header bytes.Buffer fmt.Fprint(&header, "// Code generated by rlpgen. DO NOT EDIT.\n\n") - fmt.Fprint(&header, "//go:build !norlpgen\n") - fmt.Fprint(&header, "// +build !norlpgen\n\n") return append(header.Bytes(), code...), nil }
diff --git ethereum/go-ethereum/rpc/client_opt.go taikoxyz/taiko-geth/rpc/client_opt.go index 5bef08cca8410bf22cf949886b912acf755f6fda..3fa045a9b9f39076d0ed62f845eb0e3864bba241 100644 --- ethereum/go-ethereum/rpc/client_opt.go +++ taikoxyz/taiko-geth/rpc/client_opt.go @@ -34,7 +34,8 @@ httpHeaders http.Header httpAuth HTTPAuth   // WebSocket options - wsDialer *websocket.Dialer + wsDialer *websocket.Dialer + wsMessageSizeLimit *int64 // wsMessageSizeLimit nil = default, 0 = no limit   // RPC handler options idgen func() ID @@ -63,6 +64,14 @@ // WithWebsocketDialer configures the websocket.Dialer used by the RPC client. func WithWebsocketDialer(dialer websocket.Dialer) ClientOption { return optionFunc(func(cfg *clientConfig) { cfg.wsDialer = &dialer + }) +} + +// WithWebsocketMessageSizeLimit configures the websocket message size limit used by the RPC +// client. Passing a limit of 0 means no limit. +func WithWebsocketMessageSizeLimit(messageSizeLimit int64) ClientOption { + return optionFunc(func(cfg *clientConfig) { + cfg.wsMessageSizeLimit = &messageSizeLimit }) }
diff --git ethereum/go-ethereum/rpc/ipc_windows.go taikoxyz/taiko-geth/rpc/ipc_windows.go index adb1826f0c802f2657a0707857b52fe13b84c616..efec38cf37299b9c3092daadae26da96d8fb323a 100644 --- ethereum/go-ethereum/rpc/ipc_windows.go +++ taikoxyz/taiko-geth/rpc/ipc_windows.go @@ -24,7 +24,7 @@ "context" "net" "time"   - "gopkg.in/natefinch/npipe.v2" + "github.com/Microsoft/go-winio" )   // This is used if the dialing context has no deadline. It is much smaller than the @@ -33,17 +33,12 @@ const defaultPipeDialTimeout = 2 * time.Second   // ipcListen will create a named pipe on the given endpoint. func ipcListen(endpoint string) (net.Listener, error) { - return npipe.Listen(endpoint) + return winio.ListenPipe(endpoint, nil) }   // newIPCConnection will connect to a named pipe with the given endpoint as name. func newIPCConnection(ctx context.Context, endpoint string) (net.Conn, error) { - timeout := defaultPipeDialTimeout - if deadline, ok := ctx.Deadline(); ok { - timeout = deadline.Sub(time.Now()) - if timeout < 0 { - timeout = 0 - } - } - return npipe.DialTimeout(endpoint, timeout) + ctx, cancel := context.WithTimeout(ctx, defaultPipeDialTimeout) + defer cancel() + return winio.DialPipeContext(ctx, endpoint) }
diff --git ethereum/go-ethereum/rpc/server_test.go taikoxyz/taiko-geth/rpc/server_test.go index 5d3929dfdc692652ea577a5d56e8f8f804967ac8..9d1c7fb5f0fe730ff946698707647913a5ed93ac 100644 --- ethereum/go-ethereum/rpc/server_test.go +++ taikoxyz/taiko-geth/rpc/server_test.go @@ -32,7 +32,8 @@ func TestServerRegisterName(t *testing.T) { server := NewServer() service := new(testService)   - if err := server.RegisterName("test", service); err != nil { + svcName := "test" + if err := server.RegisterName(svcName, service); err != nil { t.Fatalf("%v", err) }   @@ -40,12 +41,12 @@ if len(server.services.services) != 2 { t.Fatalf("Expected 2 service entries, got %d", len(server.services.services)) }   - svc, ok := server.services.services["test"] + svc, ok := server.services.services[svcName] if !ok { - t.Fatalf("Expected service calc to be registered") + t.Fatalf("Expected service %s to be registered", svcName) }   - wantCallbacks := 13 + wantCallbacks := 14 if len(svc.callbacks) != wantCallbacks { t.Errorf("Expected %d callbacks for service 'service', got %d", wantCallbacks, len(svc.callbacks)) }
diff --git ethereum/go-ethereum/rpc/testservice_test.go taikoxyz/taiko-geth/rpc/testservice_test.go index eab67f1dd5d8a7eeff07a601c0e8617dcd863d4f..7d873af6670e3e7696394bbeea7c4c8440f44bc0 100644 --- ethereum/go-ethereum/rpc/testservice_test.go +++ taikoxyz/taiko-geth/rpc/testservice_test.go @@ -90,6 +90,10 @@ func (s *testService) EchoWithCtx(ctx context.Context, str string, i int, args *echoArgs) echoResult { return echoResult{str, i, args} }   +func (s *testService) Repeat(msg string, i int) string { + return strings.Repeat(msg, i) +} + func (s *testService) PeerInfo(ctx context.Context) PeerInfo { return PeerInfoFromContext(ctx) }
diff --git ethereum/go-ethereum/rpc/websocket.go taikoxyz/taiko-geth/rpc/websocket.go index b1213fdfa663eb2829e57bf6ec3e2880f0c19d47..538e53a31b7c363af28b6ec862ed163cbea05ed5 100644 --- ethereum/go-ethereum/rpc/websocket.go +++ taikoxyz/taiko-geth/rpc/websocket.go @@ -38,7 +38,7 @@ wsWriteBuffer = 1024 wsPingInterval = 30 * time.Second wsPingWriteTimeout = 5 * time.Second wsPongTimeout = 30 * time.Second - wsMessageSizeLimit = 32 * 1024 * 1024 + wsDefaultReadLimit = 32 * 1024 * 1024 )   var wsBufferPool = new(sync.Pool) @@ -60,7 +60,7 @@ if err != nil { log.Debug("WebSocket upgrade failed", "err", err) return } - codec := newWebsocketCodec(conn, r.Host, r.Header) + codec := newWebsocketCodec(conn, r.Host, r.Header, wsDefaultReadLimit) s.ServeCodec(codec, 0) }) } @@ -251,7 +251,11 @@ hErr.status = resp.Status } return nil, hErr } - return newWebsocketCodec(conn, dialURL, header), nil + messageSizeLimit := int64(wsDefaultReadLimit) + if cfg.wsMessageSizeLimit != nil && *cfg.wsMessageSizeLimit >= 0 { + messageSizeLimit = *cfg.wsMessageSizeLimit + } + return newWebsocketCodec(conn, dialURL, header, messageSizeLimit), nil } return connect, nil } @@ -278,24 +282,21 @@ *jsonCodec conn *websocket.Conn info PeerInfo   - wg sync.WaitGroup - pingReset chan struct{} + wg sync.WaitGroup + pingReset chan struct{} + pongReceived chan struct{} }   -func newWebsocketCodec(conn *websocket.Conn, host string, req http.Header) ServerCodec { - conn.SetReadLimit(wsMessageSizeLimit) - conn.SetPongHandler(func(appData string) error { - conn.SetReadDeadline(time.Time{}) - return nil - }) - +func newWebsocketCodec(conn *websocket.Conn, host string, req http.Header, readLimit int64) ServerCodec { + conn.SetReadLimit(readLimit) encode := func(v interface{}, isErrorResponse bool) error { return conn.WriteJSON(v) } wc := &websocketCodec{ - jsonCodec: NewFuncCodec(conn, encode, conn.ReadJSON).(*jsonCodec), - conn: conn, - pingReset: make(chan struct{}, 1), + jsonCodec: NewFuncCodec(conn, encode, conn.ReadJSON).(*jsonCodec), + conn: conn, + pingReset: make(chan struct{}, 1), + pongReceived: make(chan struct{}), info: PeerInfo{ Transport: "ws", RemoteAddr: conn.RemoteAddr().String(), @@ -306,6 +307,13 @@ wc.info.HTTP.Host = host wc.info.HTTP.Origin = req.Get("Origin") wc.info.HTTP.UserAgent = req.Get("User-Agent") // Start pinger. + conn.SetPongHandler(func(appData string) error { + select { + case wc.pongReceived <- struct{}{}: + case <-wc.closed(): + } + return nil + }) wc.wg.Add(1) go wc.pingLoop() return wc @@ -334,26 +342,31 @@ }   // pingLoop sends periodic ping frames when the connection is idle. func (wc *websocketCodec) pingLoop() { - var timer = time.NewTimer(wsPingInterval) + var pingTimer = time.NewTimer(wsPingInterval) defer wc.wg.Done() - defer timer.Stop() + defer pingTimer.Stop()   for { select { case <-wc.closed(): return + case <-wc.pingReset: - if !timer.Stop() { - <-timer.C + if !pingTimer.Stop() { + <-pingTimer.C } - timer.Reset(wsPingInterval) - case <-timer.C: + pingTimer.Reset(wsPingInterval) + + case <-pingTimer.C: wc.jsonCodec.encMu.Lock() wc.conn.SetWriteDeadline(time.Now().Add(wsPingWriteTimeout)) wc.conn.WriteMessage(websocket.PingMessage, nil) wc.conn.SetReadDeadline(time.Now().Add(wsPongTimeout)) wc.jsonCodec.encMu.Unlock() - timer.Reset(wsPingInterval) + pingTimer.Reset(wsPingInterval) + + case <-wc.pongReceived: + wc.conn.SetReadDeadline(time.Time{}) } } }
diff --git ethereum/go-ethereum/rpc/websocket_test.go taikoxyz/taiko-geth/rpc/websocket_test.go index fb9357605b8b9ad34eae51a8876b7e5b3c6c9214..e4ac5c3fad3f0cfde8b59b261fc842167fcb7a13 100644 --- ethereum/go-ethereum/rpc/websocket_test.go +++ taikoxyz/taiko-geth/rpc/websocket_test.go @@ -113,6 +113,66 @@ t.Fatal("no error for too large call") } }   +// This test checks whether the wsMessageSizeLimit option is obeyed. +func TestWebsocketLargeRead(t *testing.T) { + t.Parallel() + + var ( + srv = newTestServer() + httpsrv = httptest.NewServer(srv.WebsocketHandler([]string{"*"})) + wsURL = "ws:" + strings.TrimPrefix(httpsrv.URL, "http:") + ) + defer srv.Stop() + defer httpsrv.Close() + + testLimit := func(limit *int64) { + opts := []ClientOption{} + expLimit := int64(wsDefaultReadLimit) + if limit != nil && *limit >= 0 { + opts = append(opts, WithWebsocketMessageSizeLimit(*limit)) + if *limit > 0 { + expLimit = *limit // 0 means infinite + } + } + client, err := DialOptions(context.Background(), wsURL, opts...) + if err != nil { + t.Fatalf("can't dial: %v", err) + } + defer client.Close() + // Remove some bytes for json encoding overhead. + underLimit := int(expLimit - 128) + overLimit := expLimit + 1 + if expLimit == wsDefaultReadLimit { + // No point trying the full 32MB in tests. Just sanity-check that + // it's not obviously limited. + underLimit = 1024 + overLimit = -1 + } + var res string + // Check under limit + if err = client.Call(&res, "test_repeat", "A", underLimit); err != nil { + t.Fatalf("unexpected error with limit %d: %v", expLimit, err) + } + if len(res) != underLimit || strings.Count(res, "A") != underLimit { + t.Fatal("incorrect data") + } + // Check over limit + if overLimit > 0 { + err = client.Call(&res, "test_repeat", "A", expLimit+1) + if err == nil || err != websocket.ErrReadLimit { + t.Fatalf("wrong error with limit %d: %v expecting %v", expLimit, err, websocket.ErrReadLimit) + } + } + } + ptr := func(v int64) *int64 { return &v } + + testLimit(ptr(-1)) // Should be ignored (use default) + testLimit(ptr(0)) // Should be ignored (use default) + testLimit(nil) // Should be ignored (use default) + testLimit(ptr(200)) + testLimit(ptr(wsDefaultReadLimit * 2)) +} + func TestWebsocketPeerInfo(t *testing.T) { var ( s = newTestServer() @@ -206,7 +266,7 @@ ) defer srv.Stop() defer httpsrv.Close()   - respLength := wsMessageSizeLimit - 50 + respLength := wsDefaultReadLimit - 50 srv.RegisterName("test", largeRespService{respLength})   c, err := DialWebsocket(context.Background(), wsURL, "")
diff --git ethereum/go-ethereum/signer/core/api_test.go taikoxyz/taiko-geth/signer/core/api_test.go index 9bb55bddca3175a6263194b4c6aa9eff88a477b1..5a9de161b3acfda6377bf36ac6424e45120f66ab 100644 --- ethereum/go-ethereum/signer/core/api_test.go +++ taikoxyz/taiko-geth/signer/core/api_test.go @@ -282,7 +282,7 @@ if err != nil { t.Fatal(err) } parsedTx := &types.Transaction{} - rlp.Decode(bytes.NewReader(res.Raw), parsedTx) + rlp.DecodeBytes(res.Raw, parsedTx)   //The tx should NOT be modified by the UI if parsedTx.Value().Cmp(tx.Value.ToInt()) != 0 { @@ -308,7 +308,7 @@ if err != nil { t.Fatal(err) } parsedTx2 := &types.Transaction{} - rlp.Decode(bytes.NewReader(res.Raw), parsedTx2) + rlp.DecodeBytes(res.Raw, parsedTx2)   //The tx should be modified by the UI if parsedTx2.Value().Cmp(tx.Value.ToInt()) != 0 {
diff --git ethereum/go-ethereum/tests/block_test.go taikoxyz/taiko-geth/tests/block_test.go index 2405da1cc7335aa76294322e8cc66e1c77aa1944..5764ae33e474639ee2234b62d1899d3c7fc10527 100644 --- ethereum/go-ethereum/tests/block_test.go +++ taikoxyz/taiko-geth/tests/block_test.go @@ -18,11 +18,12 @@ package tests   import ( "testing" + + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/core/rawdb" )   func TestBlockchain(t *testing.T) { - t.Parallel() - bt := new(testMatcher) // General state tests are 'exported' as blockchain tests, but we can run them natively. // For speedier CI-runs, the line below can be uncommented, so those are skipped. @@ -48,14 +49,40 @@ // using 4.6 TGas bt.skipLoad(`.*randomStatetest94.json.*`)   bt.walk(t, blockTestDir, func(t *testing.T, name string, test *BlockTest) { - if err := bt.checkFailure(t, test.Run(false, nil)); err != nil { - t.Errorf("test without snapshotter failed: %v", err) - } - if err := bt.checkFailure(t, test.Run(true, nil)); err != nil { - t.Errorf("test with snapshotter failed: %v", err) - } + execBlockTest(t, bt, test) }) // There is also a LegacyTests folder, containing blockchain tests generated // prior to Istanbul. However, they are all derived from GeneralStateTests, // which run natively, so there's no reason to run them here. } + +// TestExecutionSpec runs the test fixtures from execution-spec-tests. +func TestExecutionSpec(t *testing.T) { + if !common.FileExist(executionSpecDir) { + t.Skipf("directory %s does not exist", executionSpecDir) + } + bt := new(testMatcher) + + bt.walk(t, executionSpecDir, func(t *testing.T, name string, test *BlockTest) { + execBlockTest(t, bt, test) + }) +} + +func execBlockTest(t *testing.T, bt *testMatcher, test *BlockTest) { + if err := bt.checkFailure(t, test.Run(false, rawdb.HashScheme, nil)); err != nil { + t.Errorf("test in hash mode without snapshotter failed: %v", err) + return + } + if err := bt.checkFailure(t, test.Run(true, rawdb.HashScheme, nil)); err != nil { + t.Errorf("test in hash mode with snapshotter failed: %v", err) + return + } + if err := bt.checkFailure(t, test.Run(false, rawdb.PathScheme, nil)); err != nil { + t.Errorf("test in path mode without snapshotter failed: %v", err) + return + } + if err := bt.checkFailure(t, test.Run(true, rawdb.PathScheme, nil)); err != nil { + t.Errorf("test in path mode with snapshotter failed: %v", err) + return + } +}
diff --git ethereum/go-ethereum/tests/block_test_util.go taikoxyz/taiko-geth/tests/block_test_util.go index d3e525a387e3ba632cf2c557ba0ff065dd539cb9..ad1d34fb2bc731448ba33d496c0ae234910cfac0 100644 --- ethereum/go-ethereum/tests/block_test_util.go +++ taikoxyz/taiko-geth/tests/block_test_util.go @@ -38,6 +38,9 @@ "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/core/vm" "github.com/ethereum/go-ethereum/params" "github.com/ethereum/go-ethereum/rlp" + "github.com/ethereum/go-ethereum/trie" + "github.com/ethereum/go-ethereum/trie/triedb/hashdb" + "github.com/ethereum/go-ethereum/trie/triedb/pathdb" )   // A BlockTest checks handling of entire blocks. @@ -70,24 +73,27 @@ //go:generate go run github.com/fjl/gencodec -type btHeader -field-override btHeaderMarshaling -out gen_btheader.go   type btHeader struct { - Bloom types.Bloom - Coinbase common.Address - MixHash common.Hash - Nonce types.BlockNonce - Number *big.Int - Hash common.Hash - ParentHash common.Hash - ReceiptTrie common.Hash - StateRoot common.Hash - TransactionsTrie common.Hash - UncleHash common.Hash - ExtraData []byte - Difficulty *big.Int - GasLimit uint64 - GasUsed uint64 - Timestamp uint64 - BaseFeePerGas *big.Int - WithdrawalsRoot *common.Hash + Bloom types.Bloom + Coinbase common.Address + MixHash common.Hash + Nonce types.BlockNonce + Number *big.Int + Hash common.Hash + ParentHash common.Hash + ReceiptTrie common.Hash + StateRoot common.Hash + TransactionsTrie common.Hash + UncleHash common.Hash + ExtraData []byte + Difficulty *big.Int + GasLimit uint64 + GasUsed uint64 + Timestamp uint64 + BaseFeePerGas *big.Int + WithdrawalsRoot *common.Hash + BlobGasUsed *uint64 + ExcessBlobGas *uint64 + ParentBeaconBlockRoot *common.Hash }   type btHeaderMarshaling struct { @@ -98,18 +104,34 @@ GasLimit math.HexOrDecimal64 GasUsed math.HexOrDecimal64 Timestamp math.HexOrDecimal64 BaseFeePerGas *math.HexOrDecimal256 + BlobGasUsed *math.HexOrDecimal64 + ExcessBlobGas *math.HexOrDecimal64 }   -func (t *BlockTest) Run(snapshotter bool, tracer vm.EVMLogger) error { +func (t *BlockTest) Run(snapshotter bool, scheme string, tracer vm.EVMLogger) error { config, ok := Forks[t.json.Network] if !ok { return UnsupportedForkError{t.json.Network} } - // import pre accounts & construct test genesis block & state root - db := rawdb.NewMemoryDatabase() + var ( + db = rawdb.NewMemoryDatabase() + tconf = &trie.Config{} + ) + if scheme == rawdb.PathScheme { + tconf.PathDB = pathdb.Defaults + } else { + tconf.HashDB = hashdb.Defaults + } + // Commit genesis state gspec := t.genesis(config) - gblock := gspec.MustCommit(db) + triedb := trie.NewDatabase(db, tconf) + gblock, err := gspec.Commit(db, triedb) + if err != nil { + return err + } + triedb.Close() // close the db to prevent memory leak + if gblock.Hash() != t.json.Genesis.Hash { return fmt.Errorf("genesis block hash doesn't match test: computed=%x, test=%x", gblock.Hash().Bytes()[:6], t.json.Genesis.Hash[:6]) } @@ -119,7 +141,7 @@ } // Wrap the original engine within the beacon-engine engine := beacon.New(ethash.NewFaker())   - cache := &core.CacheConfig{TrieCleanLimit: 0} + cache := &core.CacheConfig{TrieCleanLimit: 0, StateScheme: scheme} if snapshotter { cache.SnapshotLimit = 1 cache.SnapshotWait = true @@ -158,18 +180,20 @@ }   func (t *BlockTest) genesis(config *params.ChainConfig) *core.Genesis { return &core.Genesis{ - Config: config, - Nonce: t.json.Genesis.Nonce.Uint64(), - Timestamp: t.json.Genesis.Timestamp, - ParentHash: t.json.Genesis.ParentHash, - ExtraData: t.json.Genesis.ExtraData, - GasLimit: t.json.Genesis.GasLimit, - GasUsed: t.json.Genesis.GasUsed, - Difficulty: t.json.Genesis.Difficulty, - Mixhash: t.json.Genesis.MixHash, - Coinbase: t.json.Genesis.Coinbase, - Alloc: t.json.Pre, - BaseFee: t.json.Genesis.BaseFeePerGas, + Config: config, + Nonce: t.json.Genesis.Nonce.Uint64(), + Timestamp: t.json.Genesis.Timestamp, + ParentHash: t.json.Genesis.ParentHash, + ExtraData: t.json.Genesis.ExtraData, + GasLimit: t.json.Genesis.GasLimit, + GasUsed: t.json.Genesis.GasUsed, + Difficulty: t.json.Genesis.Difficulty, + Mixhash: t.json.Genesis.MixHash, + Coinbase: t.json.Genesis.Coinbase, + Alloc: t.json.Pre, + BaseFee: t.json.Genesis.BaseFeePerGas, + BlobGasUsed: t.json.Genesis.BlobGasUsed, + ExcessBlobGas: t.json.Genesis.ExcessBlobGas, } }   @@ -277,6 +301,15 @@ return fmt.Errorf("baseFeePerGas: want: %v have: %v", h.BaseFeePerGas, h2.BaseFee) } if !reflect.DeepEqual(h.WithdrawalsRoot, h2.WithdrawalsHash) { return fmt.Errorf("withdrawalsRoot: want: %v have: %v", h.WithdrawalsRoot, h2.WithdrawalsHash) + } + if !reflect.DeepEqual(h.BlobGasUsed, h2.BlobGasUsed) { + return fmt.Errorf("blobGasUsed: want: %v have: %v", h.BlobGasUsed, h2.BlobGasUsed) + } + if !reflect.DeepEqual(h.ExcessBlobGas, h2.ExcessBlobGas) { + return fmt.Errorf("excessBlobGas: want: %v have: %v", h.ExcessBlobGas, h2.ExcessBlobGas) + } + if !reflect.DeepEqual(h.ParentBeaconBlockRoot, h2.ParentBeaconRoot) { + return fmt.Errorf("parentBeaconBlockRoot: want: %v have: %v", h.ParentBeaconBlockRoot, h2.ParentBeaconRoot) } return nil }
diff --git ethereum/go-ethereum/tests/fuzzers/les/les-fuzzer.go taikoxyz/taiko-geth/tests/fuzzers/les/les-fuzzer.go index c62253a72622a9d8bbea14446f324f4ecbceb35e..c29bb2ef12283083ac84ad354ab991c15c1f9d99 100644 --- ethereum/go-ethereum/tests/fuzzers/les/les-fuzzer.go +++ taikoxyz/taiko-geth/tests/fuzzers/les/les-fuzzer.go @@ -88,8 +88,8 @@ return }   func makeTries() (chtTrie *trie.Trie, bloomTrie *trie.Trie, chtKeys, bloomKeys [][]byte) { - chtTrie = trie.NewEmpty(trie.NewDatabase(rawdb.NewMemoryDatabase())) - bloomTrie = trie.NewEmpty(trie.NewDatabase(rawdb.NewMemoryDatabase())) + chtTrie = trie.NewEmpty(trie.NewDatabase(rawdb.NewMemoryDatabase(), trie.HashDefaults)) + bloomTrie = trie.NewEmpty(trie.NewDatabase(rawdb.NewMemoryDatabase(), trie.HashDefaults)) for i := 0; i < testChainLen; i++ { // The element in CHT is <big-endian block number> -> <block hash> key := make([]byte, 8)
diff --git ethereum/go-ethereum/tests/fuzzers/rangeproof/rangeproof-fuzzer.go taikoxyz/taiko-geth/tests/fuzzers/rangeproof/rangeproof-fuzzer.go index aa81e5c9d9b13c128ceeb55991206e32b82232b7..c9d781553673f257ffc18dcb46e17d2aa73b52e9 100644 --- ethereum/go-ethereum/tests/fuzzers/rangeproof/rangeproof-fuzzer.go +++ taikoxyz/taiko-geth/tests/fuzzers/rangeproof/rangeproof-fuzzer.go @@ -56,7 +56,7 @@ return x }   func (f *fuzzer) randomTrie(n int) (*trie.Trie, map[string]*kv) { - trie := trie.NewEmpty(trie.NewDatabase(rawdb.NewMemoryDatabase())) + trie := trie.NewEmpty(trie.NewDatabase(rawdb.NewMemoryDatabase(), nil)) vals := make(map[string]*kv) size := f.readInt() // Fill it with some fluff @@ -128,7 +128,7 @@ } if len(keys) == 0 { return 0 } - var first, last = keys[0], keys[len(keys)-1] + var first = keys[0] testcase %= 6 switch testcase { case 0: @@ -165,7 +165,7 @@ break } ok = 1 //nodes, subtrie - hasMore, err := trie.VerifyRangeProof(tr.Hash(), first, last, keys, vals, proof) + hasMore, err := trie.VerifyRangeProof(tr.Hash(), first, keys, vals, proof) if err != nil { if hasMore { panic("err != nil && hasMore == true")
diff --git ethereum/go-ethereum/tests/fuzzers/stacktrie/trie_fuzzer.go taikoxyz/taiko-geth/tests/fuzzers/stacktrie/trie_fuzzer.go index 391bdf300b726b7d469e97522e6d50f3b5299266..20b8ca24b3d26294bd657b7f507c99073c2376ae 100644 --- ethereum/go-ethereum/tests/fuzzers/stacktrie/trie_fuzzer.go +++ taikoxyz/taiko-geth/tests/fuzzers/stacktrie/trie_fuzzer.go @@ -136,12 +136,12 @@ func (f *fuzzer) fuzz() int { // This spongeDb is used to check the sequence of disk-db-writes var ( spongeA = &spongeDb{sponge: sha3.NewLegacyKeccak256()} - dbA = trie.NewDatabase(rawdb.NewDatabase(spongeA)) + dbA = trie.NewDatabase(rawdb.NewDatabase(spongeA), nil) trieA = trie.NewEmpty(dbA) spongeB = &spongeDb{sponge: sha3.NewLegacyKeccak256()} - dbB = trie.NewDatabase(rawdb.NewDatabase(spongeB)) - trieB = trie.NewStackTrie(func(owner common.Hash, path []byte, hash common.Hash, blob []byte) { - rawdb.WriteTrieNode(spongeB, owner, path, hash, blob, dbB.Scheme()) + dbB = trie.NewDatabase(rawdb.NewDatabase(spongeB), nil) + trieB = trie.NewStackTrie(func(path []byte, hash common.Hash, blob []byte) { + rawdb.WriteTrieNode(spongeB, common.Hash{}, path, hash, blob, dbB.Scheme()) }) vals []kv useful bool @@ -205,12 +205,9 @@ // Ensure all the nodes are persisted correctly var ( nodeset = make(map[string][]byte) // path -> blob - trieC = trie.NewStackTrie(func(owner common.Hash, path []byte, hash common.Hash, blob []byte) { + trieC = trie.NewStackTrie(func(path []byte, hash common.Hash, blob []byte) { if crypto.Keccak256Hash(blob) != hash { panic("invalid node blob") - } - if owner != (common.Hash{}) { - panic("invalid node owner") } nodeset[string(path)] = common.CopyBytes(blob) })
diff --git ethereum/go-ethereum/tests/fuzzers/trie/trie-fuzzer.go taikoxyz/taiko-geth/tests/fuzzers/trie/trie-fuzzer.go index fe9bf3d0fd3ded2ff38a268db86006270b0cf4cf..687f5efb1ceafa78f9ae40dfe3393f3a8d442662 100644 --- ethereum/go-ethereum/tests/fuzzers/trie/trie-fuzzer.go +++ taikoxyz/taiko-geth/tests/fuzzers/trie/trie-fuzzer.go @@ -143,7 +143,7 @@ }   func runRandTest(rt randTest) error { var ( - triedb = trie.NewDatabase(rawdb.NewMemoryDatabase()) + triedb = trie.NewDatabase(rawdb.NewMemoryDatabase(), nil) tr = trie.NewEmpty(triedb) origin = types.EmptyRootHash values = make(map[string]string) // tracks content of the trie
diff --git ethereum/go-ethereum/tests/fuzzers/txfetcher/txfetcher_fuzzer.go taikoxyz/taiko-geth/tests/fuzzers/txfetcher/txfetcher_fuzzer.go index 56b6b1e64eaa8625ce3c92e5f48d644dfe954ea5..8b501645b6631da52fc851acde8f3d5aa7754866 100644 --- ethereum/go-ethereum/tests/fuzzers/txfetcher/txfetcher_fuzzer.go +++ taikoxyz/taiko-geth/tests/fuzzers/txfetcher/txfetcher_fuzzer.go @@ -25,7 +25,6 @@ "time"   "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common/mclock" - "github.com/ethereum/go-ethereum/core/txpool" "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/eth/fetcher" ) @@ -80,10 +79,11 @@ rand := rand.New(rand.NewSource(0x3a29)) // Same used in package tests!!!   f := fetcher.NewTxFetcherForTests( func(common.Hash) bool { return false }, - func(txs []*txpool.Transaction) []error { + func(txs []*types.Transaction) []error { return make([]error, len(txs)) }, func(string, []common.Hash) error { return nil }, + nil, clock, rand, ) f.Start() @@ -117,6 +117,8 @@ var ( announceIdxs = make([]int, announce) announces = make([]common.Hash, announce) + types = make([]byte, announce) + sizes = make([]uint32, announce) ) for i := 0; i < len(announces); i++ { annBuf := make([]byte, 2) @@ -125,11 +127,13 @@ return 0 } announceIdxs[i] = (int(annBuf[0])*256 + int(annBuf[1])) % len(txs) announces[i] = txs[announceIdxs[i]].Hash() + types[i] = txs[announceIdxs[i]].Type() + sizes[i] = uint32(txs[announceIdxs[i]].Size()) } if verbose { fmt.Println("Notify", peer, announceIdxs) } - if err := f.Notify(peer, announces); err != nil { + if err := f.Notify(peer, types, sizes, announces); err != nil { panic(err) }
diff --git ethereum/go-ethereum/tests/init.go taikoxyz/taiko-geth/tests/init.go index a04e227dc7afe7e2ac10d79d9474f1c4d49bece4..99b7e4d33310197abddec8960d869f61818bb20b 100644 --- ethereum/go-ethereum/tests/init.go +++ taikoxyz/taiko-geth/tests/init.go @@ -318,6 +318,25 @@ TerminalTotalDifficulty: big.NewInt(0), ShanghaiTime: u64(0), CancunTime: u64(0), }, + "ShanghaiToCancunAtTime15k": { + ChainID: big.NewInt(1), + HomesteadBlock: big.NewInt(0), + EIP150Block: big.NewInt(0), + EIP155Block: big.NewInt(0), + EIP158Block: big.NewInt(0), + ByzantiumBlock: big.NewInt(0), + ConstantinopleBlock: big.NewInt(0), + PetersburgBlock: big.NewInt(0), + IstanbulBlock: big.NewInt(0), + MuirGlacierBlock: big.NewInt(0), + BerlinBlock: big.NewInt(0), + LondonBlock: big.NewInt(0), + ArrowGlacierBlock: big.NewInt(0), + MergeNetsplitBlock: big.NewInt(0), + TerminalTotalDifficulty: big.NewInt(0), + ShanghaiTime: u64(0), + CancunTime: u64(15_000), + }, }   // AvailableForks returns the set of defined fork names
diff --git ethereum/go-ethereum/tests/init_test.go taikoxyz/taiko-geth/tests/init_test.go index 7d8743efcc71b1456dfe23d2f2f469c974ca3768..3ab15e76583212b37e598578c2da5681eb94fcb6 100644 --- ethereum/go-ethereum/tests/init_test.go +++ taikoxyz/taiko-geth/tests/init_test.go @@ -41,6 +41,7 @@ legacyStateTestDir = filepath.Join(baseDir, "LegacyTests", "Constantinople", "GeneralStateTests") transactionTestDir = filepath.Join(baseDir, "TransactionTests") rlpTestDir = filepath.Join(baseDir, "RLPTests") difficultyTestDir = filepath.Join(baseDir, "BasicTests") + executionSpecDir = filepath.Join(".", "spec-tests", "fixtures") benchmarksDir = filepath.Join(".", "evm-benchmarks", "benchmarks") )
diff --git ethereum/go-ethereum/tests/state_test.go taikoxyz/taiko-geth/tests/state_test.go index 782f1b0b4c294e4ae735067d35fe8d0d9850a45a..094dafcafd7a372b7f8331d14fe1b387bc5a7357 100644 --- ethereum/go-ethereum/tests/state_test.go +++ taikoxyz/taiko-geth/tests/state_test.go @@ -30,6 +30,8 @@ "time"   "github.com/ethereum/go-ethereum/core" "github.com/ethereum/go-ethereum/core/rawdb" + "github.com/ethereum/go-ethereum/core/state" + "github.com/ethereum/go-ethereum/core/state/snapshot" "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/core/vm" "github.com/ethereum/go-ethereum/eth/tracers/logger" @@ -78,21 +80,52 @@ for _, subtest := range test.Subtests() { subtest := subtest key := fmt.Sprintf("%s/%d", subtest.Fork, subtest.Index)   - t.Run(key+"/trie", func(t *testing.T) { + t.Run(key+"/hash/trie", func(t *testing.T) { withTrace(t, test.gasLimit(subtest), func(vmconfig vm.Config) error { - _, _, err := test.Run(subtest, vmconfig, false) - return st.checkFailure(t, err) + var result error + test.Run(subtest, vmconfig, false, rawdb.HashScheme, func(err error, snaps *snapshot.Tree, state *state.StateDB) { + result = st.checkFailure(t, err) + }) + return result }) }) - t.Run(key+"/snap", func(t *testing.T) { + t.Run(key+"/hash/snap", func(t *testing.T) { withTrace(t, test.gasLimit(subtest), func(vmconfig vm.Config) error { - snaps, statedb, err := test.Run(subtest, vmconfig, true) - if snaps != nil && statedb != nil { - if _, err := snaps.Journal(statedb.IntermediateRoot(false)); err != nil { - return err + var result error + test.Run(subtest, vmconfig, true, rawdb.HashScheme, func(err error, snaps *snapshot.Tree, state *state.StateDB) { + if snaps != nil && state != nil { + if _, err := snaps.Journal(state.IntermediateRoot(false)); err != nil { + result = err + return + } } - } - return st.checkFailure(t, err) + result = st.checkFailure(t, err) + }) + return result + }) + }) + t.Run(key+"/path/trie", func(t *testing.T) { + withTrace(t, test.gasLimit(subtest), func(vmconfig vm.Config) error { + var result error + test.Run(subtest, vmconfig, false, rawdb.PathScheme, func(err error, snaps *snapshot.Tree, state *state.StateDB) { + result = st.checkFailure(t, err) + }) + return result + }) + }) + t.Run(key+"/path/snap", func(t *testing.T) { + withTrace(t, test.gasLimit(subtest), func(vmconfig vm.Config) error { + var result error + test.Run(subtest, vmconfig, true, rawdb.PathScheme, func(err error, snaps *snapshot.Tree, state *state.StateDB) { + if snaps != nil && state != nil { + if _, err := snaps.Journal(state.IntermediateRoot(false)); err != nil { + result = err + return + } + } + result = st.checkFailure(t, err) + }) + return result }) }) } @@ -190,7 +223,8 @@ var rules = config.Rules(new(big.Int), false, 0)   vmconfig.ExtraEips = eips block := t.genesis(config).ToBlock() - _, statedb := MakePreState(rawdb.NewMemoryDatabase(), t.json.Pre, false) + triedb, _, statedb := MakePreState(rawdb.NewMemoryDatabase(), t.json.Pre, false, rawdb.HashScheme) + defer triedb.Close()   var baseFee *big.Int if rules.IsLondon {
diff --git ethereum/go-ethereum/tests/state_test_util.go taikoxyz/taiko-geth/tests/state_test_util.go index 42f0c662ee42eb4f5fc28b54a9cfcd5d5f0851b2..8c255c1b5bd23c1c3fa374fb997d57f596c3a56d 100644 --- ethereum/go-ethereum/tests/state_test_util.go +++ taikoxyz/taiko-geth/tests/state_test_util.go @@ -39,6 +39,8 @@ "github.com/ethereum/go-ethereum/ethdb" "github.com/ethereum/go-ethereum/params" "github.com/ethereum/go-ethereum/rlp" "github.com/ethereum/go-ethereum/trie" + "github.com/ethereum/go-ethereum/trie/triedb/hashdb" + "github.com/ethereum/go-ethereum/trie/triedb/pathdb" "golang.org/x/crypto/sha3" )   @@ -113,6 +115,7 @@ AccessLists []*types.AccessList `json:"accessLists,omitempty"` GasLimit []uint64 `json:"gasLimit"` Value []string `json:"value"` PrivateKey []byte `json:"secretKey"` + Sender *common.Address `json:"sender"` BlobVersionedHashes []common.Hash `json:"blobVersionedHashes,omitempty"` BlobGasFeeCap *big.Int `json:"maxFeePerBlobGas,omitempty"` } @@ -187,43 +190,50 @@ return nil }   // Run executes a specific subtest and verifies the post-state and logs -func (t *StateTest) Run(subtest StateSubtest, vmconfig vm.Config, snapshotter bool) (*snapshot.Tree, *state.StateDB, error) { - snaps, statedb, root, err := t.RunNoVerify(subtest, vmconfig, snapshotter) - if checkedErr := t.checkError(subtest, err); checkedErr != nil { - return snaps, statedb, checkedErr +func (t *StateTest) Run(subtest StateSubtest, vmconfig vm.Config, snapshotter bool, scheme string, postCheck func(err error, snaps *snapshot.Tree, state *state.StateDB)) (result error) { + triedb, snaps, statedb, root, err := t.RunNoVerify(subtest, vmconfig, snapshotter, scheme) + + // Invoke the callback at the end of function for further analysis. + defer func() { + postCheck(result, snaps, statedb) + + if triedb != nil { + triedb.Close() + } + }() + checkedErr := t.checkError(subtest, err) + if checkedErr != nil { + return checkedErr } // The error has been checked; if it was unexpected, it's already returned. if err != nil { // Here, an error exists but it was expected. // We do not check the post state or logs. - return snaps, statedb, nil + return nil } post := t.json.Post[subtest.Fork][subtest.Index] // N.B: We need to do this in a two-step process, because the first Commit takes care // of self-destructs, and we need to touch the coinbase _after_ it has potentially self-destructed. if root != common.Hash(post.Root) { - return snaps, statedb, fmt.Errorf("post state root mismatch: got %x, want %x", root, post.Root) + return fmt.Errorf("post state root mismatch: got %x, want %x", root, post.Root) } if logs := rlpHash(statedb.Logs()); logs != common.Hash(post.Logs) { - return snaps, statedb, fmt.Errorf("post state logs hash mismatch: got %x, want %x", logs, post.Logs) - } - // Re-init the post-state instance for further operation - statedb, err = state.New(root, statedb.Database(), snaps) - if err != nil { - return nil, nil, err + return fmt.Errorf("post state logs hash mismatch: got %x, want %x", logs, post.Logs) } - return snaps, statedb, nil + statedb, _ = state.New(root, statedb.Database(), snaps) + return nil }   // RunNoVerify runs a specific subtest and returns the statedb and post-state root -func (t *StateTest) RunNoVerify(subtest StateSubtest, vmconfig vm.Config, snapshotter bool) (*snapshot.Tree, *state.StateDB, common.Hash, error) { +func (t *StateTest) RunNoVerify(subtest StateSubtest, vmconfig vm.Config, snapshotter bool, scheme string) (*trie.Database, *snapshot.Tree, *state.StateDB, common.Hash, error) { config, eips, err := GetChainConfig(subtest.Fork) if err != nil { - return nil, nil, common.Hash{}, UnsupportedForkError{subtest.Fork} + return nil, nil, nil, common.Hash{}, UnsupportedForkError{subtest.Fork} } vmconfig.ExtraEips = eips + block := t.genesis(config).ToBlock() - snaps, statedb := MakePreState(rawdb.NewMemoryDatabase(), t.json.Pre, snapshotter) + triedb, snaps, statedb := MakePreState(rawdb.NewMemoryDatabase(), t.json.Pre, snapshotter, scheme)   var baseFee *big.Int if config.IsLondon(new(big.Int)) { @@ -237,7 +247,8 @@ } post := t.json.Post[subtest.Fork][subtest.Index] msg, err := t.json.Tx.toMessage(post, baseFee) if err != nil { - return nil, nil, common.Hash{}, err + triedb.Close() + return nil, nil, nil, common.Hash{}, err }   // Try to recover tx with current signer @@ -245,11 +256,13 @@ if len(post.TxBytes) != 0 { var ttx types.Transaction err := ttx.UnmarshalBinary(post.TxBytes) if err != nil { - return nil, nil, common.Hash{}, err + triedb.Close() + return nil, nil, nil, common.Hash{}, err }   if _, err := types.Sender(types.LatestSigner(config), &ttx); err != nil { - return nil, nil, common.Hash{}, err + triedb.Close() + return nil, nil, nil, common.Hash{}, err } }   @@ -268,6 +281,7 @@ context.Random = &rnd context.Difficulty = big.NewInt(0) } evm := vm.NewEVM(context, txContext, statedb, config, vmconfig) + // Execute the message. snapshot := statedb.Snapshot() gaspool := new(core.GasPool) @@ -282,17 +296,25 @@ // - the coinbase self-destructed, or // - there are only 'bad' transactions, which aren't executed. In those cases, // the coinbase gets no txfee, so isn't created, and thus needs to be touched statedb.AddBalance(block.Coinbase(), new(big.Int)) - // Commit block + + // Commit state mutations into database. root, _ := statedb.Commit(block.NumberU64(), config.IsEIP158(block.Number())) - return snaps, statedb, root, err + return triedb, snaps, statedb, root, err }   func (t *StateTest) gasLimit(subtest StateSubtest) uint64 { return t.json.Tx.GasLimit[t.json.Post[subtest.Fork][subtest.Index].Indexes.Gas] }   -func MakePreState(db ethdb.Database, accounts core.GenesisAlloc, snapshotter bool) (*snapshot.Tree, *state.StateDB) { - sdb := state.NewDatabaseWithConfig(db, &trie.Config{Preimages: true}) +func MakePreState(db ethdb.Database, accounts core.GenesisAlloc, snapshotter bool, scheme string) (*trie.Database, *snapshot.Tree, *state.StateDB) { + tconf := &trie.Config{Preimages: true} + if scheme == rawdb.HashScheme { + tconf.HashDB = hashdb.Defaults + } else { + tconf.PathDB = pathdb.Defaults + } + triedb := trie.NewDatabase(db, tconf) + sdb := state.NewDatabaseWithNodeDB(db, triedb) statedb, _ := state.New(types.EmptyRootHash, sdb, nil) for addr, a := range accounts { statedb.SetCode(addr, a.Code) @@ -313,10 +335,10 @@ Recovery: false, NoBuild: false, AsyncBuild: false, } - snaps, _ = snapshot.New(snapconfig, db, sdb.TrieDB(), root) + snaps, _ = snapshot.New(snapconfig, db, triedb, root) } statedb, _ = state.New(root, sdb, snaps) - return snaps, statedb + return triedb, snaps, statedb }   func (t *StateTest) genesis(config *params.ChainConfig) *core.Genesis { @@ -338,9 +360,12 @@ return genesis }   func (tx *stTransaction) toMessage(ps stPostState, baseFee *big.Int) (*core.Message, error) { - // Derive sender from private key if present. var from common.Address - if len(tx.PrivateKey) > 0 { + // If 'sender' field is present, use that + if tx.Sender != nil { + from = *tx.Sender + } else if len(tx.PrivateKey) > 0 { + // Derive sender from private key if needed. key, err := crypto.ToECDSA(tx.PrivateKey) if err != nil { return nil, fmt.Errorf("invalid private key: %v", err)
diff --git ethereum/go-ethereum/trie/database.go taikoxyz/taiko-geth/trie/database.go index 49a884fd7f39124c666f393716cf0e802fe72090..1e59f0908f38712d7360534644b0005596948b31 100644 --- ethereum/go-ethereum/trie/database.go +++ taikoxyz/taiko-geth/trie/database.go @@ -21,6 +21,7 @@ "errors"   "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/ethdb" + "github.com/ethereum/go-ethereum/log" "github.com/ethereum/go-ethereum/trie/triedb/hashdb" "github.com/ethereum/go-ethereum/trie/triedb/pathdb" "github.com/ethereum/go-ethereum/trie/trienode" @@ -29,12 +30,16 @@ )   // Config defines all necessary options for database. type Config struct { - Cache int // Memory allowance (MB) to use for caching trie nodes in memory - Preimages bool // Flag whether the preimage of trie key is recorded - PathDB *pathdb.Config // Configs for experimental path-based scheme, not used yet. + Preimages bool // Flag whether the preimage of node key is recorded + HashDB *hashdb.Config // Configs for hash-based scheme + PathDB *pathdb.Config // Configs for experimental path-based scheme +}   - // Testing hooks - OnCommit func(states *triestate.Set) // Hook invoked when commit is performed +// HashDefaults represents a config for using hash-based scheme with +// default settings. +var HashDefaults = &Config{ + Preimages: false, + HashDB: hashdb.Defaults, }   // backend defines the methods needed to access/update trie nodes in different @@ -47,9 +52,12 @@ // Initialized returns an indicator if the state data is already initialized // according to the state scheme. Initialized(genesisRoot common.Hash) bool   - // Size returns the current storage size of the memory cache in front of the - // persistent database layer. - Size() common.StorageSize + // Size returns the current storage size of the diff layers on top of the + // disk layer and the storage size of the nodes cached in the disk layer. + // + // For hash scheme, there is no differentiation between diff layer nodes + // and dirty disk layer nodes, so both are merged into the second return. + Size() (common.StorageSize, common.StorageSize)   // Update performs a state transition by committing dirty nodes contained // in the given set in order to update state from the specified parent to @@ -77,36 +85,30 @@ preimages *preimageStore // The store for caching preimages backend backend // The backend for managing trie nodes }   -// prepare initializes the database with provided configs, but the -// database backend is still left as nil. -func prepare(diskdb ethdb.Database, config *Config) *Database { +// NewDatabase initializes the trie database with default settings, note +// the legacy hash-based scheme is used by default. +func NewDatabase(diskdb ethdb.Database, config *Config) *Database { + // Sanitize the config and use the default one if it's not specified. + if config == nil { + config = HashDefaults + } var preimages *preimageStore - if config != nil && config.Preimages { + if config.Preimages { preimages = newPreimageStore(diskdb) } - return &Database{ + db := &Database{ config: config, diskdb: diskdb, preimages: preimages, } -} - -// NewDatabase initializes the trie database with default settings, namely -// the legacy hash-based scheme is used by default. -func NewDatabase(diskdb ethdb.Database) *Database { - return NewDatabaseWithConfig(diskdb, nil) -} - -// NewDatabaseWithConfig initializes the trie database with provided configs. -// The path-based scheme is not activated yet, always initialized with legacy -// hash-based scheme by default. -func NewDatabaseWithConfig(diskdb ethdb.Database, config *Config) *Database { - var cleans int - if config != nil && config.Cache != 0 { - cleans = config.Cache * 1024 * 1024 + if config.HashDB != nil && config.PathDB != nil { + log.Crit("Both 'hash' and 'path' mode are configured") + } + if config.PathDB != nil { + db.backend = pathdb.New(diskdb, config.PathDB) + } else { + db.backend = hashdb.New(diskdb, config.HashDB, mptResolver{}) } - db := prepare(diskdb, config) - db.backend = hashdb.New(diskdb, cleans, mptResolver{}) return db }   @@ -130,9 +132,6 @@ // // The passed in maps(nodes, states) will be retained to avoid copying everything. // Therefore, these maps must not be changed afterwards. func (db *Database) Update(root common.Hash, parent common.Hash, block uint64, nodes *trienode.MergedNodeSet, states *triestate.Set) error { - if db.config != nil && db.config.OnCommit != nil { - db.config.OnCommit(states) - } if db.preimages != nil { db.preimages.commit(false) } @@ -149,18 +148,19 @@ } return db.backend.Commit(root, report) }   -// Size returns the storage size of dirty trie nodes in front of the persistent -// database and the size of cached preimages. -func (db *Database) Size() (common.StorageSize, common.StorageSize) { +// Size returns the storage size of diff layer nodes above the persistent disk +// layer, the dirty nodes buffered within the disk layer, and the size of cached +// preimages. +func (db *Database) Size() (common.StorageSize, common.StorageSize, common.StorageSize) { var ( - storages common.StorageSize - preimages common.StorageSize + diffs, nodes common.StorageSize + preimages common.StorageSize ) - storages = db.backend.Size() + diffs, nodes = db.backend.Size() if db.preimages != nil { preimages = db.preimages.size() } - return storages, preimages + return diffs, nodes, preimages }   // Initialized returns an indicator if the state data is already initialized @@ -187,6 +187,15 @@ func (db *Database) WritePreimages() { if db.preimages != nil { db.preimages.commit(true) } +} + +// Preimage retrieves a cached trie node pre-image from memory. If it cannot be +// found cached, the method queries the persistent database for the content. +func (db *Database) Preimage(hash common.Hash) []byte { + if db.preimages == nil { + return nil + } + return db.preimages.preimage(hash) }   // Cap iteratively flushes old but still referenced trie nodes until the total @@ -240,3 +249,72 @@ return nil, errors.New("not supported") } return hdb.Node(hash) } + +// Recover rollbacks the database to a specified historical point. The state is +// supported as the rollback destination only if it's canonical state and the +// corresponding trie histories are existent. It's only supported by path-based +// database and will return an error for others. +func (db *Database) Recover(target common.Hash) error { + pdb, ok := db.backend.(*pathdb.Database) + if !ok { + return errors.New("not supported") + } + return pdb.Recover(target, &trieLoader{db: db}) +} + +// Recoverable returns the indicator if the specified state is enabled to be +// recovered. It's only supported by path-based database and will return an +// error for others. +func (db *Database) Recoverable(root common.Hash) (bool, error) { + pdb, ok := db.backend.(*pathdb.Database) + if !ok { + return false, errors.New("not supported") + } + return pdb.Recoverable(root), nil +} + +// Disable deactivates the database and invalidates all available state layers +// as stale to prevent access to the persistent state, which is in the syncing +// stage. +// +// It's only supported by path-based database and will return an error for others. +func (db *Database) Disable() error { + pdb, ok := db.backend.(*pathdb.Database) + if !ok { + return errors.New("not supported") + } + return pdb.Disable() +} + +// Enable activates database and resets the state tree with the provided persistent +// state root once the state sync is finished. +func (db *Database) Enable(root common.Hash) error { + pdb, ok := db.backend.(*pathdb.Database) + if !ok { + return errors.New("not supported") + } + return pdb.Enable(root) +} + +// Journal commits an entire diff hierarchy to disk into a single journal entry. +// This is meant to be used during shutdown to persist the snapshot without +// flattening everything down (bad for reorgs). It's only supported by path-based +// database and will return an error for others. +func (db *Database) Journal(root common.Hash) error { + pdb, ok := db.backend.(*pathdb.Database) + if !ok { + return errors.New("not supported") + } + return pdb.Journal(root) +} + +// SetBufferSize sets the node buffer size to the provided value(in bytes). +// It's only supported by path-based database and will return an error for +// others. +func (db *Database) SetBufferSize(size int) error { + pdb, ok := db.backend.(*pathdb.Database) + if !ok { + return errors.New("not supported") + } + return pdb.SetBufferSize(size) +}
diff --git ethereum/go-ethereum/trie/database_test.go taikoxyz/taiko-geth/trie/database_test.go index ed43a81e5976e8196bf8a367cbbe75986bffc942..d508c6553319ab6a9ff197e36a992aa103fe69af 100644 --- ethereum/go-ethereum/trie/database_test.go +++ taikoxyz/taiko-geth/trie/database_test.go @@ -25,11 +25,16 @@ )   // newTestDatabase initializes the trie database with specified scheme. func newTestDatabase(diskdb ethdb.Database, scheme string) *Database { - db := prepare(diskdb, nil) + config := &Config{Preimages: false} if scheme == rawdb.HashScheme { - db.backend = hashdb.New(diskdb, 0, mptResolver{}) + config.HashDB = &hashdb.Config{ + CleanCacheSize: 0, + } // disable clean cache } else { - db.backend = pathdb.New(diskdb, &pathdb.Config{}) // disable clean/dirty cache + config.PathDB = &pathdb.Config{ + CleanCacheSize: 0, + DirtyCacheSize: 0, + } // disable clean/dirty cache } - return db + return NewDatabase(diskdb, config) }
diff --git ethereum/go-ethereum/trie/encoding.go taikoxyz/taiko-geth/trie/encoding.go index 8ee0022ef3a09d5902b9610ac6ceb4e7191782d9..3284d3f8f0218e299efb82730d3375767f1c7bd3 100644 --- ethereum/go-ethereum/trie/encoding.go +++ taikoxyz/taiko-geth/trie/encoding.go @@ -51,9 +51,8 @@ decodeNibbles(hex, buf[1:]) return buf }   -// hexToCompactInPlace places the compact key in input buffer, returning the length -// needed for the representation -func hexToCompactInPlace(hex []byte) int { +// hexToCompactInPlace places the compact key in input buffer, returning the compacted key. +func hexToCompactInPlace(hex []byte) []byte { var ( hexLen = len(hex) // length of the hex input firstByte = byte(0) @@ -77,7 +76,7 @@ for ; ni < hexLen; bi, ni = bi+1, ni+2 { hex[bi] = hex[ni]<<4 | hex[ni+1] } hex[0] = firstByte - return binLen + return hex[:binLen] }   func compactToHex(compact []byte) []byte {
diff --git ethereum/go-ethereum/trie/encoding_test.go taikoxyz/taiko-geth/trie/encoding_test.go index d16d25c359c7741f63f18fc0cdaa031765169441..ac50b5d025e56d8fcf1cc3a9e2f8081657b51c43 100644 --- ethereum/go-ethereum/trie/encoding_test.go +++ taikoxyz/taiko-geth/trie/encoding_test.go @@ -86,8 +86,7 @@ "10", } { hexBytes, _ := hex.DecodeString(key) exp := hexToCompact(hexBytes) - sz := hexToCompactInPlace(hexBytes) - got := hexBytes[:sz] + got := hexToCompactInPlace(hexBytes) if !bytes.Equal(exp, got) { t.Fatalf("test %d: encoding err\ninp %v\ngot %x\nexp %x\n", i, key, got, exp) } @@ -102,8 +101,7 @@ crand.Read(key) hexBytes := keybytesToHex(key) hexOrig := []byte(string(hexBytes)) exp := hexToCompact(hexBytes) - sz := hexToCompactInPlace(hexBytes) - got := hexBytes[:sz] + got := hexToCompactInPlace(hexBytes)   if !bytes.Equal(exp, got) { t.Fatalf("encoding err \ncpt %x\nhex %x\ngot %x\nexp %x\n", @@ -116,6 +114,13 @@ func BenchmarkHexToCompact(b *testing.B) { testBytes := []byte{0, 15, 1, 12, 11, 8, 16 /*term*/} for i := 0; i < b.N; i++ { hexToCompact(testBytes) + } +} + +func BenchmarkHexToCompactInPlace(b *testing.B) { + testBytes := []byte{0, 15, 1, 12, 11, 8, 16 /*term*/} + for i := 0; i < b.N; i++ { + hexToCompactInPlace(testBytes) } }
diff --git ethereum/go-ethereum/trie/iterator_test.go taikoxyz/taiko-geth/trie/iterator_test.go index e711ffb8158356eb88017572e678d1f80b03fd27..57d1f06a160a3ec851f8ec0db9ab5cd71038d406 100644 --- ethereum/go-ethereum/trie/iterator_test.go +++ taikoxyz/taiko-geth/trie/iterator_test.go @@ -18,7 +18,6 @@ package trie   import ( "bytes" - "encoding/binary" "fmt" "math/rand" "testing" @@ -27,13 +26,11 @@ "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/core/rawdb" "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/crypto" - "github.com/ethereum/go-ethereum/ethdb" - "github.com/ethereum/go-ethereum/ethdb/memorydb" "github.com/ethereum/go-ethereum/trie/trienode" )   func TestEmptyIterator(t *testing.T) { - trie := NewEmpty(NewDatabase(rawdb.NewMemoryDatabase())) + trie := NewEmpty(NewDatabase(rawdb.NewMemoryDatabase(), nil)) iter := trie.MustNodeIterator(nil)   seen := make(map[string]struct{}) @@ -46,7 +43,7 @@ } }   func TestIterator(t *testing.T) { - db := NewDatabase(rawdb.NewMemoryDatabase()) + db := NewDatabase(rawdb.NewMemoryDatabase(), nil) trie := NewEmpty(db) vals := []struct{ k, v string }{ {"do", "verb"}, @@ -89,7 +86,7 @@ return bytes.Compare(k.k, other.k) }   func TestIteratorLargeData(t *testing.T) { - trie := NewEmpty(NewDatabase(rawdb.NewMemoryDatabase())) + trie := NewEmpty(NewDatabase(rawdb.NewMemoryDatabase(), nil)) vals := make(map[string]*kv)   for i := byte(0); i < 255; i++ { @@ -208,7 +205,7 @@ {"jars", "d"}, }   func TestIteratorSeek(t *testing.T) { - trie := NewEmpty(NewDatabase(rawdb.NewMemoryDatabase())) + trie := NewEmpty(NewDatabase(rawdb.NewMemoryDatabase(), nil)) for _, val := range testdata1 { trie.MustUpdate([]byte(val.k), []byte(val.v)) } @@ -249,7 +246,7 @@ return nil }   func TestDifferenceIterator(t *testing.T) { - dba := NewDatabase(rawdb.NewMemoryDatabase()) + dba := NewDatabase(rawdb.NewMemoryDatabase(), nil) triea := NewEmpty(dba) for _, val := range testdata1 { triea.MustUpdate([]byte(val.k), []byte(val.v)) @@ -258,7 +255,7 @@ rootA, nodesA, _ := triea.Commit(false) dba.Update(rootA, types.EmptyRootHash, 0, trienode.NewWithNodeSet(nodesA), nil) triea, _ = New(TrieID(rootA), dba)   - dbb := NewDatabase(rawdb.NewMemoryDatabase()) + dbb := NewDatabase(rawdb.NewMemoryDatabase(), nil) trieb := NewEmpty(dbb) for _, val := range testdata2 { trieb.MustUpdate([]byte(val.k), []byte(val.v)) @@ -291,7 +288,7 @@ } }   func TestUnionIterator(t *testing.T) { - dba := NewDatabase(rawdb.NewMemoryDatabase()) + dba := NewDatabase(rawdb.NewMemoryDatabase(), nil) triea := NewEmpty(dba) for _, val := range testdata1 { triea.MustUpdate([]byte(val.k), []byte(val.v)) @@ -300,7 +297,7 @@ rootA, nodesA, _ := triea.Commit(false) dba.Update(rootA, types.EmptyRootHash, 0, trienode.NewWithNodeSet(nodesA), nil) triea, _ = New(TrieID(rootA), dba)   - dbb := NewDatabase(rawdb.NewMemoryDatabase()) + dbb := NewDatabase(rawdb.NewMemoryDatabase(), nil) trieb := NewEmpty(dbb) for _, val := range testdata2 { trieb.MustUpdate([]byte(val.k), []byte(val.v)) @@ -344,7 +341,7 @@ } }   func TestIteratorNoDups(t *testing.T) { - tr := NewEmpty(NewDatabase(rawdb.NewMemoryDatabase())) + tr := NewEmpty(NewDatabase(rawdb.NewMemoryDatabase(), nil)) for _, val := range testdata1 { tr.MustUpdate([]byte(val.k), []byte(val.v)) } @@ -537,96 +534,6 @@ testIteratorNodeBlob(t, rawdb.HashScheme) testIteratorNodeBlob(t, rawdb.PathScheme) }   -type loggingDb struct { - getCount uint64 - backend ethdb.KeyValueStore -} - -func (l *loggingDb) Has(key []byte) (bool, error) { - return l.backend.Has(key) -} - -func (l *loggingDb) Get(key []byte) ([]byte, error) { - l.getCount++ - return l.backend.Get(key) -} - -func (l *loggingDb) Put(key []byte, value []byte) error { - return l.backend.Put(key, value) -} - -func (l *loggingDb) Delete(key []byte) error { - return l.backend.Delete(key) -} - -func (l *loggingDb) NewBatch() ethdb.Batch { - return l.backend.NewBatch() -} - -func (l *loggingDb) NewBatchWithSize(size int) ethdb.Batch { - return l.backend.NewBatchWithSize(size) -} - -func (l *loggingDb) NewIterator(prefix []byte, start []byte) ethdb.Iterator { - return l.backend.NewIterator(prefix, start) -} - -func (l *loggingDb) NewSnapshot() (ethdb.Snapshot, error) { - return l.backend.NewSnapshot() -} - -func (l *loggingDb) Stat(property string) (string, error) { - return l.backend.Stat(property) -} - -func (l *loggingDb) Compact(start []byte, limit []byte) error { - return l.backend.Compact(start, limit) -} - -func (l *loggingDb) Close() error { - return l.backend.Close() -} - -// makeLargeTestTrie create a sample test trie -func makeLargeTestTrie() (*Database, *StateTrie, *loggingDb) { - // Create an empty trie - logDb := &loggingDb{0, memorydb.New()} - triedb := NewDatabase(rawdb.NewDatabase(logDb)) - trie, _ := NewStateTrie(TrieID(types.EmptyRootHash), triedb) - - // Fill it with some arbitrary data - for i := 0; i < 10000; i++ { - key := make([]byte, 32) - val := make([]byte, 32) - binary.BigEndian.PutUint64(key, uint64(i)) - binary.BigEndian.PutUint64(val, uint64(i)) - key = crypto.Keccak256(key) - val = crypto.Keccak256(val) - trie.MustUpdate(key, val) - } - root, nodes, _ := trie.Commit(false) - triedb.Update(root, types.EmptyRootHash, 0, trienode.NewWithNodeSet(nodes), nil) - triedb.Commit(root, false) - - // Return the generated trie - trie, _ = NewStateTrie(TrieID(root), triedb) - return triedb, trie, logDb -} - -// Tests that the node iterator indeed walks over the entire database contents. -func TestNodeIteratorLargeTrie(t *testing.T) { - // Create some arbitrary test trie to iterate - db, trie, logDb := makeLargeTestTrie() - db.Cap(0) // flush everything - // Do a seek operation - trie.NodeIterator(common.FromHex("0x77667766776677766778855885885885")) - // master: 24 get operations - // this pr: 6 get operations - if have, want := logDb.getCount, uint64(6); have != want { - t.Fatalf("Too many lookups during seek, have %d want %d", have, want) - } -} - func testIteratorNodeBlob(t *testing.T, scheme string) { var ( db = rawdb.NewMemoryDatabase() @@ -700,7 +607,7 @@ return false, nil, common.Hash{} } hash = common.BytesToHash(key) } else { - ok, remain := rawdb.IsAccountTrieNode(key) + ok, remain := rawdb.ResolveAccountTrieNodeKey(key) if !ok { return false, nil, common.Hash{} }
diff --git ethereum/go-ethereum/trie/proof.go taikoxyz/taiko-geth/trie/proof.go index a463c80b4889bf3354b3c953c68ba1dc3f8620bd..a526a534025300bd1c78a69fffd1103d5574df75 100644 --- ethereum/go-ethereum/trie/proof.go +++ taikoxyz/taiko-geth/trie/proof.go @@ -481,7 +481,7 @@ // // Note: This method does not verify that the proof is of minimal form. If the input // proofs are 'bloated' with neighbour leaves or random data, aside from the 'useful' // data, then the proof will still be accepted. -func VerifyRangeProof(rootHash common.Hash, firstKey []byte, lastKey []byte, keys [][]byte, values [][]byte, proof ethdb.KeyValueReader) (bool, error) { +func VerifyRangeProof(rootHash common.Hash, firstKey []byte, keys [][]byte, values [][]byte, proof ethdb.KeyValueReader) (bool, error) { if len(keys) != len(values) { return false, fmt.Errorf("inconsistent proof data, keys: %d, values: %d", len(keys), len(values)) } @@ -520,6 +520,7 @@ return false, errors.New("more entries available") } return false, nil } + var lastKey = keys[len(keys)-1] // Special case, there is only one element and two edge keys are same. // In this case, we can't construct two edge paths. So handle it here. if len(keys) == 1 && bytes.Equal(firstKey, lastKey) {
diff --git ethereum/go-ethereum/trie/proof_test.go taikoxyz/taiko-geth/trie/proof_test.go index e8ea116c8803bfdc6b9d8c829f0e6ecb09b0e2d0..59ae201cea162f72e43060aff002c1dfddd08864 100644 --- ethereum/go-ethereum/trie/proof_test.go +++ taikoxyz/taiko-geth/trie/proof_test.go @@ -94,7 +94,7 @@ } }   func TestOneElementProof(t *testing.T) { - trie := NewEmpty(NewDatabase(rawdb.NewMemoryDatabase())) + trie := NewEmpty(NewDatabase(rawdb.NewMemoryDatabase(), nil)) updateString(trie, "k", "v") for i, prover := range makeProvers(trie) { proof := prover([]byte("k")) @@ -145,7 +145,7 @@ // Tests that missing keys can also be proven. The test explicitly uses a single // entry trie and checks for missing keys both before and after the single entry. func TestMissingKeyProof(t *testing.T) { - trie := NewEmpty(NewDatabase(rawdb.NewMemoryDatabase())) + trie := NewEmpty(NewDatabase(rawdb.NewMemoryDatabase(), nil)) updateString(trie, "k", "v")   for i, key := range []string{"a", "j", "l", "z"} { @@ -191,7 +191,7 @@ for i := start; i < end; i++ { keys = append(keys, entries[i].k) vals = append(vals, entries[i].v) } - _, err := VerifyRangeProof(trie.Hash(), keys[0], keys[len(keys)-1], keys, vals, proof) + _, err := VerifyRangeProof(trie.Hash(), keys[0], keys, vals, proof) if err != nil { t.Fatalf("Case %d(%d->%d) expect no error, got %v", i, start, end-1, err) } @@ -221,19 +221,10 @@ // Short circuit if the decreased key is underflow if bytes.Compare(first, entries[start].k) > 0 { continue } - // Short circuit if the increased key is same with the next key - last := increaseKey(common.CopyBytes(entries[end-1].k)) - if end != len(entries) && bytes.Equal(last, entries[end].k) { - continue - } - // Short circuit if the increased key is overflow - if bytes.Compare(last, entries[end-1].k) < 0 { - continue - } if err := trie.Prove(first, proof); err != nil { t.Fatalf("Failed to prove the first node %v", err) } - if err := trie.Prove(last, proof); err != nil { + if err := trie.Prove(entries[end-1].k, proof); err != nil { t.Fatalf("Failed to prove the last node %v", err) } var keys [][]byte @@ -242,36 +233,15 @@ for i := start; i < end; i++ { keys = append(keys, entries[i].k) vals = append(vals, entries[i].v) } - _, err := VerifyRangeProof(trie.Hash(), first, last, keys, vals, proof) + _, err := VerifyRangeProof(trie.Hash(), first, keys, vals, proof) if err != nil { t.Fatalf("Case %d(%d->%d) expect no error, got %v", i, start, end-1, err) } } - // Special case, two edge proofs for two edge key. - proof := memorydb.New() - first := common.HexToHash("0x0000000000000000000000000000000000000000000000000000000000000000").Bytes() - last := common.HexToHash("0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff").Bytes() - if err := trie.Prove(first, proof); err != nil { - t.Fatalf("Failed to prove the first node %v", err) - } - if err := trie.Prove(last, proof); err != nil { - t.Fatalf("Failed to prove the last node %v", err) - } - var k [][]byte - var v [][]byte - for i := 0; i < len(entries); i++ { - k = append(k, entries[i].k) - v = append(v, entries[i].v) - } - _, err := VerifyRangeProof(trie.Hash(), first, last, k, v, proof) - if err != nil { - t.Fatal("Failed to verify whole rang with non-existent edges") - } }   // TestRangeProofWithInvalidNonExistentProof tests such scenarios: // - There exists a gap between the first element and the left edge proof -// - There exists a gap between the last element and the right edge proof func TestRangeProofWithInvalidNonExistentProof(t *testing.T) { trie, vals := randomTrie(4096) var entries []*kv @@ -298,29 +268,7 @@ for i := start; i < end; i++ { k = append(k, entries[i].k) v = append(v, entries[i].v) } - _, err := VerifyRangeProof(trie.Hash(), first, k[len(k)-1], k, v, proof) - if err == nil { - t.Fatalf("Expected to detect the error, got nil") - } - - // Case 2 - start, end = 100, 200 - last := increaseKey(common.CopyBytes(entries[end-1].k)) - proof = memorydb.New() - if err := trie.Prove(entries[start].k, proof); err != nil { - t.Fatalf("Failed to prove the first node %v", err) - } - if err := trie.Prove(last, proof); err != nil { - t.Fatalf("Failed to prove the last node %v", err) - } - end = 195 // Capped slice - k = make([][]byte, 0) - v = make([][]byte, 0) - for i := start; i < end; i++ { - k = append(k, entries[i].k) - v = append(v, entries[i].v) - } - _, err = VerifyRangeProof(trie.Hash(), k[0], last, k, v, proof) + _, err := VerifyRangeProof(trie.Hash(), first, k, v, proof) if err == nil { t.Fatalf("Expected to detect the error, got nil") } @@ -344,7 +292,7 @@ proof := memorydb.New() if err := trie.Prove(entries[start].k, proof); err != nil { t.Fatalf("Failed to prove the first node %v", err) } - _, err := VerifyRangeProof(trie.Hash(), entries[start].k, entries[start].k, [][]byte{entries[start].k}, [][]byte{entries[start].v}, proof) + _, err := VerifyRangeProof(trie.Hash(), entries[start].k, [][]byte{entries[start].k}, [][]byte{entries[start].v}, proof) if err != nil { t.Fatalf("Expected no error, got %v", err) } @@ -359,7 +307,7 @@ } if err := trie.Prove(entries[start].k, proof); err != nil { t.Fatalf("Failed to prove the last node %v", err) } - _, err = VerifyRangeProof(trie.Hash(), first, entries[start].k, [][]byte{entries[start].k}, [][]byte{entries[start].v}, proof) + _, err = VerifyRangeProof(trie.Hash(), first, [][]byte{entries[start].k}, [][]byte{entries[start].v}, proof) if err != nil { t.Fatalf("Expected no error, got %v", err) } @@ -374,7 +322,7 @@ } if err := trie.Prove(last, proof); err != nil { t.Fatalf("Failed to prove the last node %v", err) } - _, err = VerifyRangeProof(trie.Hash(), entries[start].k, last, [][]byte{entries[start].k}, [][]byte{entries[start].v}, proof) + _, err = VerifyRangeProof(trie.Hash(), entries[start].k, [][]byte{entries[start].k}, [][]byte{entries[start].v}, proof) if err != nil { t.Fatalf("Expected no error, got %v", err) } @@ -389,13 +337,13 @@ } if err := trie.Prove(last, proof); err != nil { t.Fatalf("Failed to prove the last node %v", err) } - _, err = VerifyRangeProof(trie.Hash(), first, last, [][]byte{entries[start].k}, [][]byte{entries[start].v}, proof) + _, err = VerifyRangeProof(trie.Hash(), first, [][]byte{entries[start].k}, [][]byte{entries[start].v}, proof) if err != nil { t.Fatalf("Expected no error, got %v", err) }   // Test the mini trie with only a single element. - tinyTrie := NewEmpty(NewDatabase(rawdb.NewMemoryDatabase())) + tinyTrie := NewEmpty(NewDatabase(rawdb.NewMemoryDatabase(), nil)) entry := &kv{randBytes(32), randBytes(20), false} tinyTrie.MustUpdate(entry.k, entry.v)   @@ -408,7 +356,7 @@ } if err := tinyTrie.Prove(last, proof); err != nil { t.Fatalf("Failed to prove the last node %v", err) } - _, err = VerifyRangeProof(tinyTrie.Hash(), first, last, [][]byte{entry.k}, [][]byte{entry.v}, proof) + _, err = VerifyRangeProof(tinyTrie.Hash(), first, [][]byte{entry.k}, [][]byte{entry.v}, proof) if err != nil { t.Fatalf("Expected no error, got %v", err) } @@ -430,7 +378,7 @@ for i := 0; i < len(entries); i++ { k = append(k, entries[i].k) v = append(v, entries[i].v) } - _, err := VerifyRangeProof(trie.Hash(), nil, nil, k, v, nil) + _, err := VerifyRangeProof(trie.Hash(), nil, k, v, nil) if err != nil { t.Fatalf("Expected no error, got %v", err) } @@ -443,7 +391,7 @@ } if err := trie.Prove(entries[len(entries)-1].k, proof); err != nil { t.Fatalf("Failed to prove the last node %v", err) } - _, err = VerifyRangeProof(trie.Hash(), k[0], k[len(k)-1], k, v, proof) + _, err = VerifyRangeProof(trie.Hash(), k[0], k, v, proof) if err != nil { t.Fatalf("Expected no error, got %v", err) } @@ -451,14 +399,13 @@ // Even with non-existent edge proofs, it should still work. proof = memorydb.New() first := common.HexToHash("0x0000000000000000000000000000000000000000000000000000000000000000").Bytes() - last := common.HexToHash("0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff").Bytes() if err := trie.Prove(first, proof); err != nil { t.Fatalf("Failed to prove the first node %v", err) } - if err := trie.Prove(last, proof); err != nil { + if err := trie.Prove(entries[len(entries)-1].k, proof); err != nil { t.Fatalf("Failed to prove the last node %v", err) } - _, err = VerifyRangeProof(trie.Hash(), first, last, k, v, proof) + _, err = VerifyRangeProof(trie.Hash(), first, k, v, proof) if err != nil { t.Fatalf("Expected no error, got %v", err) } @@ -467,7 +414,7 @@ // TestSingleSideRangeProof tests the range starts from zero. func TestSingleSideRangeProof(t *testing.T) { for i := 0; i < 64; i++ { - trie := NewEmpty(NewDatabase(rawdb.NewMemoryDatabase())) + trie := NewEmpty(NewDatabase(rawdb.NewMemoryDatabase(), nil)) var entries []*kv for i := 0; i < 4096; i++ { value := &kv{randBytes(32), randBytes(20), false} @@ -491,43 +438,7 @@ for i := 0; i <= pos; i++ { k = append(k, entries[i].k) v = append(v, entries[i].v) } - _, err := VerifyRangeProof(trie.Hash(), common.Hash{}.Bytes(), k[len(k)-1], k, v, proof) - if err != nil { - t.Fatalf("Expected no error, got %v", err) - } - } - } -} - -// TestReverseSingleSideRangeProof tests the range ends with 0xffff...fff. -func TestReverseSingleSideRangeProof(t *testing.T) { - for i := 0; i < 64; i++ { - trie := NewEmpty(NewDatabase(rawdb.NewMemoryDatabase())) - var entries []*kv - for i := 0; i < 4096; i++ { - value := &kv{randBytes(32), randBytes(20), false} - trie.MustUpdate(value.k, value.v) - entries = append(entries, value) - } - slices.SortFunc(entries, (*kv).cmp) - - var cases = []int{0, 1, 50, 100, 1000, 2000, len(entries) - 1} - for _, pos := range cases { - proof := memorydb.New() - if err := trie.Prove(entries[pos].k, proof); err != nil { - t.Fatalf("Failed to prove the first node %v", err) - } - last := common.HexToHash("0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff") - if err := trie.Prove(last.Bytes(), proof); err != nil { - t.Fatalf("Failed to prove the last node %v", err) - } - k := make([][]byte, 0) - v := make([][]byte, 0) - for i := pos; i < len(entries); i++ { - k = append(k, entries[i].k) - v = append(v, entries[i].v) - } - _, err := VerifyRangeProof(trie.Hash(), k[0], last.Bytes(), k, v, proof) + _, err := VerifyRangeProof(trie.Hash(), common.Hash{}.Bytes(), k, v, proof) if err != nil { t.Fatalf("Expected no error, got %v", err) } @@ -561,7 +472,7 @@ for i := start; i < end; i++ { keys = append(keys, entries[i].k) vals = append(vals, entries[i].v) } - var first, last = keys[0], keys[len(keys)-1] + var first = keys[0] testcase := mrand.Intn(6) var index int switch testcase { @@ -576,7 +487,7 @@ vals[index] = randBytes(20) // In theory it can't be same case 2: // Gapped entry slice index = mrand.Intn(end - start) - if (index == 0 && start < 100) || (index == end-start-1 && end <= 100) { + if (index == 0 && start < 100) || (index == end-start-1) { continue } keys = append(keys[:index], keys[index+1:]...) @@ -599,7 +510,7 @@ // Set random value to nil, deletion index = mrand.Intn(end - start) vals[index] = nil } - _, err := VerifyRangeProof(trie.Hash(), first, last, keys, vals, proof) + _, err := VerifyRangeProof(trie.Hash(), first, keys, vals, proof) if err == nil { t.Fatalf("%d Case %d index %d range: (%d->%d) expect error, got nil", i, testcase, index, start, end-1) } @@ -609,7 +520,7 @@ // TestGappedRangeProof focuses on the small trie with embedded nodes. // If the gapped node is embedded in the trie, it should be detected too. func TestGappedRangeProof(t *testing.T) { - trie := NewEmpty(NewDatabase(rawdb.NewMemoryDatabase())) + trie := NewEmpty(NewDatabase(rawdb.NewMemoryDatabase(), nil)) var entries []*kv // Sorted entries for i := byte(0); i < 10; i++ { value := &kv{common.LeftPadBytes([]byte{i}, 32), []byte{i}, false} @@ -633,7 +544,7 @@ } keys = append(keys, entries[i].k) vals = append(vals, entries[i].v) } - _, err := VerifyRangeProof(trie.Hash(), keys[0], keys[len(keys)-1], keys, vals, proof) + _, err := VerifyRangeProof(trie.Hash(), keys[0], keys, vals, proof) if err == nil { t.Fatal("expect error, got nil") } @@ -649,24 +560,22 @@ } slices.SortFunc(entries, (*kv).cmp)   pos := 1000 - first := decreaseKey(common.CopyBytes(entries[pos].k)) - first = decreaseKey(first) - last := decreaseKey(common.CopyBytes(entries[pos].k)) + first := common.CopyBytes(entries[0].k)   proof := memorydb.New() if err := trie.Prove(first, proof); err != nil { t.Fatalf("Failed to prove the first node %v", err) } - if err := trie.Prove(last, proof); err != nil { - t.Fatalf("Failed to prove the last node %v", err) + if err := trie.Prove(entries[2000].k, proof); err != nil { + t.Fatalf("Failed to prove the first node %v", err) } - _, err := VerifyRangeProof(trie.Hash(), first, last, [][]byte{entries[pos].k}, [][]byte{entries[pos].v}, proof) + _, err := VerifyRangeProof(trie.Hash(), first, [][]byte{entries[pos].k}, [][]byte{entries[pos].v}, proof) if err == nil { t.Fatalf("Expected error, got nil") }   first = increaseKey(common.CopyBytes(entries[pos].k)) - last = increaseKey(common.CopyBytes(entries[pos].k)) + last := increaseKey(common.CopyBytes(entries[pos].k)) last = increaseKey(last)   proof = memorydb.New() @@ -676,14 +585,14 @@ } if err := trie.Prove(last, proof); err != nil { t.Fatalf("Failed to prove the last node %v", err) } - _, err = VerifyRangeProof(trie.Hash(), first, last, [][]byte{entries[pos].k}, [][]byte{entries[pos].v}, proof) + _, err = VerifyRangeProof(trie.Hash(), first, [][]byte{entries[pos].k}, [][]byte{entries[pos].v}, proof) if err == nil { t.Fatalf("Expected error, got nil") } }   func TestHasRightElement(t *testing.T) { - trie := NewEmpty(NewDatabase(rawdb.NewMemoryDatabase())) + trie := NewEmpty(NewDatabase(rawdb.NewMemoryDatabase(), nil)) var entries []*kv for i := 0; i < 4096; i++ { value := &kv{randBytes(32), randBytes(20), false} @@ -703,15 +612,12 @@ {0, 10, true}, {50, 100, true}, {50, len(entries), false}, // No more element expected {len(entries) - 1, len(entries), false}, // Single last element with two existent proofs(point to same key) - {len(entries) - 1, -1, false}, // Single last element with non-existent right proof {0, len(entries), false}, // The whole set with existent left proof {-1, len(entries), false}, // The whole set with non-existent left proof - {-1, -1, false}, // The whole set with non-existent left/right proof } for _, c := range cases { var ( firstKey []byte - lastKey []byte start = c.start end = c.end proof = memorydb.New() @@ -727,16 +633,8 @@ if err := trie.Prove(entries[c.start].k, proof); err != nil { t.Fatalf("Failed to prove the first node %v", err) } } - if c.end == -1 { - lastKey, end = common.HexToHash("0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff").Bytes(), len(entries) - if err := trie.Prove(lastKey, proof); err != nil { - t.Fatalf("Failed to prove the first node %v", err) - } - } else { - lastKey = entries[c.end-1].k - if err := trie.Prove(entries[c.end-1].k, proof); err != nil { - t.Fatalf("Failed to prove the first node %v", err) - } + if err := trie.Prove(entries[c.end-1].k, proof); err != nil { + t.Fatalf("Failed to prove the first node %v", err) } k := make([][]byte, 0) v := make([][]byte, 0) @@ -744,7 +642,7 @@ for i := start; i < end; i++ { k = append(k, entries[i].k) v = append(v, entries[i].v) } - hasMore, err := VerifyRangeProof(trie.Hash(), firstKey, lastKey, k, v, proof) + hasMore, err := VerifyRangeProof(trie.Hash(), firstKey, k, v, proof) if err != nil { t.Fatalf("Expected no error, got %v", err) } @@ -777,7 +675,7 @@ first := increaseKey(common.CopyBytes(entries[c.pos].k)) if err := trie.Prove(first, proof); err != nil { t.Fatalf("Failed to prove the first node %v", err) } - _, err := VerifyRangeProof(trie.Hash(), first, nil, nil, nil, proof) + _, err := VerifyRangeProof(trie.Hash(), first, nil, nil, proof) if c.err && err == nil { t.Fatalf("Expected error, got nil") } @@ -817,7 +715,7 @@ want := memorydb.New() trie.Prove(keys[0], want) trie.Prove(keys[len(keys)-1], want)   - if _, err := VerifyRangeProof(trie.Hash(), keys[0], keys[len(keys)-1], keys, vals, proof); err != nil { + if _, err := VerifyRangeProof(trie.Hash(), keys[0], keys, vals, proof); err != nil { t.Fatalf("expected bloated proof to succeed, got %v", err) } } @@ -860,7 +758,7 @@ for i := start; i < end; i++ { keys = append(keys, entries[i].k) vals = append(vals, entries[i].v) } - _, err := VerifyRangeProof(trie.Hash(), keys[0], keys[len(keys)-1], keys, vals, proof) + _, err := VerifyRangeProof(trie.Hash(), keys[0], keys, vals, proof) if err == nil { t.Fatalf("Expected failure on noop entry") } @@ -895,7 +793,7 @@ for i := 0; i < len(entries); i++ { keys = append(keys, entries[i].k) vals = append(vals, entries[i].v) } - _, err := VerifyRangeProof(trie.Hash(), nil, nil, keys, vals, nil) + _, err := VerifyRangeProof(trie.Hash(), nil, keys, vals, nil) if err == nil { t.Fatalf("Expected failure on noop entry") } @@ -1001,7 +899,7 @@ }   b.ResetTimer() for i := 0; i < b.N; i++ { - _, err := VerifyRangeProof(trie.Hash(), keys[0], keys[len(keys)-1], keys, values, proof) + _, err := VerifyRangeProof(trie.Hash(), keys[0], keys, values, proof) if err != nil { b.Fatalf("Case %d(%d->%d) expect no error, got %v", i, start, end-1, err) } @@ -1028,7 +926,7 @@ values = append(values, entry.v) } b.ResetTimer() for i := 0; i < b.N; i++ { - _, err := VerifyRangeProof(trie.Hash(), keys[0], keys[len(keys)-1], keys, values, nil) + _, err := VerifyRangeProof(trie.Hash(), keys[0], keys, values, nil) if err != nil { b.Fatalf("Expected no error, got %v", err) } @@ -1036,7 +934,7 @@ } }   func randomTrie(n int) (*Trie, map[string]*kv) { - trie := NewEmpty(NewDatabase(rawdb.NewMemoryDatabase())) + trie := NewEmpty(NewDatabase(rawdb.NewMemoryDatabase(), nil)) vals := make(map[string]*kv) for i := byte(0); i < 100; i++ { value := &kv{common.LeftPadBytes([]byte{i}, 32), []byte{i}, false} @@ -1055,7 +953,7 @@ return trie, vals }   func nonRandomTrie(n int) (*Trie, map[string]*kv) { - trie := NewEmpty(NewDatabase(rawdb.NewMemoryDatabase())) + trie := NewEmpty(NewDatabase(rawdb.NewMemoryDatabase(), nil)) vals := make(map[string]*kv) max := uint64(0xffffffffffffffff) for i := uint64(0); i < uint64(n); i++ { @@ -1080,22 +978,21 @@ vals := [][]byte{ common.Hex2Bytes("02"), common.Hex2Bytes("03"), } - trie := NewEmpty(NewDatabase(rawdb.NewMemoryDatabase())) + trie := NewEmpty(NewDatabase(rawdb.NewMemoryDatabase(), nil)) for i, key := range keys { trie.MustUpdate(key, vals[i]) } root := trie.Hash() proof := memorydb.New() start := common.Hex2Bytes("0000000000000000000000000000000000000000000000000000000000000000") - end := common.Hex2Bytes("ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff") if err := trie.Prove(start, proof); err != nil { t.Fatalf("failed to prove start: %v", err) } - if err := trie.Prove(end, proof); err != nil { + if err := trie.Prove(keys[len(keys)-1], proof); err != nil { t.Fatalf("failed to prove end: %v", err) }   - more, err := VerifyRangeProof(root, start, end, keys, vals, proof) + more, err := VerifyRangeProof(root, start, keys, vals, proof) if err != nil { t.Fatalf("failed to verify range proof: %v", err) }
diff --git ethereum/go-ethereum/trie/secure_trie_test.go taikoxyz/taiko-geth/trie/secure_trie_test.go index a610ca2fd667d2441c2ca4fc644d7273d0a3f376..2087866d3855f1403db6dddf4f28aa01172e1fa8 100644 --- ethereum/go-ethereum/trie/secure_trie_test.go +++ taikoxyz/taiko-geth/trie/secure_trie_test.go @@ -31,14 +31,14 @@ "github.com/ethereum/go-ethereum/trie/trienode" )   func newEmptySecure() *StateTrie { - trie, _ := NewStateTrie(TrieID(types.EmptyRootHash), NewDatabase(rawdb.NewMemoryDatabase())) + trie, _ := NewStateTrie(TrieID(types.EmptyRootHash), NewDatabase(rawdb.NewMemoryDatabase(), nil)) return trie }   // makeTestStateTrie creates a large enough secure trie for testing. func makeTestStateTrie() (*Database, *StateTrie, map[string][]byte) { // Create an empty trie - triedb := NewDatabase(rawdb.NewMemoryDatabase()) + triedb := NewDatabase(rawdb.NewMemoryDatabase(), nil) trie, _ := NewStateTrie(TrieID(types.EmptyRootHash), triedb)   // Fill it with some arbitrary data
diff --git ethereum/go-ethereum/trie/stacktrie.go taikoxyz/taiko-geth/trie/stacktrie.go index ee1ce282918d6dd24ff2306a35ae1e9c678bda3d..35208e1cb3453c4e2cf60b23d16c680a8884ab74 100644 --- ethereum/go-ethereum/trie/stacktrie.go +++ taikoxyz/taiko-geth/trie/stacktrie.go @@ -17,11 +17,7 @@ package trie   import ( - "bufio" - "bytes" - "encoding/gob" "errors" - "io" "sync"   "github.com/ethereum/go-ethereum/common" @@ -29,171 +25,87 @@ "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/log" )   -var ErrCommitDisabled = errors.New("no database for committing") - -var stPool = sync.Pool{ - New: func() interface{} { - return NewStackTrie(nil) - }, -} +var ( + ErrCommitDisabled = errors.New("no database for committing") + stPool = sync.Pool{New: func() any { return new(stNode) }} + _ = types.TrieHasher((*StackTrie)(nil)) +)   // NodeWriteFunc is used to provide all information of a dirty node for committing // so that callers can flush nodes into database with desired scheme. -type NodeWriteFunc = func(owner common.Hash, path []byte, hash common.Hash, blob []byte) - -func stackTrieFromPool(writeFn NodeWriteFunc, owner common.Hash) *StackTrie { - st := stPool.Get().(*StackTrie) - st.owner = owner - st.writeFn = writeFn - return st -} - -func returnToPool(st *StackTrie) { - st.Reset() - stPool.Put(st) -} +type NodeWriteFunc = func(path []byte, hash common.Hash, blob []byte)   // StackTrie is a trie implementation that expects keys to be inserted // in order. Once it determines that a subtree will no longer be inserted // into, it will hash it and free up the memory it uses. type StackTrie struct { - owner common.Hash // the owner of the trie - nodeType uint8 // node type (as in branch, ext, leaf) - val []byte // value contained by this node if it's a leaf - key []byte // key chunk covered by this (leaf|ext) node - children [16]*StackTrie // list of children (for branch and exts) - writeFn NodeWriteFunc // function for committing nodes, can be nil + writeFn NodeWriteFunc // function for committing nodes, can be nil + root *stNode + h *hasher }   // NewStackTrie allocates and initializes an empty trie. func NewStackTrie(writeFn NodeWriteFunc) *StackTrie { return &StackTrie{ - nodeType: emptyNode, - writeFn: writeFn, + writeFn: writeFn, + root: stPool.Get().(*stNode), + h: newHasher(false), } }   -// NewStackTrieWithOwner allocates and initializes an empty trie, but with -// the additional owner field. -func NewStackTrieWithOwner(writeFn NodeWriteFunc, owner common.Hash) *StackTrie { - return &StackTrie{ - owner: owner, - nodeType: emptyNode, - writeFn: writeFn, +// Update inserts a (key, value) pair into the stack trie. +func (t *StackTrie) Update(key, value []byte) error { + k := keybytesToHex(key) + if len(value) == 0 { + panic("deletion not supported") } + t.insert(t.root, k[:len(k)-1], value, nil) + return nil }   -// NewFromBinary initialises a serialized stacktrie with the given db. -func NewFromBinary(data []byte, writeFn NodeWriteFunc) (*StackTrie, error) { - var st StackTrie - if err := st.UnmarshalBinary(data); err != nil { - return nil, err - } - // If a database is used, we need to recursively add it to every child - if writeFn != nil { - st.setWriter(writeFn) +// MustUpdate is a wrapper of Update and will omit any encountered error but +// just print out an error message. +func (t *StackTrie) MustUpdate(key, value []byte) { + if err := t.Update(key, value); err != nil { + log.Error("Unhandled trie error in StackTrie.Update", "err", err) } - return &st, nil }   -// MarshalBinary implements encoding.BinaryMarshaler -func (st *StackTrie) MarshalBinary() (data []byte, err error) { - var ( - b bytes.Buffer - w = bufio.NewWriter(&b) - ) - if err := gob.NewEncoder(w).Encode(struct { - Owner common.Hash - NodeType uint8 - Val []byte - Key []byte - }{ - st.owner, - st.nodeType, - st.val, - st.key, - }); err != nil { - return nil, err - } - for _, child := range st.children { - if child == nil { - w.WriteByte(0) - continue - } - w.WriteByte(1) - if childData, err := child.MarshalBinary(); err != nil { - return nil, err - } else { - w.Write(childData) - } - } - w.Flush() - return b.Bytes(), nil +func (t *StackTrie) Reset() { + t.writeFn = nil + t.root = stPool.Get().(*stNode) }   -// UnmarshalBinary implements encoding.BinaryUnmarshaler -func (st *StackTrie) UnmarshalBinary(data []byte) error { - r := bytes.NewReader(data) - return st.unmarshalBinary(r) +// stNode represents a node within a StackTrie +type stNode struct { + typ uint8 // node type (as in branch, ext, leaf) + key []byte // key chunk covered by this (leaf|ext) node + val []byte // value contained by this node if it's a leaf + children [16]*stNode // list of children (for branch and exts) }   -func (st *StackTrie) unmarshalBinary(r io.Reader) error { - var dec struct { - Owner common.Hash - NodeType uint8 - Val []byte - Key []byte - } - if err := gob.NewDecoder(r).Decode(&dec); err != nil { - return err - } - st.owner = dec.Owner - st.nodeType = dec.NodeType - st.val = dec.Val - st.key = dec.Key - - var hasChild = make([]byte, 1) - for i := range st.children { - if _, err := r.Read(hasChild); err != nil { - return err - } else if hasChild[0] == 0 { - continue - } - var child StackTrie - if err := child.unmarshalBinary(r); err != nil { - return err - } - st.children[i] = &child - } - return nil -} - -func (st *StackTrie) setWriter(writeFn NodeWriteFunc) { - st.writeFn = writeFn - for _, child := range st.children { - if child != nil { - child.setWriter(writeFn) - } - } -} - -func newLeaf(owner common.Hash, key, val []byte, writeFn NodeWriteFunc) *StackTrie { - st := stackTrieFromPool(writeFn, owner) - st.nodeType = leafNode +// newLeaf constructs a leaf node with provided node key and value. The key +// will be deep-copied in the function and safe to modify afterwards, but +// value is not. +func newLeaf(key, val []byte) *stNode { + st := stPool.Get().(*stNode) + st.typ = leafNode st.key = append(st.key, key...) st.val = val return st }   -func newExt(owner common.Hash, key []byte, child *StackTrie, writeFn NodeWriteFunc) *StackTrie { - st := stackTrieFromPool(writeFn, owner) - st.nodeType = extNode +// newExt constructs an extension node with provided node key and child. The +// key will be deep-copied in the function and safe to modify afterwards. +func newExt(key []byte, child *stNode) *stNode { + st := stPool.Get().(*stNode) + st.typ = extNode st.key = append(st.key, key...) st.children[0] = child return st }   -// List all values that StackTrie#nodeType can hold +// List all values that stNode#nodeType can hold const ( emptyNode = iota branchNode @@ -202,59 +114,40 @@ leafNode hashedNode )   -// Update inserts a (key, value) pair into the stack trie. -func (st *StackTrie) Update(key, value []byte) error { - k := keybytesToHex(key) - if len(value) == 0 { - panic("deletion not supported") - } - st.insert(k[:len(k)-1], value, nil) - return nil -} - -// MustUpdate is a wrapper of Update and will omit any encountered error but -// just print out an error message. -func (st *StackTrie) MustUpdate(key, value []byte) { - if err := st.Update(key, value); err != nil { - log.Error("Unhandled trie error in StackTrie.Update", "err", err) - } -} - -func (st *StackTrie) Reset() { - st.owner = common.Hash{} - st.writeFn = nil - st.key = st.key[:0] - st.val = nil - for i := range st.children { - st.children[i] = nil +func (n *stNode) reset() *stNode { + n.key = n.key[:0] + n.val = nil + for i := range n.children { + n.children[i] = nil } - st.nodeType = emptyNode + n.typ = emptyNode + return n }   // Helper function that, given a full key, determines the index // at which the chunk pointed by st.keyOffset is different from // the same chunk in the full key. -func (st *StackTrie) getDiffIndex(key []byte) int { - for idx, nibble := range st.key { +func (n *stNode) getDiffIndex(key []byte) int { + for idx, nibble := range n.key { if nibble != key[idx] { return idx } } - return len(st.key) + return len(n.key) }   // Helper function to that inserts a (key, value) pair into // the trie. -func (st *StackTrie) insert(key, value []byte, prefix []byte) { - switch st.nodeType { +func (t *StackTrie) insert(st *stNode, key, value []byte, prefix []byte) { + switch st.typ { case branchNode: /* Branch */ idx := int(key[0])   // Unresolve elder siblings for i := idx - 1; i >= 0; i-- { if st.children[i] != nil { - if st.children[i].nodeType != hashedNode { - st.children[i].hash(append(prefix, byte(i))) + if st.children[i].typ != hashedNode { + t.hash(st.children[i], append(prefix, byte(i))) } break } @@ -262,9 +155,9 @@ }   // Add new child if st.children[idx] == nil { - st.children[idx] = newLeaf(st.owner, key[1:], value, st.writeFn) + st.children[idx] = newLeaf(key[1:], value) } else { - st.children[idx].insert(key[1:], value, append(prefix, key[0])) + t.insert(st.children[idx], key[1:], value, append(prefix, key[0])) }   case extNode: /* Ext */ @@ -279,46 +172,46 @@ // for each of the differentiated subtrees. if diffidx == len(st.key) { // Ext key and key segment are identical, recurse into // the child node. - st.children[0].insert(key[diffidx:], value, append(prefix, key[:diffidx]...)) + t.insert(st.children[0], key[diffidx:], value, append(prefix, key[:diffidx]...)) return } // Save the original part. Depending if the break is // at the extension's last byte or not, create an // intermediate extension or use the extension's child // node directly. - var n *StackTrie + var n *stNode if diffidx < len(st.key)-1 { // Break on the non-last byte, insert an intermediate // extension. The path prefix of the newly-inserted // extension should also contain the different byte. - n = newExt(st.owner, st.key[diffidx+1:], st.children[0], st.writeFn) - n.hash(append(prefix, st.key[:diffidx+1]...)) + n = newExt(st.key[diffidx+1:], st.children[0]) + t.hash(n, append(prefix, st.key[:diffidx+1]...)) } else { // Break on the last byte, no need to insert // an extension node: reuse the current node. // The path prefix of the original part should // still be same. n = st.children[0] - n.hash(append(prefix, st.key...)) + t.hash(n, append(prefix, st.key...)) } - var p *StackTrie + var p *stNode if diffidx == 0 { // the break is on the first byte, so // the current node is converted into // a branch node. st.children[0] = nil p = st - st.nodeType = branchNode + st.typ = branchNode } else { // the common prefix is at least one byte // long, insert a new intermediate branch // node. - st.children[0] = stackTrieFromPool(st.writeFn, st.owner) - st.children[0].nodeType = branchNode + st.children[0] = stPool.Get().(*stNode) + st.children[0].typ = branchNode p = st.children[0] } // Create a leaf for the inserted part - o := newLeaf(st.owner, key[diffidx+1:], value, st.writeFn) + o := newLeaf(key[diffidx+1:], value)   // Insert both child leaves where they belong: origIdx := st.key[diffidx] @@ -344,18 +237,18 @@ // Check if the split occurs at the first nibble of the // chunk. In that case, no prefix extnode is necessary. // Otherwise, create that - var p *StackTrie + var p *stNode if diffidx == 0 { // Convert current leaf into a branch - st.nodeType = branchNode + st.typ = branchNode p = st st.children[0] = nil } else { // Convert current node into an ext, // and insert a child branch node. - st.nodeType = extNode - st.children[0] = NewStackTrieWithOwner(st.writeFn, st.owner) - st.children[0].nodeType = branchNode + st.typ = extNode + st.children[0] = stPool.Get().(*stNode) + st.children[0].typ = branchNode p = st.children[0] }   @@ -363,11 +256,11 @@ // Create the two child leaves: one containing the original // value and another containing the new value. The child leaf // is hashed directly in order to free up some memory. origIdx := st.key[diffidx] - p.children[origIdx] = newLeaf(st.owner, st.key[diffidx+1:], st.val, st.writeFn) - p.children[origIdx].hash(append(prefix, st.key[:diffidx+1]...)) + p.children[origIdx] = newLeaf(st.key[diffidx+1:], st.val) + t.hash(p.children[origIdx], append(prefix, st.key[:diffidx+1]...))   newIdx := key[diffidx] - p.children[newIdx] = newLeaf(st.owner, key[diffidx+1:], value, st.writeFn) + p.children[newIdx] = newLeaf(key[diffidx+1:], value)   // Finally, cut off the key part that has been passed // over to the children. @@ -375,7 +268,7 @@ st.key = st.key[:diffidx] st.val = nil   case emptyNode: /* Empty */ - st.nodeType = leafNode + st.typ = leafNode st.key = key st.val = value   @@ -398,25 +291,18 @@ // - Then the <32 byte rlp-encoded value will be accessible in 'st.val'. // - And the 'st.type' will be 'hashedNode' AGAIN // // This method also sets 'st.type' to hashedNode, and clears 'st.key'. -func (st *StackTrie) hash(path []byte) { - h := newHasher(false) - defer returnHasherToPool(h) - - st.hashRec(h, path) -} - -func (st *StackTrie) hashRec(hasher *hasher, path []byte) { +func (t *StackTrie) hash(st *stNode, path []byte) { // The switch below sets this to the RLP-encoding of this node. var encodedNode []byte   - switch st.nodeType { + switch st.typ { case hashedNode: return   case emptyNode: st.val = types.EmptyRootHash.Bytes() st.key = st.key[:0] - st.nodeType = hashedNode + st.typ = hashedNode return   case branchNode: @@ -426,50 +312,46 @@ if child == nil { nodes.Children[i] = nilValueNode continue } - child.hashRec(hasher, append(path, byte(i))) + t.hash(child, append(path, byte(i))) + if len(child.val) < 32 { nodes.Children[i] = rawNode(child.val) } else { nodes.Children[i] = hashNode(child.val) } - - // Release child back to pool. st.children[i] = nil - returnToPool(child) + stPool.Put(child.reset()) // Release child back to pool. } - - nodes.encode(hasher.encbuf) - encodedNode = hasher.encodedBytes() + nodes.encode(t.h.encbuf) + encodedNode = t.h.encodedBytes()   case extNode: - st.children[0].hashRec(hasher, append(path, st.key...)) + t.hash(st.children[0], append(path, st.key...))   - n := shortNode{Key: hexToCompact(st.key)} + n := shortNode{Key: hexToCompactInPlace(st.key)} if len(st.children[0].val) < 32 { n.Val = rawNode(st.children[0].val) } else { n.Val = hashNode(st.children[0].val) } - - n.encode(hasher.encbuf) - encodedNode = hasher.encodedBytes() + n.encode(t.h.encbuf) + encodedNode = t.h.encodedBytes()   - // Release child back to pool. - returnToPool(st.children[0]) + stPool.Put(st.children[0].reset()) // Release child back to pool. st.children[0] = nil   case leafNode: st.key = append(st.key, byte(16)) - n := shortNode{Key: hexToCompact(st.key), Val: valueNode(st.val)} + n := shortNode{Key: hexToCompactInPlace(st.key), Val: valueNode(st.val)}   - n.encode(hasher.encbuf) - encodedNode = hasher.encodedBytes() + n.encode(t.h.encbuf) + encodedNode = t.h.encodedBytes()   default: panic("invalid node type") }   - st.nodeType = hashedNode + st.typ = hashedNode st.key = st.key[:0] if len(encodedNode) < 32 { st.val = common.CopyBytes(encodedNode) @@ -478,18 +360,16 @@ }   // Write the hash to the 'val'. We allocate a new val here to not mutate // input values - st.val = hasher.hashData(encodedNode) - if st.writeFn != nil { - st.writeFn(st.owner, path, common.BytesToHash(st.val), encodedNode) + st.val = t.h.hashData(encodedNode) + if t.writeFn != nil { + t.writeFn(path, common.BytesToHash(st.val), encodedNode) } }   // Hash returns the hash of the current node. -func (st *StackTrie) Hash() (h common.Hash) { - hasher := newHasher(false) - defer returnHasherToPool(hasher) - - st.hashRec(hasher, nil) +func (t *StackTrie) Hash() (h common.Hash) { + st := t.root + t.hash(st, nil) if len(st.val) == 32 { copy(h[:], st.val) return h @@ -497,9 +377,9 @@ } // If the node's RLP isn't 32 bytes long, the node will not // be hashed, and instead contain the rlp-encoding of the // node. For the top level node, we need to force the hashing. - hasher.sha.Reset() - hasher.sha.Write(st.val) - hasher.sha.Read(h[:]) + t.h.sha.Reset() + t.h.sha.Write(st.val) + t.h.sha.Read(h[:]) return h }   @@ -510,14 +390,12 @@ // here is to commit the root node. // // The associated database is expected, otherwise the whole commit // functionality should be disabled. -func (st *StackTrie) Commit() (h common.Hash, err error) { - if st.writeFn == nil { +func (t *StackTrie) Commit() (h common.Hash, err error) { + if t.writeFn == nil { return common.Hash{}, ErrCommitDisabled } - hasher := newHasher(false) - defer returnHasherToPool(hasher) - - st.hashRec(hasher, nil) + st := t.root + t.hash(st, nil) if len(st.val) == 32 { copy(h[:], st.val) return h, nil @@ -525,10 +403,10 @@ } // If the node's RLP isn't 32 bytes long, the node will not // be hashed (and committed), and instead contain the rlp-encoding of the // node. For the top level node, we need to force the hashing+commit. - hasher.sha.Reset() - hasher.sha.Write(st.val) - hasher.sha.Read(h[:]) + t.h.sha.Reset() + t.h.sha.Write(st.val) + t.h.sha.Read(h[:])   - st.writeFn(st.owner, nil, h, st.val) + t.writeFn(nil, h, st.val) return h, nil }
diff --git ethereum/go-ethereum/trie/stacktrie_test.go taikoxyz/taiko-geth/trie/stacktrie_test.go index ea3eef78820dd83c0ac39660e7214eda45d61799..0e52781c62ec789a0545f6c81a08fd16cc3100e0 100644 --- ethereum/go-ethereum/trie/stacktrie_test.go +++ taikoxyz/taiko-geth/trie/stacktrie_test.go @@ -165,13 +165,44 @@ {"123d", "x___________________________1", "8f09663deb02f08958136410dc48565e077f76bb6c9d8c84d35fc8913a657d31"}, {"123e", "x___________________________2", "0d230561e398c579e09a9f7b69ceaf7d3970f5a436fdb28b68b7a37c5bdd6b80"}, {"13aa", "x___________________________3", "ff0dc70ce2e5db90ee42a4c2ad12139596b890e90eb4e16526ab38fa465b35cf"}, }, + { // branch node with short values + {"01", "a", "b48605025f5f4b129d40a420e721aa7d504487f015fce85b96e52126365ef7dc"}, + {"80", "b", "2dc6b680daf74db067cb7aeaad73265ded93d96fce190fcbf64f498d475672ab"}, + {"ee", "c", "017dc705a54ac5328dd263fa1bae68d655310fb3e3f7b7bc57e9a43ddf99c4bf"}, + {"ff", "d", "bd5a3584d271d459bd4eb95247b2fc88656b3671b60c1125ffe7bc0b689470d0"}, + }, + { // ext node with short branch node, then becoming long + {"a0", "a", "a83e028cb1e4365935661a9fd36a5c65c30b9ab416eaa877424146ca2a69d088"}, + {"a1", "b", "f586a4639b07b01798ca65e05c253b75d51135ebfbf6f8d6e87c0435089e65f0"}, + {"a2", "c", "63e297c295c008e09a8d531e18d57f270b6bc403e23179b915429db948cd62e3"}, + {"a3", "d", "94a7b721535578e9381f1f4e4b6ec29f8bdc5f0458a30320684c562f5d47b4b5"}, + {"a4", "e", "4b7e66d1c81965cdbe8fab8295ef56bc57fefdc5733d4782d2f8baf630f083c6"}, + {"a5", "f", "2997e7b502198ce1783b5277faacf52b25844fb55a99b63e88bdbbafac573106"}, + {"a6", "g", "bee629dd27a40772b2e1a67ec6db270d26acdf8d3b674dfae27866ad6ae1f48b"}, + }, + { // branch node with short values, then long ones + {"a001", "v1", "b9cc982d995392b51e6787f1915f0b88efd4ad8b30f138da0a3e2242f2323e35"}, + {"b002", "v2", "a7b474bc77ef5097096fa0ee6298fdae8928c0bc3724e7311cd0fa9ed1942fc7"}, + {"c003", "v___________________________3", "dceb5bb7c92b0e348df988a8d9fc36b101397e38ebd405df55ba6ee5f14a264a"}, + {"d004", "v___________________________4", "36e60ecb86b9626165e1c6543c42ecbe4d83bca58e8e1124746961511fce362a"}, + }, + { // ext node to branch node with short values, then long ones + {"8002", "v1", "3258fcb3e9e7d7234ecd3b8d4743999e4ab3a21592565e0a5ca64c141e8620d9"}, + {"8004", "v2", "b6cb95b7024a83c17624a3c9bed09b4b5e8ed426f49f54b8ad13c39028b1e75a"}, + {"8008", "v___________________________3", "c769d82963abe6f0900bf69754738eeb2f84559777cfa87a44f54e1aab417871"}, + {"800d", "v___________________________4", "1cad1fdaab1a6fa95d7b780fd680030e423eb76669971368ba04797a8d9cdfc9"}, + }, + { // ext node with a child of size 31 (Y) and branch node with a child of size 31 (X) + {"000001", "ZZZZZZZZZ", "cef154b87c03c563408520ff9b26923c360cbc3ddb590c079bedeeb25a8c9c77"}, + {"000002", "Y", "2130735e600f612f6e657a32bd7be64ddcaec6512c5694844b19de713922895d"}, + {"000003", "XXXXXXXXXXXXXXXXXXXXXXXXXXXX", "962c0fffdeef7612a4f7bff1950d67e3e81c878e48b9ae45b3b374253b050bd8"}, + }, } - st := NewStackTrie(nil) for i, test := range tests { // The StackTrie does not allow Insert(), Hash(), Insert(), ... // so we will create new trie for every sequence length of inserts. for l := 1; l <= len(test); l++ { - st.Reset() + st := NewStackTrie(nil) for j := 0; j < l; j++ { kv := &test[j] if err := st.Update(common.FromHex(kv.K), []byte(kv.V)); err != nil { @@ -188,7 +219,7 @@ }   func TestSizeBug(t *testing.T) { st := NewStackTrie(nil) - nt := NewEmpty(NewDatabase(rawdb.NewMemoryDatabase())) + nt := NewEmpty(NewDatabase(rawdb.NewMemoryDatabase(), nil))   leaf := common.FromHex("290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e563") value := common.FromHex("94cf40d0d2b44f2b66e07cace1372ca42b73cf21a3") @@ -203,7 +234,7 @@ }   func TestEmptyBug(t *testing.T) { st := NewStackTrie(nil) - nt := NewEmpty(NewDatabase(rawdb.NewMemoryDatabase())) + nt := NewEmpty(NewDatabase(rawdb.NewMemoryDatabase(), nil))   //leaf := common.FromHex("290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e563") //value := common.FromHex("94cf40d0d2b44f2b66e07cace1372ca42b73cf21a3") @@ -229,7 +260,7 @@ }   func TestValLength56(t *testing.T) { st := NewStackTrie(nil) - nt := NewEmpty(NewDatabase(rawdb.NewMemoryDatabase())) + nt := NewEmpty(NewDatabase(rawdb.NewMemoryDatabase(), nil))   //leaf := common.FromHex("290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e563") //value := common.FromHex("94cf40d0d2b44f2b66e07cace1372ca42b73cf21a3") @@ -254,7 +285,7 @@ // TestUpdateSmallNodes tests a case where the leaves are small (both key and value), // which causes a lot of node-within-node. This case was found via fuzzing. func TestUpdateSmallNodes(t *testing.T) { st := NewStackTrie(nil) - nt := NewEmpty(NewDatabase(rawdb.NewMemoryDatabase())) + nt := NewEmpty(NewDatabase(rawdb.NewMemoryDatabase(), nil)) kvs := []struct { K string V string @@ -282,7 +313,7 @@ // This case was found via fuzzing. func TestUpdateVariableKeys(t *testing.T) { t.SkipNow() st := NewStackTrie(nil) - nt := NewEmpty(NewDatabase(rawdb.NewMemoryDatabase())) + nt := NewEmpty(NewDatabase(rawdb.NewMemoryDatabase(), nil)) kvs := []struct { K string V string @@ -345,48 +376,3 @@ t.Fatalf("item %d, have %#x want %#x", i, have, want) } } } - -// TestStacktrieSerialization tests that the stacktrie works well if we -// serialize/unserialize it a lot -func TestStacktrieSerialization(t *testing.T) { - var ( - st = NewStackTrie(nil) - nt = NewEmpty(NewDatabase(rawdb.NewMemoryDatabase())) - keyB = big.NewInt(1) - keyDelta = big.NewInt(1) - vals [][]byte - keys [][]byte - ) - getValue := func(i int) []byte { - if i%2 == 0 { // large - return crypto.Keccak256(big.NewInt(int64(i)).Bytes()) - } else { //small - return big.NewInt(int64(i)).Bytes() - } - } - for i := 0; i < 10; i++ { - vals = append(vals, getValue(i)) - keys = append(keys, common.BigToHash(keyB).Bytes()) - keyB = keyB.Add(keyB, keyDelta) - keyDelta.Add(keyDelta, common.Big1) - } - for i, k := range keys { - nt.Update(k, common.CopyBytes(vals[i])) - } - - for i, k := range keys { - blob, err := st.MarshalBinary() - if err != nil { - t.Fatal(err) - } - newSt, err := NewFromBinary(blob, nil) - if err != nil { - t.Fatal(err) - } - st = newSt - st.Update(k, common.CopyBytes(vals[i])) - } - if have, want := st.Hash(), nt.Hash(); have != want { - t.Fatalf("have %#x want %#x", have, want) - } -}
diff --git ethereum/go-ethereum/trie/sync.go taikoxyz/taiko-geth/trie/sync.go index 4f55845991796307b7b81562fa0d50f57b39c828..6939aed76d4b941695207db20272ee99607aebb0 100644 --- ethereum/go-ethereum/trie/sync.go +++ taikoxyz/taiko-geth/trie/sync.go @@ -27,6 +27,7 @@ "github.com/ethereum/go-ethereum/core/rawdb" "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/ethdb" "github.com/ethereum/go-ethereum/log" + "github.com/ethereum/go-ethereum/metrics" )   // ErrNotRequested is returned by the trie sync when it's requested to process a @@ -41,6 +42,16 @@ // maxFetchesPerDepth is the maximum number of pending trie nodes per depth. The // role of this value is to limit the number of trie nodes that get expanded in // memory if the node was configured with a significant number of peers. const maxFetchesPerDepth = 16384 + +var ( + // deletionGauge is the metric to track how many trie node deletions + // are performed in total during the sync process. + deletionGauge = metrics.NewRegisteredGauge("trie/sync/delete", nil) + + // lookupGauge is the metric to track how many trie node lookups are + // performed to determine if node needs to be deleted. + lookupGauge = metrics.NewRegisteredGauge("trie/sync/lookup", nil) +)   // SyncPath is a path tuple identifying a particular trie node either in a single // trie (account) or a layered trie (account -> storage). @@ -93,9 +104,10 @@ type LeafCallback func(keys [][]byte, path []byte, leaf []byte, parent common.Hash, parentPath []byte) error   // nodeRequest represents a scheduled or already in-flight trie node retrieval request. type nodeRequest struct { - hash common.Hash // Hash of the trie node to retrieve - path []byte // Merkle path leading to this node for prioritization - data []byte // Data content of the node, cached until all subtrees complete + hash common.Hash // Hash of the trie node to retrieve + path []byte // Merkle path leading to this node for prioritization + data []byte // Data content of the node, cached until all subtrees complete + deletes [][]byte // List of internal path segments for trie nodes to delete   parent *nodeRequest // Parent state node referencing this entry deps int // Number of dependencies before allowed to commit this node @@ -125,18 +137,20 @@ // syncMemBatch is an in-memory buffer of successfully downloaded but not yet // persisted data items. type syncMemBatch struct { - nodes map[string][]byte // In-memory membatch of recently completed nodes - hashes map[string]common.Hash // Hashes of recently completed nodes - codes map[common.Hash][]byte // In-memory membatch of recently completed codes - size uint64 // Estimated batch-size of in-memory data. + nodes map[string][]byte // In-memory membatch of recently completed nodes + hashes map[string]common.Hash // Hashes of recently completed nodes + deletes map[string]struct{} // List of paths for trie node to delete + codes map[common.Hash][]byte // In-memory membatch of recently completed codes + size uint64 // Estimated batch-size of in-memory data. }   // newSyncMemBatch allocates a new memory-buffer for not-yet persisted trie nodes. func newSyncMemBatch() *syncMemBatch { return &syncMemBatch{ - nodes: make(map[string][]byte), - hashes: make(map[string]common.Hash), - codes: make(map[common.Hash][]byte), + nodes: make(map[string][]byte), + hashes: make(map[string]common.Hash), + deletes: make(map[string]struct{}), + codes: make(map[common.Hash][]byte), } }   @@ -288,7 +302,7 @@ return nodePaths, nodeHashes, codeHashes }   // ProcessCode injects the received data for requested item. Note it can -// happpen that the single response commits two pending requests(e.g. +// happen that the single response commits two pending requests(e.g. // there are two requests one for code and one for node but the hash // is same). In this case the second response for the same hash will // be treated as "non-requested" item or "already-processed" item but @@ -347,16 +361,23 @@ // Commit flushes the data stored in the internal membatch out to persistent // storage, returning any occurred error. func (s *Sync) Commit(dbw ethdb.Batch) error { - // Dump the membatch into a database dbw + // Flush the pending node writes into database batch. for path, value := range s.membatch.nodes { owner, inner := ResolvePath([]byte(path)) rawdb.WriteTrieNode(dbw, owner, inner, s.membatch.hashes[path], value, s.scheme) } + // Flush the pending node deletes into the database batch. + // Please note that each written and deleted node has a + // unique path, ensuring no duplication occurs. + for path := range s.membatch.deletes { + owner, inner := ResolvePath([]byte(path)) + rawdb.DeleteTrieNode(dbw, owner, inner, common.Hash{} /* unused */, s.scheme) + } + // Flush the pending code writes into database batch. for hash, value := range s.membatch.codes { rawdb.WriteCode(dbw, hash, value) } - // Drop the membatch data and return - s.membatch = newSyncMemBatch() + s.membatch = newSyncMemBatch() // reset the batch return nil }   @@ -370,7 +391,7 @@ func (s *Sync) Pending() int { return len(s.nodeReqs) + len(s.codeReqs) }   -// schedule inserts a new state retrieval request into the fetch queue. If there +// scheduleNodeRequest inserts a new state retrieval request into the fetch queue. If there // is already a pending request for this node, the new request will be discarded // and only a parent reference added to the old one. func (s *Sync) scheduleNodeRequest(req *nodeRequest) { @@ -385,7 +406,7 @@ } s.queue.Push(string(req.path), prio) }   -// schedule inserts a new state retrieval request into the fetch queue. If there +// scheduleCodeRequest inserts a new state retrieval request into the fetch queue. If there // is already a pending request for this node, the new request will be discarded // and only a parent reference added to the old one. func (s *Sync) scheduleCodeRequest(req *codeRequest) { @@ -425,6 +446,39 @@ children = []childNode{{ node: node.Val, path: append(append([]byte(nil), req.path...), key...), }} + // Mark all internal nodes between shortNode and its **in disk** + // child as invalid. This is essential in the case of path mode + // scheme; otherwise, state healing might overwrite existing child + // nodes silently while leaving a dangling parent node within the + // range of this internal path on disk. This would break the + // guarantee for state healing. + // + // While it's possible for this shortNode to overwrite a previously + // existing full node, the other branches of the fullNode can be + // retained as they remain untouched and complete. + // + // This step is only necessary for path mode, as there is no deletion + // in hash mode at all. + if _, ok := node.Val.(hashNode); ok && s.scheme == rawdb.PathScheme { + owner, inner := ResolvePath(req.path) + for i := 1; i < len(key); i++ { + // While checking for a non-existent item in Pebble can be less efficient + // without a bloom filter, the relatively low frequency of lookups makes + // the performance impact negligible. + var exists bool + if owner == (common.Hash{}) { + exists = rawdb.ExistsAccountTrieNode(s.database, append(inner, key[:i]...)) + } else { + exists = rawdb.ExistsStorageTrieNode(s.database, owner, append(inner, key[:i]...)) + } + if exists { + req.deletes = append(req.deletes, key[:i]) + deletionGauge.Inc(1) + log.Debug("Detected dangling node", "owner", owner, "path", append(inner, key[:i]...)) + } + } + lookupGauge.Inc(int64(len(key) - 1)) + } case *fullNode: for i := 0; i < 17; i++ { if node.Children[i] != nil { @@ -502,17 +556,26 @@ } return requests, nil }   -// commit finalizes a retrieval request and stores it into the membatch. If any +// commitNodeRequest finalizes a retrieval request and stores it into the membatch. If any // of the referencing parent requests complete due to this commit, they are also // committed themselves. func (s *Sync) commitNodeRequest(req *nodeRequest) error { // Write the node content to the membatch s.membatch.nodes[string(req.path)] = req.data s.membatch.hashes[string(req.path)] = req.hash + // The size tracking refers to the db-batch, not the in-memory data. - // Therefore, we ignore the req.path, and account only for the hash+data - // which eventually is written to db. - s.membatch.size += common.HashLength + uint64(len(req.data)) + if s.scheme == rawdb.PathScheme { + s.membatch.size += uint64(len(req.path) + len(req.data)) + } else { + s.membatch.size += common.HashLength + uint64(len(req.data)) + } + // Delete the internal nodes which are marked as invalid + for _, segment := range req.deletes { + path := append(req.path, segment...) + s.membatch.deletes[string(path)] = struct{}{} + s.membatch.size += uint64(len(path)) + } delete(s.nodeReqs, string(req.path)) s.fetches[len(req.path)]--   @@ -528,7 +591,7 @@ } return nil }   -// commit finalizes a retrieval request and stores it into the membatch. If any +// commitCodeRequest finalizes a retrieval request and stores it into the membatch. If any // of the referencing parent requests complete due to this commit, they are also // committed themselves. func (s *Sync) commitCodeRequest(req *codeRequest) error {
diff --git ethereum/go-ethereum/trie/sync_test.go taikoxyz/taiko-geth/trie/sync_test.go index b6fe8d84a6df241ab5ba85f4b04802a006aa46eb..3b7986ef67922c185022b2461d9d73c380fe34ab 100644 --- ethereum/go-ethereum/trie/sync_test.go +++ taikoxyz/taiko-geth/trie/sync_test.go @@ -70,31 +70,53 @@ }   // checkTrieContents cross references a reconstructed trie with an expected data // content map. -func checkTrieContents(t *testing.T, db ethdb.Database, scheme string, root []byte, content map[string][]byte) { +func checkTrieContents(t *testing.T, db ethdb.Database, scheme string, root []byte, content map[string][]byte, rawTrie bool) { // Check root availability and trie contents ndb := newTestDatabase(db, scheme) - trie, err := NewStateTrie(TrieID(common.BytesToHash(root)), ndb) - if err != nil { - t.Fatalf("failed to create trie at %x: %v", root, err) + if err := checkTrieConsistency(db, scheme, common.BytesToHash(root), rawTrie); err != nil { + t.Fatalf("inconsistent trie at %x: %v", root, err) } - if err := checkTrieConsistency(db, scheme, common.BytesToHash(root)); err != nil { - t.Fatalf("inconsistent trie at %x: %v", root, err) + type reader interface { + MustGet(key []byte) []byte + } + var r reader + if rawTrie { + trie, err := New(TrieID(common.BytesToHash(root)), ndb) + if err != nil { + t.Fatalf("failed to create trie at %x: %v", root, err) + } + r = trie + } else { + trie, err := NewStateTrie(TrieID(common.BytesToHash(root)), ndb) + if err != nil { + t.Fatalf("failed to create trie at %x: %v", root, err) + } + r = trie } for key, val := range content { - if have := trie.MustGet([]byte(key)); !bytes.Equal(have, val) { + if have := r.MustGet([]byte(key)); !bytes.Equal(have, val) { t.Errorf("entry %x: content mismatch: have %x, want %x", key, have, val) } } }   // checkTrieConsistency checks that all nodes in a trie are indeed present. -func checkTrieConsistency(db ethdb.Database, scheme string, root common.Hash) error { +func checkTrieConsistency(db ethdb.Database, scheme string, root common.Hash, rawTrie bool) error { ndb := newTestDatabase(db, scheme) - trie, err := NewStateTrie(TrieID(root), ndb) - if err != nil { - return nil // Consider a non existent state consistent + var it NodeIterator + if rawTrie { + trie, err := New(TrieID(root), ndb) + if err != nil { + return nil // Consider a non existent state consistent + } + it = trie.MustNodeIterator(nil) + } else { + trie, err := NewStateTrie(TrieID(root), ndb) + if err != nil { + return nil // Consider a non existent state consistent + } + it = trie.MustNodeIterator(nil) } - it := trie.MustNodeIterator(nil) for it.Next(true) { } return it.Error() @@ -109,8 +131,8 @@ }   // Tests that an empty trie is not scheduled for syncing. func TestEmptySync(t *testing.T) { - dbA := NewDatabase(rawdb.NewMemoryDatabase()) - dbB := NewDatabase(rawdb.NewMemoryDatabase()) + dbA := newTestDatabase(rawdb.NewMemoryDatabase(), rawdb.HashScheme) + dbB := newTestDatabase(rawdb.NewMemoryDatabase(), rawdb.HashScheme) dbC := newTestDatabase(rawdb.NewMemoryDatabase(), rawdb.PathScheme) dbD := newTestDatabase(rawdb.NewMemoryDatabase(), rawdb.PathScheme)   @@ -205,7 +227,7 @@ }) } } // Cross check that the two tries are in sync - checkTrieContents(t, diskdb, srcDb.Scheme(), srcTrie.Hash().Bytes(), srcData) + checkTrieContents(t, diskdb, srcDb.Scheme(), srcTrie.Hash().Bytes(), srcData, false) }   // Tests that the trie scheduler can correctly reconstruct the state even if only @@ -271,7 +293,7 @@ }) } } // Cross check that the two tries are in sync - checkTrieContents(t, diskdb, srcDb.Scheme(), srcTrie.Hash().Bytes(), srcData) + checkTrieContents(t, diskdb, srcDb.Scheme(), srcTrie.Hash().Bytes(), srcData, false) }   // Tests that given a root hash, a trie can sync iteratively on a single thread, @@ -341,7 +363,7 @@ } } } // Cross check that the two tries are in sync - checkTrieContents(t, diskdb, srcDb.Scheme(), srcTrie.Hash().Bytes(), srcData) + checkTrieContents(t, diskdb, srcDb.Scheme(), srcTrie.Hash().Bytes(), srcData, false) }   // Tests that the trie scheduler can correctly reconstruct the state even if only @@ -413,7 +435,7 @@ } } } // Cross check that the two tries are in sync - checkTrieContents(t, diskdb, srcDb.Scheme(), srcTrie.Hash().Bytes(), srcData) + checkTrieContents(t, diskdb, srcDb.Scheme(), srcTrie.Hash().Bytes(), srcData, false) }   // Tests that a trie sync will not request nodes multiple times, even if they @@ -484,7 +506,7 @@ }) } } // Cross check that the two tries are in sync - checkTrieContents(t, diskdb, srcDb.Scheme(), srcTrie.Hash().Bytes(), srcData) + checkTrieContents(t, diskdb, srcDb.Scheme(), srcTrie.Hash().Bytes(), srcData, false) }   // Tests that at any point in time during a sync, only complete sub-tries are in @@ -569,7 +591,7 @@ owner, inner := ResolvePath([]byte(path)) nodeHash := addedHashes[i] value := rawdb.ReadTrieNode(diskdb, owner, inner, nodeHash, scheme) rawdb.DeleteTrieNode(diskdb, owner, inner, nodeHash, scheme) - if err := checkTrieConsistency(diskdb, srcDb.Scheme(), root); err == nil { + if err := checkTrieConsistency(diskdb, srcDb.Scheme(), root, false); err == nil { t.Fatalf("trie inconsistency not caught, missing: %x", path) } rawdb.WriteTrieNode(diskdb, owner, inner, nodeHash, value, scheme) @@ -643,7 +665,7 @@ reqs = append(reqs, NewSyncPath([]byte(paths[i]))) } } // Cross check that the two tries are in sync - checkTrieContents(t, diskdb, srcDb.Scheme(), srcTrie.Hash().Bytes(), srcData) + checkTrieContents(t, diskdb, srcDb.Scheme(), srcTrie.Hash().Bytes(), srcData, false)   // Check that the trie nodes have been requested path-ordered for i := 0; i < len(reqs)-1; i++ { @@ -664,7 +686,7 @@ sched := NewSync(root, db, nil, srcDb.Scheme())   // The code requests are ignored here since there is no code // at the testing trie. - paths, nodes, _ := sched.Missing(1) + paths, nodes, _ := sched.Missing(0) var elements []trieElement for i := 0; i < len(paths); i++ { elements = append(elements, trieElement{ @@ -698,7 +720,7 @@ t.Fatalf("failed to commit data: %v", err) } batch.Write()   - paths, nodes, _ = sched.Missing(1) + paths, nodes, _ = sched.Missing(0) elements = elements[:0] for i := 0; i < len(paths); i++ { elements = append(elements, trieElement{ @@ -724,7 +746,7 @@ // Create a destination trie and sync with the scheduler diskdb := rawdb.NewMemoryDatabase() syncWith(t, srcTrie.Hash(), diskdb, srcDb) - checkTrieContents(t, diskdb, srcDb.Scheme(), srcTrie.Hash().Bytes(), srcData) + checkTrieContents(t, diskdb, srcDb.Scheme(), srcTrie.Hash().Bytes(), srcData, false)   // Push more modifications into the src trie, to see if dest trie can still // sync with it(overwrite stale states) @@ -748,7 +770,7 @@ preRoot = root srcTrie, _ = NewStateTrie(TrieID(root), srcDb)   syncWith(t, srcTrie.Hash(), diskdb, srcDb) - checkTrieContents(t, diskdb, srcDb.Scheme(), srcTrie.Hash().Bytes(), diff) + checkTrieContents(t, diskdb, srcDb.Scheme(), srcTrie.Hash().Bytes(), diff, false)   // Revert added modifications from the src trie, to see if dest trie can still // sync with it(overwrite reverted states) @@ -772,5 +794,98 @@ } srcTrie, _ = NewStateTrie(TrieID(root), srcDb)   syncWith(t, srcTrie.Hash(), diskdb, srcDb) - checkTrieContents(t, diskdb, srcDb.Scheme(), srcTrie.Hash().Bytes(), reverted) + checkTrieContents(t, diskdb, srcDb.Scheme(), srcTrie.Hash().Bytes(), reverted, false) +} + +// Tests if state syncer can correctly catch up the pivot move. +func TestPivotMove(t *testing.T) { + testPivotMove(t, rawdb.HashScheme, true) + testPivotMove(t, rawdb.HashScheme, false) + testPivotMove(t, rawdb.PathScheme, true) + testPivotMove(t, rawdb.PathScheme, false) +} + +func testPivotMove(t *testing.T, scheme string, tiny bool) { + var ( + srcDisk = rawdb.NewMemoryDatabase() + srcTrieDB = newTestDatabase(srcDisk, scheme) + srcTrie, _ = New(TrieID(types.EmptyRootHash), srcTrieDB) + + deleteFn = func(key []byte, tr *Trie, states map[string][]byte) { + tr.Delete(key) + delete(states, string(key)) + } + writeFn = func(key []byte, val []byte, tr *Trie, states map[string][]byte) { + if val == nil { + if tiny { + val = randBytes(4) + } else { + val = randBytes(32) + } + } + tr.Update(key, val) + states[string(key)] = common.CopyBytes(val) + } + copyStates = func(states map[string][]byte) map[string][]byte { + cpy := make(map[string][]byte) + for k, v := range states { + cpy[k] = v + } + return cpy + } + ) + stateA := make(map[string][]byte) + writeFn([]byte{0x01, 0x23}, nil, srcTrie, stateA) + writeFn([]byte{0x01, 0x24}, nil, srcTrie, stateA) + writeFn([]byte{0x12, 0x33}, nil, srcTrie, stateA) + writeFn([]byte{0x12, 0x34}, nil, srcTrie, stateA) + writeFn([]byte{0x02, 0x34}, nil, srcTrie, stateA) + writeFn([]byte{0x13, 0x44}, nil, srcTrie, stateA) + + rootA, nodesA, _ := srcTrie.Commit(false) + if err := srcTrieDB.Update(rootA, types.EmptyRootHash, 0, trienode.NewWithNodeSet(nodesA), nil); err != nil { + panic(err) + } + if err := srcTrieDB.Commit(rootA, false); err != nil { + panic(err) + } + // Create a destination trie and sync with the scheduler + destDisk := rawdb.NewMemoryDatabase() + syncWith(t, rootA, destDisk, srcTrieDB) + checkTrieContents(t, destDisk, scheme, srcTrie.Hash().Bytes(), stateA, true) + + // Delete element to collapse trie + stateB := copyStates(stateA) + srcTrie, _ = New(TrieID(rootA), srcTrieDB) + deleteFn([]byte{0x02, 0x34}, srcTrie, stateB) + deleteFn([]byte{0x13, 0x44}, srcTrie, stateB) + writeFn([]byte{0x01, 0x24}, nil, srcTrie, stateB) + + rootB, nodesB, _ := srcTrie.Commit(false) + if err := srcTrieDB.Update(rootB, rootA, 0, trienode.NewWithNodeSet(nodesB), nil); err != nil { + panic(err) + } + if err := srcTrieDB.Commit(rootB, false); err != nil { + panic(err) + } + syncWith(t, rootB, destDisk, srcTrieDB) + checkTrieContents(t, destDisk, scheme, srcTrie.Hash().Bytes(), stateB, true) + + // Add elements to expand trie + stateC := copyStates(stateB) + srcTrie, _ = New(TrieID(rootB), srcTrieDB) + + writeFn([]byte{0x01, 0x24}, stateA[string([]byte{0x01, 0x24})], srcTrie, stateC) + writeFn([]byte{0x02, 0x34}, nil, srcTrie, stateC) + writeFn([]byte{0x13, 0x44}, nil, srcTrie, stateC) + + rootC, nodesC, _ := srcTrie.Commit(false) + if err := srcTrieDB.Update(rootC, rootB, 0, trienode.NewWithNodeSet(nodesC), nil); err != nil { + panic(err) + } + if err := srcTrieDB.Commit(rootC, false); err != nil { + panic(err) + } + syncWith(t, rootC, destDisk, srcTrieDB) + checkTrieContents(t, destDisk, scheme, srcTrie.Hash().Bytes(), stateC, true) }
diff --git ethereum/go-ethereum/trie/tracer_test.go taikoxyz/taiko-geth/trie/tracer_test.go index 86daec6d2077c3eccbc2544b132a4234d5d42b0e..acb8c2f6bf4ff8e6d692458215b86bdbf7ed36de 100644 --- ethereum/go-ethereum/trie/tracer_test.go +++ taikoxyz/taiko-geth/trie/tracer_test.go @@ -61,7 +61,7 @@ // Tests if the trie diffs are tracked correctly. Tracer should capture // all non-leaf dirty nodes, no matter the node is embedded or not. func testTrieTracer(t *testing.T, vals []struct{ k, v string }) { - db := NewDatabase(rawdb.NewMemoryDatabase()) + db := NewDatabase(rawdb.NewMemoryDatabase(), nil) trie := NewEmpty(db)   // Determine all new nodes are tracked @@ -104,7 +104,7 @@ testTrieTracerNoop(t, standard) }   func testTrieTracerNoop(t *testing.T, vals []struct{ k, v string }) { - trie := NewEmpty(NewDatabase(rawdb.NewMemoryDatabase())) + trie := NewEmpty(NewDatabase(rawdb.NewMemoryDatabase(), nil)) for _, val := range vals { trie.MustUpdate([]byte(val.k), []byte(val.v)) } @@ -128,7 +128,7 @@ }   func testAccessList(t *testing.T, vals []struct{ k, v string }) { var ( - db = NewDatabase(rawdb.NewMemoryDatabase()) + db = NewDatabase(rawdb.NewMemoryDatabase(), nil) trie = NewEmpty(db) orig = trie.Copy() ) @@ -211,7 +211,7 @@ // Tests origin values won't be tracked in Iterator or Prover func TestAccessListLeak(t *testing.T) { var ( - db = NewDatabase(rawdb.NewMemoryDatabase()) + db = NewDatabase(rawdb.NewMemoryDatabase(), nil) trie = NewEmpty(db) ) // Create trie from scratch @@ -262,7 +262,7 @@ // Tests whether the original tree node is correctly deleted after being embedded // in its parent due to the smaller size of the original tree node. func TestTinyTree(t *testing.T) { var ( - db = NewDatabase(rawdb.NewMemoryDatabase()) + db = NewDatabase(rawdb.NewMemoryDatabase(), nil) trie = NewEmpty(db) ) for _, val := range tiny {
diff --git ethereum/go-ethereum/trie/trie_reader.go taikoxyz/taiko-geth/trie/trie_reader.go index 1c63ff4544fd3f3f7358d4840447e42107e0c67a..42159645590fbe425e6f1f2a3c2daeee62a528e5 100644 --- ethereum/go-ethereum/trie/trie_reader.go +++ taikoxyz/taiko-geth/trie/trie_reader.go @@ -20,6 +20,7 @@ import ( "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/log" + "github.com/ethereum/go-ethereum/trie/triestate" )   // Reader wraps the Node method of a backing trie store. @@ -83,3 +84,18 @@ return nil, &MissingNodeError{Owner: r.owner, NodeHash: hash, Path: path, err: err} } return blob, nil } + +// trieLoader implements triestate.TrieLoader for constructing tries. +type trieLoader struct { + db *Database +} + +// OpenTrie opens the main account trie. +func (l *trieLoader) OpenTrie(root common.Hash) (triestate.Trie, error) { + return New(TrieID(root), l.db) +} + +// OpenStorageTrie opens the storage trie of an account. +func (l *trieLoader) OpenStorageTrie(stateRoot common.Hash, addrHash, root common.Hash) (triestate.Trie, error) { + return New(StorageTrieID(stateRoot, addrHash, root), l.db) +}
diff --git ethereum/go-ethereum/trie/trie_test.go taikoxyz/taiko-geth/trie/trie_test.go index 3cb21c1956b312735bbb1a23fa06484a2275844b..2dfe81ef81d2ffd7860c169074ae6c808b1c8a1a 100644 --- ethereum/go-ethereum/trie/trie_test.go +++ taikoxyz/taiko-geth/trie/trie_test.go @@ -45,7 +45,7 @@ spew.Config.DisableMethods = false }   func TestEmptyTrie(t *testing.T) { - trie := NewEmpty(NewDatabase(rawdb.NewMemoryDatabase())) + trie := NewEmpty(NewDatabase(rawdb.NewMemoryDatabase(), nil)) res := trie.Hash() exp := types.EmptyRootHash if res != exp { @@ -54,7 +54,7 @@ } }   func TestNull(t *testing.T) { - trie := NewEmpty(NewDatabase(rawdb.NewMemoryDatabase())) + trie := NewEmpty(NewDatabase(rawdb.NewMemoryDatabase(), nil)) key := make([]byte, 32) value := []byte("test") trie.MustUpdate(key, value) @@ -64,8 +64,13 @@ } }   func TestMissingRoot(t *testing.T) { + testMissingRoot(t, rawdb.HashScheme) + testMissingRoot(t, rawdb.PathScheme) +} + +func testMissingRoot(t *testing.T, scheme string) { root := common.HexToHash("0beec7b5ea3f0fdbc95d0dd47f3c5bc275da8a33") - trie, err := New(TrieID(root), NewDatabase(rawdb.NewMemoryDatabase())) + trie, err := New(TrieID(root), newTestDatabase(rawdb.NewMemoryDatabase(), scheme)) if trie != nil { t.Error("New returned non-nil trie for invalid root") } @@ -161,7 +166,7 @@ } }   func TestInsert(t *testing.T) { - trie := NewEmpty(NewDatabase(rawdb.NewMemoryDatabase())) + trie := NewEmpty(NewDatabase(rawdb.NewMemoryDatabase(), nil))   updateString(trie, "doe", "reindeer") updateString(trie, "dog", "puppy") @@ -173,7 +178,7 @@ if root != exp { t.Errorf("case 1: exp %x got %x", exp, root) }   - trie = NewEmpty(NewDatabase(rawdb.NewMemoryDatabase())) + trie = NewEmpty(NewDatabase(rawdb.NewMemoryDatabase(), nil)) updateString(trie, "A", "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa")   exp = common.HexToHash("d23786fb4a010da3ce639d66d5e904a11dbc02746d1ce25029e53290cabf28ab") @@ -184,7 +189,7 @@ } }   func TestGet(t *testing.T) { - db := NewDatabase(rawdb.NewMemoryDatabase()) + db := NewDatabase(rawdb.NewMemoryDatabase(), nil) trie := NewEmpty(db) updateString(trie, "doe", "reindeer") updateString(trie, "dog", "puppy") @@ -209,7 +214,7 @@ } }   func TestDelete(t *testing.T) { - trie := NewEmpty(NewDatabase(rawdb.NewMemoryDatabase())) + trie := NewEmpty(NewDatabase(rawdb.NewMemoryDatabase(), nil)) vals := []struct{ k, v string }{ {"do", "verb"}, {"ether", "wookiedoo"}, @@ -236,7 +241,7 @@ } }   func TestEmptyValues(t *testing.T) { - trie := NewEmpty(NewDatabase(rawdb.NewMemoryDatabase())) + trie := NewEmpty(NewDatabase(rawdb.NewMemoryDatabase(), nil))   vals := []struct{ k, v string }{ {"do", "verb"}, @@ -260,7 +265,7 @@ } }   func TestReplication(t *testing.T) { - db := NewDatabase(rawdb.NewMemoryDatabase()) + db := NewDatabase(rawdb.NewMemoryDatabase(), nil) trie := NewEmpty(db) vals := []struct{ k, v string }{ {"do", "verb"}, @@ -321,7 +326,7 @@ } }   func TestLargeValue(t *testing.T) { - trie := NewEmpty(NewDatabase(rawdb.NewMemoryDatabase())) + trie := NewEmpty(NewDatabase(rawdb.NewMemoryDatabase(), nil)) trie.MustUpdate([]byte("key1"), []byte{99, 99, 99, 99}) trie.MustUpdate([]byte("key2"), bytes.Repeat([]byte{1}, 32)) trie.Hash() @@ -604,12 +609,14 @@ const benchElemCount = 20000   func benchGet(b *testing.B) { - triedb := NewDatabase(rawdb.NewMemoryDatabase()) + triedb := NewDatabase(rawdb.NewMemoryDatabase(), nil) trie := NewEmpty(triedb) k := make([]byte, 32) for i := 0; i < benchElemCount; i++ { binary.LittleEndian.PutUint64(k, uint64(i)) - trie.MustUpdate(k, k) + v := make([]byte, 32) + binary.LittleEndian.PutUint64(v, uint64(i)) + trie.MustUpdate(k, v) } binary.LittleEndian.PutUint64(k, benchElemCount/2)   @@ -621,12 +628,14 @@ b.StopTimer() }   func benchUpdate(b *testing.B, e binary.ByteOrder) *Trie { - trie := NewEmpty(NewDatabase(rawdb.NewMemoryDatabase())) + trie := NewEmpty(NewDatabase(rawdb.NewMemoryDatabase(), nil)) k := make([]byte, 32) b.ReportAllocs() for i := 0; i < b.N; i++ { + v := make([]byte, 32) e.PutUint64(k, uint64(i)) - trie.MustUpdate(k, k) + e.PutUint64(v, uint64(i)) + trie.MustUpdate(k, v) } return trie } @@ -651,7 +660,7 @@ // Create a realistic account trie to hash. We're first adding and hashing N // entries, then adding N more. addresses, accounts := makeAccounts(2 * b.N) // Insert the accounts into the trie and hash it - trie := NewEmpty(NewDatabase(rawdb.NewMemoryDatabase())) + trie := NewEmpty(NewDatabase(rawdb.NewMemoryDatabase(), nil)) i := 0 for ; i < len(addresses)/2; i++ { trie.MustUpdate(crypto.Keccak256(addresses[i][:]), accounts[i]) @@ -682,7 +691,7 @@ func benchmarkCommitAfterHash(b *testing.B, collectLeaf bool) { // Make the random benchmark deterministic addresses, accounts := makeAccounts(b.N) - trie := NewEmpty(NewDatabase(rawdb.NewMemoryDatabase())) + trie := NewEmpty(NewDatabase(rawdb.NewMemoryDatabase(), nil)) for i := 0; i < len(addresses); i++ { trie.MustUpdate(crypto.Keccak256(addresses[i][:]), accounts[i]) } @@ -696,7 +705,7 @@ func TestTinyTrie(t *testing.T) { // Create a realistic account trie to hash _, accounts := makeAccounts(5) - trie := NewEmpty(NewDatabase(rawdb.NewMemoryDatabase())) + trie := NewEmpty(NewDatabase(rawdb.NewMemoryDatabase(), nil)) trie.MustUpdate(common.Hex2Bytes("0000000000000000000000000000000000000000000000000000000000001337"), accounts[3]) if exp, root := common.HexToHash("8c6a85a4d9fda98feff88450299e574e5378e32391f75a055d470ac0653f1005"), trie.Hash(); exp != root { t.Errorf("1: got %x, exp %x", root, exp) @@ -709,7 +718,7 @@ trie.MustUpdate(common.Hex2Bytes("0000000000000000000000000000000000000000000000000000000000001339"), accounts[4]) if exp, root := common.HexToHash("0608c1d1dc3905fa22204c7a0e43644831c3b6d3def0f274be623a948197e64a"), trie.Hash(); exp != root { t.Errorf("3: got %x, exp %x", root, exp) } - checktr := NewEmpty(NewDatabase(rawdb.NewMemoryDatabase())) + checktr := NewEmpty(NewDatabase(rawdb.NewMemoryDatabase(), nil)) it := NewIterator(trie.MustNodeIterator(nil)) for it.Next() { checktr.MustUpdate(it.Key, it.Value) @@ -722,7 +731,7 @@ func TestCommitAfterHash(t *testing.T) { // Create a realistic account trie to hash addresses, accounts := makeAccounts(1000) - trie := NewEmpty(NewDatabase(rawdb.NewMemoryDatabase())) + trie := NewEmpty(NewDatabase(rawdb.NewMemoryDatabase(), nil)) for i := 0; i < len(addresses); i++ { trie.MustUpdate(crypto.Keccak256(addresses[i][:]), accounts[i]) } @@ -788,11 +797,17 @@ func (s *spongeDb) Stat(property string) (string, error) { panic("implement me") } func (s *spongeDb) Compact(start []byte, limit []byte) error { panic("implement me") } func (s *spongeDb) Close() error { return nil } func (s *spongeDb) Put(key []byte, value []byte) error { - valbrief := value + var ( + keybrief = key + valbrief = value + ) + if len(keybrief) > 8 { + keybrief = keybrief[:8] + } if len(valbrief) > 8 { valbrief = valbrief[:8] } - s.journal = append(s.journal, fmt.Sprintf("%v: PUT([%x...], [%d bytes] %x...)\n", s.id, key[:8], len(value), valbrief)) + s.journal = append(s.journal, fmt.Sprintf("%v: PUT([%x...], [%d bytes] %x...)\n", s.id, keybrief, len(value), valbrief)) s.sponge.Write(key) s.sponge.Write(value) return nil @@ -830,7 +845,7 @@ } { addresses, accounts := makeAccounts(tc.count) // This spongeDb is used to check the sequence of disk-db-writes s := &spongeDb{sponge: sha3.NewLegacyKeccak256()} - db := NewDatabase(rawdb.NewDatabase(s)) + db := NewDatabase(rawdb.NewDatabase(s), nil) trie := NewEmpty(db) // Fill the trie with elements for i := 0; i < tc.count; i++ { @@ -861,7 +876,7 @@ } { prng := rand.New(rand.NewSource(int64(i))) // This spongeDb is used to check the sequence of disk-db-writes s := &spongeDb{sponge: sha3.NewLegacyKeccak256()} - db := NewDatabase(rawdb.NewDatabase(s)) + db := NewDatabase(rawdb.NewDatabase(s), nil) trie := NewEmpty(db) // Fill the trie with elements for i := 0; i < tc.count; i++ { @@ -893,12 +908,12 @@ for count := 1; count < 200; count++ { prng := rand.New(rand.NewSource(int64(count))) // This spongeDb is used to check the sequence of disk-db-writes s := &spongeDb{sponge: sha3.NewLegacyKeccak256(), id: "a"} - db := NewDatabase(rawdb.NewDatabase(s)) + db := NewDatabase(rawdb.NewDatabase(s), nil) trie := NewEmpty(db) // Another sponge is used for the stacktrie commits stackTrieSponge := &spongeDb{sponge: sha3.NewLegacyKeccak256(), id: "b"} - stTrie := NewStackTrie(func(owner common.Hash, path []byte, hash common.Hash, blob []byte) { - rawdb.WriteTrieNode(stackTrieSponge, owner, path, hash, blob, db.Scheme()) + stTrie := NewStackTrie(func(path []byte, hash common.Hash, blob []byte) { + rawdb.WriteTrieNode(stackTrieSponge, common.Hash{}, path, hash, blob, db.Scheme()) }) // Fill the trie with elements for i := 0; i < count; i++ { @@ -952,12 +967,12 @@ // that even a small trie which contains a leaf will have an extension making it // not fit into 32 bytes, rlp-encoded. However, it's still the correct thing to do. func TestCommitSequenceSmallRoot(t *testing.T) { s := &spongeDb{sponge: sha3.NewLegacyKeccak256(), id: "a"} - db := NewDatabase(rawdb.NewDatabase(s)) + db := NewDatabase(rawdb.NewDatabase(s), nil) trie := NewEmpty(db) // Another sponge is used for the stacktrie commits stackTrieSponge := &spongeDb{sponge: sha3.NewLegacyKeccak256(), id: "b"} - stTrie := NewStackTrie(func(owner common.Hash, path []byte, hash common.Hash, blob []byte) { - rawdb.WriteTrieNode(stackTrieSponge, owner, path, hash, blob, db.Scheme()) + stTrie := NewStackTrie(func(path []byte, hash common.Hash, blob []byte) { + rawdb.WriteTrieNode(stackTrieSponge, common.Hash{}, path, hash, blob, db.Scheme()) }) // Add a single small-element to the trie(s) key := make([]byte, 5) @@ -1029,7 +1044,7 @@ }   func benchmarkHashFixedSize(b *testing.B, addresses [][20]byte, accounts [][]byte) { b.ReportAllocs() - trie := NewEmpty(NewDatabase(rawdb.NewMemoryDatabase())) + trie := NewEmpty(NewDatabase(rawdb.NewMemoryDatabase(), nil)) for i := 0; i < len(addresses); i++ { trie.MustUpdate(crypto.Keccak256(addresses[i][:]), accounts[i]) } @@ -1080,7 +1095,7 @@ }   func benchmarkCommitAfterHashFixedSize(b *testing.B, addresses [][20]byte, accounts [][]byte) { b.ReportAllocs() - trie := NewEmpty(NewDatabase(rawdb.NewMemoryDatabase())) + trie := NewEmpty(NewDatabase(rawdb.NewMemoryDatabase(), nil)) for i := 0; i < len(addresses); i++ { trie.MustUpdate(crypto.Keccak256(addresses[i][:]), accounts[i]) } @@ -1132,7 +1147,7 @@ }   func benchmarkDerefRootFixedSize(b *testing.B, addresses [][20]byte, accounts [][]byte) { b.ReportAllocs() - triedb := NewDatabase(rawdb.NewMemoryDatabase()) + triedb := NewDatabase(rawdb.NewMemoryDatabase(), nil) trie := NewEmpty(triedb) for i := 0; i < len(addresses); i++ { trie.MustUpdate(crypto.Keccak256(addresses[i][:]), accounts[i])
diff --git ethereum/go-ethereum/trie/triedb/hashdb/database.go taikoxyz/taiko-geth/trie/triedb/hashdb/database.go index 4441f2a3827d2a6b7d2a681936e1ca90f6a2e789..764ab24ec8dd9f4c0ed1a6fcf806f7c463d14ae0 100644 --- ethereum/go-ethereum/trie/triedb/hashdb/database.go +++ taikoxyz/taiko-geth/trie/triedb/hashdb/database.go @@ -65,6 +65,20 @@ type ChildResolver interface { ForEach(node []byte, onChild func(common.Hash)) }   +// Config contains the settings for database. +type Config struct { + CleanCacheSize int // Maximum memory allowance (in bytes) for caching clean nodes +} + +// Defaults is the default setting for database if it's not specified. +// Notably, clean cache is disabled explicitly, +var Defaults = &Config{ + // Explicitly set clean cache size to 0 to avoid creating fastcache, + // otherwise database must be closed when it's no longer needed to + // prevent memory leak. + CleanCacheSize: 0, +} + // Database is an intermediate write layer between the trie data structures and // the disk database. The aim is to accumulate trie writes in-memory and only // periodically flush a couple tries to disk, garbage collecting the remainder. @@ -122,12 +136,13 @@ resolver.ForEach(n.node, onChild) }   // New initializes the hash-based node database. -func New(diskdb ethdb.Database, size int, resolver ChildResolver) *Database { - // Initialize the clean cache if the specified cache allowance - // is non-zero. Note, the size is in bytes. +func New(diskdb ethdb.Database, config *Config, resolver ChildResolver) *Database { + if config == nil { + config = Defaults + } var cleans *fastcache.Cache - if size > 0 { - cleans = fastcache.New(size) + if config.CleanCacheSize > 0 { + cleans = fastcache.New(config.CleanCacheSize) } return &Database{ diskdb: diskdb, @@ -609,7 +624,10 @@ }   // Size returns the current storage size of the memory cache in front of the // persistent database layer. -func (db *Database) Size() common.StorageSize { +// +// The first return will always be 0, representing the memory stored in unbounded +// diff layers above the dirty cache. This is only available in pathdb. +func (db *Database) Size() (common.StorageSize, common.StorageSize) { db.lock.RLock() defer db.lock.RUnlock()   @@ -617,11 +635,17 @@ // db.dirtiesSize only contains the useful data in the cache, but when reporting // the total memory consumption, the maintenance metadata is also needed to be // counted. var metadataSize = common.StorageSize(len(db.dirties) * cachedNodeSize) - return db.dirtiesSize + db.childrenSize + metadataSize + return 0, db.dirtiesSize + db.childrenSize + metadataSize }   // Close closes the trie database and releases all held resources. -func (db *Database) Close() error { return nil } +func (db *Database) Close() error { + if db.cleans != nil { + db.cleans.Reset() + db.cleans = nil + } + return nil +}   // Scheme returns the node scheme used in the database. func (db *Database) Scheme() string {
diff --git ethereum/go-ethereum/trie/triedb/pathdb/database.go taikoxyz/taiko-geth/trie/triedb/pathdb/database.go index 29f6b5e103cd9f138eea954484da071f2cf4e5be..dc64414e9b520aeca5a08e6ca44b090680729dcf 100644 --- ethereum/go-ethereum/trie/triedb/pathdb/database.go +++ taikoxyz/taiko-geth/trie/triedb/pathdb/database.go @@ -33,8 +33,26 @@ "github.com/ethereum/go-ethereum/trie/trienode" "github.com/ethereum/go-ethereum/trie/triestate" )   -// maxDiffLayers is the maximum diff layers allowed in the layer tree. -const maxDiffLayers = 128 +const ( + // maxDiffLayers is the maximum diff layers allowed in the layer tree. + maxDiffLayers = 128 + + // defaultCleanSize is the default memory allowance of clean cache. + defaultCleanSize = 16 * 1024 * 1024 + + // maxBufferSize is the maximum memory allowance of node buffer. + // Too large nodebuffer will cause the system to pause for a long + // time when write happens. Also, the largest batch that pebble can + // support is 4GB, node will panic if batch size exceeds this limit. + maxBufferSize = 256 * 1024 * 1024 + + // DefaultBufferSize is the default memory allowance of node buffer + // that aggregates the writes from above until it's flushed into the + // disk. It's meant to be used once the initial sync is finished. + // Do not increase the buffer size arbitrarily, otherwise the system + // pause time will increase when the database writes happen. + DefaultBufferSize = 64 * 1024 * 1024 +)   // layer is the interface implemented by all state layers which includes some // public methods and some additional methods for internal usage. @@ -68,29 +86,32 @@ }   // Config contains the settings for database. type Config struct { - StateLimit uint64 // Number of recent blocks to maintain state history for - CleanSize int // Maximum memory allowance (in bytes) for caching clean nodes - DirtySize int // Maximum memory allowance (in bytes) for caching dirty nodes - ReadOnly bool // Flag whether the database is opened in read only mode. + StateHistory uint64 // Number of recent blocks to maintain state history for + CleanCacheSize int // Maximum memory allowance (in bytes) for caching clean nodes + DirtyCacheSize int // Maximum memory allowance (in bytes) for caching dirty nodes + ReadOnly bool // Flag whether the database is opened in read only mode. }   -var ( - // defaultCleanSize is the default memory allowance of clean cache. - defaultCleanSize = 16 * 1024 * 1024 - - // defaultBufferSize is the default memory allowance of node buffer - // that aggregates the writes from above until it's flushed into the - // disk. Do not increase the buffer size arbitrarily, otherwise the - // system pause time will increase when the database writes happen. - defaultBufferSize = 128 * 1024 * 1024 -) +// sanitize checks the provided user configurations and changes anything that's +// unreasonable or unworkable. +func (c *Config) sanitize() *Config { + conf := *c + if conf.DirtyCacheSize > maxBufferSize { + log.Warn("Sanitizing invalid node buffer size", "provided", common.StorageSize(conf.DirtyCacheSize), "updated", common.StorageSize(maxBufferSize)) + conf.DirtyCacheSize = maxBufferSize + } + return &conf +}   // Defaults contains default settings for Ethereum mainnet. var Defaults = &Config{ - StateLimit: params.FullImmutabilityThreshold, - CleanSize: defaultCleanSize, - DirtySize: defaultBufferSize, + StateHistory: params.FullImmutabilityThreshold, + CleanCacheSize: defaultCleanSize, + DirtyCacheSize: DefaultBufferSize, } + +// ReadOnly is the config in order to open database in read only mode. +var ReadOnly = &Config{ReadOnly: true}   // Database is a multiple-layered structure for maintaining in-memory trie nodes. // It consists of one persistent base layer backed by a key-value store, on top @@ -107,7 +128,8 @@ type Database struct { // readOnly is the flag whether the mutation is allowed to be applied. // It will be set automatically when the database is journaled during // the shutdown to reject all following unexpected mutations. - readOnly bool // Indicator if database is opened in read only mode + readOnly bool // Flag if database is opened in read only mode + waitSync bool // Flag if database is deactivated due to initial state sync bufferSize int // Memory allowance (in bytes) for caching dirty nodes config *Config // Configuration for database diskdb ethdb.Database // Persistent storage for matured trie nodes @@ -123,9 +145,11 @@ func New(diskdb ethdb.Database, config *Config) *Database { if config == nil { config = Defaults } + config = config.sanitize() + db := &Database{ readOnly: config.ReadOnly, - bufferSize: config.DirtySize, + bufferSize: config.DirtyCacheSize, config: config, diskdb: diskdb, } @@ -140,7 +164,7 @@ // Because the freezer can only be opened once at the same time, this // mechanism also ensures that at most one **non-readOnly** database // is opened at the same time to prevent accidental mutation. if ancient, err := diskdb.AncientDatadir(); err == nil && ancient != "" && !db.readOnly { - freezer, err := rawdb.NewStateHistoryFreezer(ancient, false) + freezer, err := rawdb.NewStateFreezer(ancient, false) if err != nil { log.Crit("Failed to open state history freezer", "err", err) } @@ -156,6 +180,12 @@ if pruned != 0 { log.Warn("Truncated extra state histories", "number", pruned) } } + // Disable database in case node is still in the initial state sync stage. + if rawdb.ReadSnapSyncStatusFlag(diskdb) == rawdb.StateSyncRunning && !db.readOnly { + if err := db.Disable(); err != nil { + log.Crit("Failed to disable database", "err", err) // impossible to happen + } + } log.Warn("Path-based state scheme is an experimental feature") return db } @@ -181,9 +211,9 @@ // Hold the lock to prevent concurrent mutations. db.lock.Lock() defer db.lock.Unlock()   - // Short circuit if the database is in read only mode. - if db.readOnly { - return errSnapshotReadOnly + // Short circuit if the mutation is not allowed. + if err := db.modifyAllowed(); err != nil { + return err } if err := db.tree.add(root, parentRoot, block, nodes, states); err != nil { return err @@ -204,45 +234,59 @@ // Hold the lock to prevent concurrent mutations. db.lock.Lock() defer db.lock.Unlock()   + // Short circuit if the mutation is not allowed. + if err := db.modifyAllowed(); err != nil { + return err + } + return db.tree.cap(root, 0) +} + +// Disable deactivates the database and invalidates all available state layers +// as stale to prevent access to the persistent state, which is in the syncing +// stage. +func (db *Database) Disable() error { + db.lock.Lock() + defer db.lock.Unlock() + // Short circuit if the database is in read only mode. if db.readOnly { - return errSnapshotReadOnly + return errDatabaseReadOnly } - return db.tree.cap(root, 0) + // Prevent duplicated disable operation. + if db.waitSync { + log.Error("Reject duplicated disable operation") + return nil + } + db.waitSync = true + + // Mark the disk layer as stale to prevent access to persistent state. + db.tree.bottom().markStale() + + // Write the initial sync flag to persist it across restarts. + rawdb.WriteSnapSyncStatusFlag(db.diskdb, rawdb.StateSyncRunning) + log.Info("Disabled trie database due to state sync") + return nil }   -// Reset rebuilds the database with the specified state as the base. -// -// - if target state is empty, clear the stored state and all layers on top -// - if target state is non-empty, ensure the stored state matches with it -// and clear all other layers on top. -func (db *Database) Reset(root common.Hash) error { +// Enable activates database and resets the state tree with the provided persistent +// state root once the state sync is finished. +func (db *Database) Enable(root common.Hash) error { db.lock.Lock() defer db.lock.Unlock()   // Short circuit if the database is in read only mode. if db.readOnly { - return errSnapshotReadOnly + return errDatabaseReadOnly } - batch := db.diskdb.NewBatch() + // Ensure the provided state root matches the stored one. root = types.TrieRootHash(root) - if root == types.EmptyRootHash { - // Empty state is requested as the target, nuke out - // the root node and leave all others as dangling. - rawdb.DeleteAccountTrieNode(batch, nil) - } else { - // Ensure the requested state is existent before any - // action is applied. - _, hash := rawdb.ReadAccountTrieNode(db.diskdb, nil) - if hash != root { - return fmt.Errorf("state is mismatched, local: %x, target: %x", hash, root) - } + _, stored := rawdb.ReadAccountTrieNode(db.diskdb, nil) + if stored != root { + return fmt.Errorf("state root mismatch: stored %x, synced %x", stored, root) } - // Mark the disk layer as stale before applying any mutation. - db.tree.bottom().markStale() - // Drop the stale state journal in persistent database and // reset the persistent state id back to zero. + batch := db.diskdb.NewBatch() rawdb.DeleteTrieJournal(batch) rawdb.WritePersistentStateID(batch, 0) if err := batch.Write(); err != nil { @@ -259,8 +303,11 @@ } } // Re-construct a new disk layer backed by persistent state // with **empty clean cache and node buffer**. - dl := newDiskLayer(root, 0, db, nil, newNodeBuffer(db.bufferSize, nil, 0)) - db.tree.reset(dl) + db.tree.reset(newDiskLayer(root, 0, db, nil, newNodeBuffer(db.bufferSize, nil, 0))) + + // Re-enable the database as the final step. + db.waitSync = false + rawdb.WriteSnapSyncStatusFlag(db.diskdb, rawdb.StateSyncFinished) log.Info("Rebuilt trie database", "root", root) return nil } @@ -273,7 +320,10 @@ db.lock.Lock() defer db.lock.Unlock()   // Short circuit if rollback operation is not supported. - if db.readOnly || db.freezer == nil { + if err := db.modifyAllowed(); err != nil { + return err + } + if db.freezer == nil { return errors.New("state rollback is non-supported") } // Short circuit if the target state is not recoverable. @@ -344,7 +394,14 @@ func (db *Database) Close() error { db.lock.Lock() defer db.lock.Unlock()   + // Set the database to read-only mode to prevent all + // following mutations. db.readOnly = true + + // Release the memory held by clean cache. + db.tree.bottom().resetCache() + + // Close the attached state history freezer. if db.freezer == nil { return nil } @@ -353,16 +410,16 @@ }   // Size returns the current storage size of the memory cache in front of the // persistent database layer. -func (db *Database) Size() (size common.StorageSize) { +func (db *Database) Size() (diffs common.StorageSize, nodes common.StorageSize) { db.tree.forEach(func(layer layer) { if diff, ok := layer.(*diffLayer); ok { - size += common.StorageSize(diff.memory) + diffs += common.StorageSize(diff.memory) } if disk, ok := layer.(*diskLayer); ok { - size += disk.size() + nodes += disk.size() } }) - return size + return diffs, nodes }   // Initialized returns an indicator if the state data is already @@ -382,6 +439,10 @@ func (db *Database) SetBufferSize(size int) error { db.lock.Lock() defer db.lock.Unlock()   + if size > maxBufferSize { + log.Info("Capped node buffer size", "provided", common.StorageSize(size), "adjusted", common.StorageSize(maxBufferSize)) + size = maxBufferSize + } db.bufferSize = size return db.tree.bottom().setBufferSize(db.bufferSize) } @@ -390,3 +451,15 @@ // Scheme returns the node scheme used in the database. func (db *Database) Scheme() string { return rawdb.PathScheme } + +// modifyAllowed returns the indicator if mutation is allowed. This function +// assumes the db.lock is already held. +func (db *Database) modifyAllowed() error { + if db.readOnly { + return errDatabaseReadOnly + } + if db.waitSync { + return errDatabaseWaitSync + } + return nil +}
diff --git ethereum/go-ethereum/trie/triedb/pathdb/database_test.go taikoxyz/taiko-geth/trie/triedb/pathdb/database_test.go index bcc37e59c853050b769f8bc47133f2c41e3ed217..912364f7f44a90cfd1491b925bac5443aa51b7a0 100644 --- ethereum/go-ethereum/trie/triedb/pathdb/database_test.go +++ taikoxyz/taiko-geth/trie/triedb/pathdb/database_test.go @@ -46,7 +46,8 @@ } else { h.Update(key.Bytes(), val) } } - return h.Commit(false) + root, nodes, _ := h.Commit(false) + return root, nodes }   func generateAccount(storageRoot common.Hash) types.StateAccount { @@ -98,7 +99,7 @@ func newTester(t *testing.T) *tester { var ( disk, _ = rawdb.NewDatabaseWithFreezer(rawdb.NewMemoryDatabase(), t.TempDir(), "", false) - db = New(disk, &Config{CleanSize: 256 * 1024, DirtySize: 256 * 1024}) + db = New(disk, &Config{CleanCacheSize: 256 * 1024, DirtyCacheSize: 256 * 1024}) obj = &tester{ db: db, preimages: make(map[common.Hash]common.Address), @@ -438,38 +439,39 @@ } } }   -func TestReset(t *testing.T) { - var ( - tester = newTester(t) - index = tester.bottomIndex() - ) +func TestDisable(t *testing.T) { + tester := newTester(t) defer tester.release()   - // Reset database to unknown target, should reject it - if err := tester.db.Reset(testutil.RandomHash()); err == nil { - t.Fatal("Failed to reject invalid reset") + _, stored := rawdb.ReadAccountTrieNode(tester.db.diskdb, nil) + if err := tester.db.Disable(); err != nil { + t.Fatal("Failed to deactivate database") + } + if err := tester.db.Enable(types.EmptyRootHash); err == nil { + t.Fatalf("Invalid activation should be rejected") } - // Reset database to state persisted in the disk - if err := tester.db.Reset(types.EmptyRootHash); err != nil { - t.Fatalf("Failed to reset database %v", err) + if err := tester.db.Enable(stored); err != nil { + t.Fatal("Failed to activate database") } + // Ensure journal is deleted from disk if blob := rawdb.ReadTrieJournal(tester.db.diskdb); len(blob) != 0 { t.Fatal("Failed to clean journal") } // Ensure all trie histories are removed - for i := 0; i <= index; i++ { - _, err := readHistory(tester.db.freezer, uint64(i+1)) - if err == nil { - t.Fatalf("Failed to clean state history, index %d", i+1) - } + n, err := tester.db.freezer.Ancients() + if err != nil { + t.Fatal("Failed to clean state history") + } + if n != 0 { + t.Fatal("Failed to clean state history") } // Verify layer tree structure, single disk layer is expected if tester.db.tree.len() != 1 { t.Fatalf("Extra layer kept %d", tester.db.tree.len()) } - if tester.db.tree.bottom().rootHash() != types.EmptyRootHash { - t.Fatalf("Root hash is not matched exp %x got %x", types.EmptyRootHash, tester.db.tree.bottom().rootHash()) + if tester.db.tree.bottom().rootHash() != stored { + t.Fatalf("Root hash is not matched exp %x got %x", stored, tester.db.tree.bottom().rootHash()) } }
diff --git ethereum/go-ethereum/trie/triedb/pathdb/difflayer.go taikoxyz/taiko-geth/trie/triedb/pathdb/difflayer.go index d25ac1c601d79ef86145abefe20a2fd02b7e4a11..10567715d2e71e98052ed8d755e1aedf0356d234 100644 --- ethereum/go-ethereum/trie/triedb/pathdb/difflayer.go +++ taikoxyz/taiko-geth/trie/triedb/pathdb/difflayer.go @@ -114,7 +114,7 @@ // bubble up an error here. It shouldn't happen at all. if n.Hash != hash { dirtyFalseMeter.Mark(1) log.Error("Unexpected trie node in diff layer", "owner", owner, "path", path, "expect", hash, "got", n.Hash) - return nil, newUnexpectedNodeError("diff", hash, n.Hash, owner, path) + return nil, newUnexpectedNodeError("diff", hash, n.Hash, owner, path, n.Blob) } dirtyHitMeter.Mark(1) dirtyNodeHitDepthHist.Update(int64(depth))
diff --git ethereum/go-ethereum/trie/triedb/pathdb/difflayer_test.go taikoxyz/taiko-geth/trie/triedb/pathdb/difflayer_test.go index 77c4cd5722dad094e15606848a75abaed3bcca10..9b5907c3c5b30db61aa697b7c6dcfd97c17b36e6 100644 --- ethereum/go-ethereum/trie/triedb/pathdb/difflayer_test.go +++ taikoxyz/taiko-geth/trie/triedb/pathdb/difflayer_test.go @@ -29,7 +29,7 @@ func emptyLayer() *diskLayer { return &diskLayer{ db: New(rawdb.NewMemoryDatabase(), nil), - buffer: newNodeBuffer(defaultBufferSize, nil, 0), + buffer: newNodeBuffer(DefaultBufferSize, nil, 0), } }
diff --git ethereum/go-ethereum/trie/triedb/pathdb/disklayer.go taikoxyz/taiko-geth/trie/triedb/pathdb/disklayer.go index b526b3b7dd9db98be4db1119bfa8afcb061dc512..d3b6419cc59484c6a24368b6b24a545ff1bf1973 100644 --- ethereum/go-ethereum/trie/triedb/pathdb/disklayer.go +++ taikoxyz/taiko-geth/trie/triedb/pathdb/disklayer.go @@ -47,8 +47,8 @@ func newDiskLayer(root common.Hash, id uint64, db *Database, cleans *fastcache.Cache, buffer *nodebuffer) *diskLayer { // Initialize a clean cache if the memory allowance is not zero // or reuse the provided cache if it is not nil (inherited from // the original disk layer). - if cleans == nil && db.config.CleanSize != 0 { - cleans = fastcache.New(db.config.CleanSize) + if cleans == nil && db.config.CleanCacheSize != 0 { + cleans = fastcache.New(db.config.CleanCacheSize) } return &diskLayer{ root: root, @@ -150,7 +150,7 @@ } if nHash != hash { diskFalseMeter.Mark(1) log.Error("Unexpected trie node in disk", "owner", owner, "path", path, "expect", hash, "got", nHash) - return nil, newUnexpectedNodeError("disk", hash, nHash, owner, path) + return nil, newUnexpectedNodeError("disk", hash, nHash, owner, path, nBlob) } if dl.cleans != nil && len(nBlob) > 0 { dl.cleans.Set(key, nBlob) @@ -177,7 +177,7 @@ // after storing the state history but without flushing the // corresponding states(journal), the stored state history will // be truncated in the next restart. if dl.db.freezer != nil { - err := writeHistory(dl.db.diskdb, dl.db.freezer, bottom, dl.db.config.StateLimit) + err := writeHistory(dl.db.diskdb, dl.db.freezer, bottom, dl.db.config.StateHistory) if err != nil { return nil, err } @@ -274,6 +274,20 @@ if dl.stale { return 0 } return common.StorageSize(dl.buffer.size) +} + +// resetCache releases the memory held by clean cache to prevent memory leak. +func (dl *diskLayer) resetCache() { + dl.lock.RLock() + defer dl.lock.RUnlock() + + // Stale disk layer loses the ownership of clean cache. + if dl.stale { + return + } + if dl.cleans != nil { + dl.cleans.Reset() + } }   // hasher is used to compute the sha256 hash of the provided data.
diff --git ethereum/go-ethereum/trie/triedb/pathdb/errors.go taikoxyz/taiko-geth/trie/triedb/pathdb/errors.go index f503a9c49d2e0a0284149b27d2e933ec12084968..78ee4459fe50943d103ca2400173c6786317dfd0 100644 --- ethereum/go-ethereum/trie/triedb/pathdb/errors.go +++ taikoxyz/taiko-geth/trie/triedb/pathdb/errors.go @@ -21,12 +21,17 @@ "errors" "fmt"   "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/common/hexutil" )   var ( - // errSnapshotReadOnly is returned if the database is opened in read only mode - // and mutation is requested. - errSnapshotReadOnly = errors.New("read only") + // errDatabaseReadOnly is returned if the database is opened in read only mode + // to prevent any mutation. + errDatabaseReadOnly = errors.New("read only") + + // errDatabaseWaitSync is returned if the initial state sync is not completed + // yet and database is disabled to prevent accessing state. + errDatabaseWaitSync = errors.New("waiting for sync")   // errSnapshotStale is returned from data accessors if the underlying layer // layer had been invalidated due to the chain progressing forward far enough @@ -46,6 +51,10 @@ // not hash matched with expectation. errUnexpectedNode = errors.New("unexpected node") )   -func newUnexpectedNodeError(loc string, expHash common.Hash, gotHash common.Hash, owner common.Hash, path []byte) error { - return fmt.Errorf("%w, loc: %s, node: (%x %v), %x!=%x", errUnexpectedNode, loc, owner, path, expHash, gotHash) +func newUnexpectedNodeError(loc string, expHash common.Hash, gotHash common.Hash, owner common.Hash, path []byte, blob []byte) error { + blobHex := "nil" + if len(blob) > 0 { + blobHex = hexutil.Encode(blob) + } + return fmt.Errorf("%w, loc: %s, node: (%x %v), %x!=%x, blob: %s", errUnexpectedNode, loc, owner, path, expHash, gotHash, blobHex) }
diff --git ethereum/go-ethereum/trie/triedb/pathdb/history_test.go taikoxyz/taiko-geth/trie/triedb/pathdb/history_test.go index 6c250c2591ccb772a20daeb614bac0077b0a3e44..677103e2b0ad479e11ca05c916d9d8046a4deb1d 100644 --- ethereum/go-ethereum/trie/triedb/pathdb/history_test.go +++ taikoxyz/taiko-geth/trie/triedb/pathdb/history_test.go @@ -226,7 +226,7 @@ }   // openFreezer initializes the freezer instance for storing state histories. func openFreezer(datadir string, readOnly bool) (*rawdb.ResettableFreezer, error) { - return rawdb.NewStateHistoryFreezer(datadir, readOnly) + return rawdb.NewStateFreezer(datadir, readOnly) }   func compareSet[k comparable](a, b map[k][]byte) bool {
diff --git ethereum/go-ethereum/trie/triedb/pathdb/journal.go taikoxyz/taiko-geth/trie/triedb/pathdb/journal.go index d8c7d39fb9bdf794e52613c9b950c8be9d6d9a2e..ac770763e38df7315728ad1734720b8070776ec9 100644 --- ethereum/go-ethereum/trie/triedb/pathdb/journal.go +++ taikoxyz/taiko-geth/trie/triedb/pathdb/journal.go @@ -21,6 +21,7 @@ "bytes" "errors" "fmt" "io" + "time"   "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/core/rawdb" @@ -341,13 +342,21 @@ l := db.tree.get(root) if l == nil { return fmt.Errorf("triedb layer [%#x] missing", root) } + disk := db.tree.bottom() + if l, ok := l.(*diffLayer); ok { + log.Info("Persisting dirty state to disk", "head", l.block, "root", root, "layers", l.id-disk.id+disk.buffer.layers) + } else { // disk layer only on noop runs (likely) or deep reorgs (unlikely) + log.Info("Persisting dirty state to disk", "root", root, "layers", disk.buffer.layers) + } + start := time.Now() + // Run the journaling db.lock.Lock() defer db.lock.Unlock()   // Short circuit if the database is in read only mode. if db.readOnly { - return errSnapshotReadOnly + return errDatabaseReadOnly } // Firstly write out the metadata of journal journal := new(bytes.Buffer) @@ -373,6 +382,6 @@ rawdb.WriteTrieJournal(db.diskdb, journal.Bytes())   // Set the db in read only mode to reject all following mutations db.readOnly = true - log.Info("Stored journal in triedb", "disk", diskroot, "size", common.StorageSize(journal.Len())) + log.Info("Persisted dirty state to disk", "size", common.StorageSize(journal.Len()), "elapsed", common.PrettyDuration(time.Since(start))) return nil }
diff --git ethereum/go-ethereum/trie/triedb/pathdb/nodebuffer.go taikoxyz/taiko-geth/trie/triedb/pathdb/nodebuffer.go index 67de225b0495993b833a0ed49d1f7cb2bc4f0c58..4a7d328b9afb8fbbad679028debbaf3a07146581 100644 --- ethereum/go-ethereum/trie/triedb/pathdb/nodebuffer.go +++ taikoxyz/taiko-geth/trie/triedb/pathdb/nodebuffer.go @@ -71,7 +71,7 @@ } if n.Hash != hash { dirtyFalseMeter.Mark(1) log.Error("Unexpected trie node in node buffer", "owner", owner, "path", path, "expect", hash, "got", n.Hash) - return nil, newUnexpectedNodeError("dirty", hash, n.Hash, owner, path) + return nil, newUnexpectedNodeError("dirty", hash, n.Hash, owner, path, n.Blob) } return n, nil }
diff --git ethereum/go-ethereum/trie/triedb/pathdb/testutils.go taikoxyz/taiko-geth/trie/triedb/pathdb/testutils.go index 4406dbc52124ab93c8c6fa5dc1525f2e05f4a1df..d6fdacb4213e376492b7564e627e964c2f97214f 100644 --- ethereum/go-ethereum/trie/triedb/pathdb/testutils.go +++ taikoxyz/taiko-geth/trie/triedb/pathdb/testutils.go @@ -80,7 +80,7 @@ }   // Commit computes the new hash of the states and returns the set with all // state changes. -func (h *testHasher) Commit(collectLeaf bool) (common.Hash, *trienode.NodeSet) { +func (h *testHasher) Commit(collectLeaf bool) (common.Hash, *trienode.NodeSet, error) { var ( nodes = make(map[common.Hash][]byte) set = trienode.NewNodeSet(h.owner) @@ -108,7 +108,7 @@ } if root == types.EmptyRootHash && h.root != types.EmptyRootHash { set.AddNode(nil, trienode.NewDeleted()) } - return root, set + return root, set, nil }   // hash performs the hash computation upon the provided states.
diff --git ethereum/go-ethereum/light/nodeset.go taikoxyz/taiko-geth/trie/trienode/proof.go rename from light/nodeset.go rename to trie/trienode/proof.go index 3662596785c79f85250d949eb653b4872f9827d0..012f0087dded262bea272f84e71c4c5c0af7337b 100644 --- ethereum/go-ethereum/light/nodeset.go +++ taikoxyz/taiko-geth/trie/trienode/proof.go @@ -14,7 +14,7 @@ // // You should have received a copy of the GNU Lesser General Public License // along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.   -package light +package trienode   import ( "errors" @@ -26,9 +26,9 @@ "github.com/ethereum/go-ethereum/ethdb" "github.com/ethereum/go-ethereum/rlp" )   -// NodeSet stores a set of trie nodes. It implements trie.Database and can also +// ProofSet stores a set of trie nodes. It implements trie.Database and can also // act as a cache for another trie.Database. -type NodeSet struct { +type ProofSet struct { nodes map[string][]byte order []string   @@ -36,15 +36,15 @@ dataSize int lock sync.RWMutex }   -// NewNodeSet creates an empty node set -func NewNodeSet() *NodeSet { - return &NodeSet{ +// NewProofSet creates an empty node set +func NewProofSet() *ProofSet { + return &ProofSet{ nodes: make(map[string][]byte), } }   // Put stores a new node in the set -func (db *NodeSet) Put(key []byte, value []byte) error { +func (db *ProofSet) Put(key []byte, value []byte) error { db.lock.Lock() defer db.lock.Unlock()   @@ -61,7 +61,7 @@ return nil }   // Delete removes a node from the set -func (db *NodeSet) Delete(key []byte) error { +func (db *ProofSet) Delete(key []byte) error { db.lock.Lock() defer db.lock.Unlock()   @@ -70,7 +70,7 @@ return nil }   // Get returns a stored node -func (db *NodeSet) Get(key []byte) ([]byte, error) { +func (db *ProofSet) Get(key []byte) ([]byte, error) { db.lock.RLock() defer db.lock.RUnlock()   @@ -81,13 +81,13 @@ return nil, errors.New("not found") }   // Has returns true if the node set contains the given key -func (db *NodeSet) Has(key []byte) (bool, error) { +func (db *ProofSet) Has(key []byte) (bool, error) { _, err := db.Get(key) return err == nil, nil }   // KeyCount returns the number of nodes in the set -func (db *NodeSet) KeyCount() int { +func (db *ProofSet) KeyCount() int { db.lock.RLock() defer db.lock.RUnlock()   @@ -95,19 +95,19 @@ return len(db.nodes) }   // DataSize returns the aggregated data size of nodes in the set -func (db *NodeSet) DataSize() int { +func (db *ProofSet) DataSize() int { db.lock.RLock() defer db.lock.RUnlock()   return db.dataSize }   -// NodeList converts the node set to a NodeList -func (db *NodeSet) NodeList() NodeList { +// List converts the node set to a ProofList +func (db *ProofSet) List() ProofList { db.lock.RLock() defer db.lock.RUnlock()   - var values NodeList + var values ProofList for _, key := range db.order { values = append(values, db.nodes[key]) } @@ -115,7 +115,7 @@ return values }   // Store writes the contents of the set to the given database -func (db *NodeSet) Store(target ethdb.KeyValueWriter) { +func (db *ProofSet) Store(target ethdb.KeyValueWriter) { db.lock.RLock() defer db.lock.RUnlock()   @@ -124,36 +124,36 @@ target.Put([]byte(key), value) } }   -// NodeList stores an ordered list of trie nodes. It implements ethdb.KeyValueWriter. -type NodeList []rlp.RawValue +// ProofList stores an ordered list of trie nodes. It implements ethdb.KeyValueWriter. +type ProofList []rlp.RawValue   // Store writes the contents of the list to the given database -func (n NodeList) Store(db ethdb.KeyValueWriter) { +func (n ProofList) Store(db ethdb.KeyValueWriter) { for _, node := range n { db.Put(crypto.Keccak256(node), node) } }   -// NodeSet converts the node list to a NodeSet -func (n NodeList) NodeSet() *NodeSet { - db := NewNodeSet() +// Set converts the node list to a ProofSet +func (n ProofList) Set() *ProofSet { + db := NewProofSet() n.Store(db) return db }   // Put stores a new node at the end of the list -func (n *NodeList) Put(key []byte, value []byte) error { +func (n *ProofList) Put(key []byte, value []byte) error { *n = append(*n, value) return nil }   // Delete panics as there's no reason to remove a node from the list. -func (n *NodeList) Delete(key []byte) error { +func (n *ProofList) Delete(key []byte) error { panic("not supported") }   // DataSize returns the aggregated data size of nodes in the list -func (n NodeList) DataSize() int { +func (n ProofList) DataSize() int { var size int for _, node := range n { size += len(node)
diff --git ethereum/go-ethereum/trie/triestate/state.go taikoxyz/taiko-geth/trie/triestate/state.go index cb3611baf9cd08db2bcda099e728d33489a65464..4c47e9c3973495ed881c75315a2f011b3bcfef6c 100644 --- ethereum/go-ethereum/trie/triestate/state.go +++ taikoxyz/taiko-geth/trie/triestate/state.go @@ -43,7 +43,7 @@ Delete(key []byte) error   // Commit the trie and returns a set of dirty nodes generated along with // the new root hash. - Commit(collectLeaf bool) (common.Hash, *trienode.NodeSet) + Commit(collectLeaf bool) (common.Hash, *trienode.NodeSet, error) }   // TrieLoader wraps functions to load tries. @@ -129,7 +129,10 @@ if err != nil { return nil, fmt.Errorf("failed to revert state, err: %w", err) } } - root, result := tr.Commit(false) + root, result, err := tr.Commit(false) + if err != nil { + return nil, err + } if root != prevRoot { return nil, fmt.Errorf("failed to revert state, want %#x, got %#x", prevRoot, root) } @@ -181,7 +184,10 @@ if err != nil { return err } } - root, result := st.Commit(false) + root, result, err := st.Commit(false) + if err != nil { + return err + } if root != prev.Root { return errors.New("failed to reset storage trie") } @@ -232,7 +238,10 @@ if err := st.Delete(key.Bytes()); err != nil { return err } } - root, result := st.Commit(false) + root, result, err := st.Commit(false) + if err != nil { + return err + } if root != types.EmptyRootHash { return errors.New("failed to clear storage trie") }
diff --git ethereum/go-ethereum/.github/workflows/ci.yml taikoxyz/taiko-geth/.github/workflows/ci.yml new file mode 100644 index 0000000000000000000000000000000000000000..9c0b770436b98e496f42701751d5ae7685de8df3 --- /dev/null +++ taikoxyz/taiko-geth/.github/workflows/ci.yml @@ -0,0 +1,33 @@ +name: "Unit tests" + +on: + pull_request: + branches: [taiko] + push: + branches: [taiko] + +jobs: + test: + runs-on: ubuntu-latest + steps: + - name: Cancel Previous Runs + uses: styfle/cancel-workflow-action@0.11.0 + with: + access_token: ${{ github.token }} + + - uses: actions/checkout@v3 + with: + repository: taikoxyz/taiko-geth + + - name: Set up Go + uses: actions/setup-go@v3 + with: + go-version: '1.20' + + - name: Lint + run: make lint + + - name: Test + env: + TAIKO_TEST: true + run: make test
diff --git ethereum/go-ethereum/.github/workflows/docker.yml taikoxyz/taiko-geth/.github/workflows/docker.yml new file mode 100644 index 0000000000000000000000000000000000000000..b8183c3e538c102f441e32b3f89806ec21c0cbc8 --- /dev/null +++ taikoxyz/taiko-geth/.github/workflows/docker.yml @@ -0,0 +1,47 @@ +name: "Push docker image to GCR" + +on: + push: + branches: [taiko] + tags: + - "v*" + +jobs: + push-docker-image: + runs-on: ubuntu-latest + + steps: + - name: Checkout + uses: actions/checkout@v2 + + - name: Login to GCR + uses: docker/login-action@v2 + with: + registry: gcr.io + username: _json_key + password: ${{ secrets.GCR_JSON_KEY }} + + - name: Set up QEMU + uses: docker/setup-qemu-action@v1 + + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v1 + + - name: Docker meta + id: meta + uses: docker/metadata-action@v4 + with: + images: | + gcr.io/evmchain/taiko-geth + tags: | + type=ref,event=branch + type=ref,event=pr + type=ref,event=tag + type=sha + - name: Build and push + uses: docker/build-push-action@v2 + with: + platforms: linux/amd64,linux/arm64 + push: true + tags: ${{ steps.meta.outputs.tags }} + labels: ${{ steps.meta.outputs.labels }}
diff --git ethereum/go-ethereum/.github/workflows/lint-pr.yml taikoxyz/taiko-geth/.github/workflows/lint-pr.yml new file mode 100644 index 0000000000000000000000000000000000000000..ce00cc6b1e4f71c72816be78d787197a0450419e --- /dev/null +++ taikoxyz/taiko-geth/.github/workflows/lint-pr.yml @@ -0,0 +1,14 @@ +name: "Lint PR" + +on: + pull_request: + types: [opened, edited, synchronize, reopened] + +jobs: + main: + name: Validate PR title + runs-on: ubuntu-latest + steps: + - uses: amannn/action-semantic-pull-request@v5 + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
diff --git ethereum/go-ethereum/.github/workflows/openai-review.yml taikoxyz/taiko-geth/.github/workflows/openai-review.yml new file mode 100644 index 0000000000000000000000000000000000000000..25d3c99cf7bdb1b8c74e1eb9fa6e97745fae885b --- /dev/null +++ taikoxyz/taiko-geth/.github/workflows/openai-review.yml @@ -0,0 +1,36 @@ +on: [pull_request] + +jobs: + add_pr_comment: + permissions: write-all + runs-on: ubuntu-latest + name: OpenAI PR Comment + if: "contains(github.event.pull_request.labels.*.name, 'option.review-by-ai')" + steps: + - uses: actions/checkout@v3 + with: + ref: ${{ github.event.pull_request.head.sha }} + fetch-depth: 2 + - id: patch + run: | + patch_output=$(curl --silent --request GET \ + --url https://api.github.com/repos/$PATCH_REPO/pulls/$PATCH_PR \ + --header "Accept: application/vnd.github.v3.patch" \ + --header "Authorization: Bearer $PATCH_GITHUB_TOKEN") + echo $patch_output + echo "GIT_PATCH_OUTPUT=$(echo $patch_output)" >> $GITHUB_ENV + env: + PATCH_GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + PATCH_PR: ${{ github.event.pull_request.number }} + PATCH_REPO: ${{ github.repository }} + - id: review + uses: taikoxyz/openai-review-action@main + with: + GIT_COMMIT_HASH: ${{ github.event.pull_request.head.sha }} + GIT_PATCH_OUTPUT: ${{ env.GIT_PATCH_OUTPUT }} + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }} + OPENAI_ORG_KEY: ${{ secrets.OPENAI_ORG_KEY }} + PR_NUMBER: ${{ github.event.pull_request.number }} + PR_TITLE: ${{ github.event.pull_request.title }} + REPOSITORY_NAME: ${{ github.repository }}
diff --git ethereum/go-ethereum/.gitignore taikoxyz/taiko-geth/.gitignore index e24e1d1677098fe7310f7adad5ecc8500236b44f..3f27cdc00f0746c28f7e79285a50425f435bd0ef 100644 --- ethereum/go-ethereum/.gitignore +++ taikoxyz/taiko-geth/.gitignore @@ -47,4 +47,6 @@ /dashboard/assets/bundle.js.map /dashboard/assets/package-lock.json   **/yarn-error.log -logs/ \ No newline at end of file +logs/ + +tests/spec-tests/
diff --git ethereum/go-ethereum/.travis.yml taikoxyz/taiko-geth/.travis.yml index 925e23b1a57f7555d882f4a8fbf2cb8c7d59ef0b..4f5d482c65142d38fc81ab6d1612eb0110cad90f 100644 --- ethereum/go-ethereum/.travis.yml +++ taikoxyz/taiko-geth/.travis.yml @@ -13,7 +13,7 @@ # This builder only tests code linters on latest version of Go - stage: lint os: linux dist: bionic - go: 1.20.x + go: 1.21.x env: - lint git: @@ -28,7 +28,7 @@ if: type = push os: linux arch: amd64 dist: bionic - go: 1.20.x + go: 1.21.x env: - docker services: @@ -45,7 +45,7 @@ if: type = push os: linux arch: arm64 dist: bionic - go: 1.20.x + go: 1.21.x env: - docker services: @@ -63,10 +63,9 @@ if: type = push os: linux dist: bionic sudo: required - go: 1.20.x + go: 1.21.x env: - azure-linux - - GO111MODULE=on git: submodules: false # avoid cloning ethereum/tests addons: @@ -97,10 +96,9 @@ # This builder does the OSX Azure uploads - stage: build if: type = push os: osx - go: 1.20.x + go: 1.21.x env: - azure-osx - - GO111MODULE=on git: submodules: false # avoid cloning ethereum/tests script: @@ -112,41 +110,34 @@ - stage: build os: linux arch: amd64 dist: bionic - go: 1.20.x - env: - - GO111MODULE=on + go: 1.21.x script: - - go run build/ci.go test $TEST_PACKAGES + - travis_wait 30 go run build/ci.go test $TEST_PACKAGES   - stage: build if: type = pull_request os: linux arch: arm64 dist: bionic - go: 1.19.x - env: - - GO111MODULE=on + go: 1.20.x script: - - go run build/ci.go test $TEST_PACKAGES + - travis_wait 30 go run build/ci.go test $TEST_PACKAGES   - stage: build os: linux dist: bionic - go: 1.19.x - env: - - GO111MODULE=on + go: 1.20.x script: - - go run build/ci.go test $TEST_PACKAGES + - travis_wait 30 go run build/ci.go test $TEST_PACKAGES   # This builder does the Ubuntu PPA nightly uploads - stage: build if: type = cron || (type = push && tag ~= /^v[0-9]/) os: linux dist: bionic - go: 1.20.x + go: 1.21.x env: - ubuntu-ppa - - GO111MODULE=on git: submodules: false # avoid cloning ethereum/tests addons: @@ -167,10 +158,9 @@ - stage: build if: type = cron os: linux dist: bionic - go: 1.20.x + go: 1.21.x env: - azure-purge - - GO111MODULE=on git: submodules: false # avoid cloning ethereum/tests script: @@ -181,9 +171,7 @@ - stage: build if: type = cron os: linux dist: bionic - go: 1.20.x - env: - - GO111MODULE=on + go: 1.21.x script: - - go run build/ci.go test -race $TEST_PACKAGES + - travis_wait 30 go run build/ci.go test -race $TEST_PACKAGES
diff --git ethereum/go-ethereum/Dockerfile taikoxyz/taiko-geth/Dockerfile index 1951fed8ef87d47d688eaf1543c220d177c78216..ed69a04789678e839186208e04a2483b33b4d68c 100644 --- ethereum/go-ethereum/Dockerfile +++ taikoxyz/taiko-geth/Dockerfile @@ -4,7 +4,7 @@ ARG VERSION="" ARG BUILDNUM=""   # Build Geth in a stock Go builder container -FROM golang:1.20-alpine as builder +FROM golang:1.21-alpine as builder   RUN apk add --no-cache gcc musl-dev linux-headers git
diff --git ethereum/go-ethereum/Makefile taikoxyz/taiko-geth/Makefile index e6286da7fbaea459a64024b87605d8b6ed6aff10..d736ef61c001ec02581a6867982291cdf684b3ab 100644 --- ethereum/go-ethereum/Makefile +++ taikoxyz/taiko-geth/Makefile @@ -6,7 +6,7 @@ .PHONY: geth android ios evm all test clean   GOBIN = ./build/bin GO ?= latest -GORUN = env GO111MODULE=on go run +GORUN = go run   geth: $(GORUN) build/ci.go install ./cmd/geth @@ -23,7 +23,7 @@ lint: ## Run linters. $(GORUN) build/ci.go lint   clean: - env GO111MODULE=on go clean -cache + go clean -cache rm -fr build/_workspace/pkg/ $(GOBIN)/*   # The devtools target installs tools required for 'go generate'.
diff --git ethereum/go-ethereum/README.md taikoxyz/taiko-geth/README.md index 77317090c17ef7315d12c2b61de6889c9daef620..b0d33edbc61965f205c3b4ed4aa2897f596193d4 100644 --- ethereum/go-ethereum/README.md +++ taikoxyz/taiko-geth/README.md @@ -1,3 +1,13 @@ +# taiko-geth + +[![CI](https://github.com/taikoxyz/taiko-geth/actions/workflows/ci.yml/badge.svg)](https://github.com/taikoxyz/taiko-geth/actions/workflows/ci.yml) + +The codebase is based on [go-ethereum v1.13.4](https://github.com/ethereum/go-ethereum/releases/tag/v1.13.4). + +## Tracing changes + +All source code changes by [taiko](https://taiko.xyz) team are commented with `"CHANGE(taiko): ...."`, and the filenames of all additional files have the prefix `"taiko_"` (`taiko_*.go`). + ## Go Ethereum   Official Golang execution layer implementation of the Ethereum protocol. @@ -83,7 +93,7 @@ * Start `geth` in snap sync mode (default, can be changed with the `--syncmode` flag), causing it to download more data in exchange for avoiding processing the entire history of the Ethereum network, which is very CPU intensive. * Start the built-in interactive [JavaScript console](https://geth.ethereum.org/docs/interacting-with-geth/javascript-console), - (via the trailing `console` subcommand) through which you can interact using [`web3` methods](https://github.com/ChainSafe/web3.js/blob/0.20.7/DOCUMENTATION.md) + (via the trailing `console` subcommand) through which you can interact using [`web3` methods](https://github.com/ChainSafe/web3.js/blob/0.20.7/DOCUMENTATION.md) (note: the `web3` version bundled within `geth` is very old, and not up to date with official docs), as well as `geth`'s own [management APIs](https://geth.ethereum.org/docs/interacting-with-geth/rpc). This tool is optional and if you leave it out you can always attach it to an already running @@ -344,7 +354,7 @@ ### Contributing to geth.ethereum.org   For contributions to the [go-ethereum website](https://geth.ethereum.org), please checkout and raise pull requests against the `website` branch. -For more detailed instructions please see the `website` branch [README](https://github.com/ethereum/go-ethereum/tree/website#readme) or the +For more detailed instructions please see the `website` branch [README](https://github.com/ethereum/go-ethereum/tree/website#readme) or the [contributing](https://geth.ethereum.org/docs/developers/geth-developer/contributing) page of the website.   ## License
diff --git ethereum/go-ethereum/beacon/engine/gen_blockmetadata.go taikoxyz/taiko-geth/beacon/engine/gen_blockmetadata.go new file mode 100644 index 0000000000000000000000000000000000000000..3b0edb54939aa6fc11ea8462a53c971c83cd8c46 --- /dev/null +++ taikoxyz/taiko-geth/beacon/engine/gen_blockmetadata.go @@ -0,0 +1,82 @@ +// Code generated by github.com/fjl/gencodec. DO NOT EDIT. + +package engine + +import ( + "encoding/json" + "errors" + "math/big" + + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/common/hexutil" +) + +var _ = (*blockMetadataMarshaling)(nil) + +// MarshalJSON marshals as JSON. +func (b BlockMetadata) MarshalJSON() ([]byte, error) { + type BlockMetadata struct { + Beneficiary common.Address `json:"beneficiary" gencodec:"required"` + GasLimit uint64 `json:"gasLimit" gencodec:"required"` + Timestamp hexutil.Uint64 `json:"timestamp" gencodec:"required"` + MixHash common.Hash `json:"mixHash" gencodec:"required"` + TxList hexutil.Bytes `json:"txList" gencodec:"required"` + HighestBlockID *big.Int `json:"highestBlockID" gencodec:"required"` + ExtraData []byte `json:"extraData" gencodec:"required"` + } + var enc BlockMetadata + enc.Beneficiary = b.Beneficiary + enc.GasLimit = b.GasLimit + enc.Timestamp = hexutil.Uint64(b.Timestamp) + enc.MixHash = b.MixHash + enc.TxList = b.TxList + enc.HighestBlockID = b.HighestBlockID + enc.ExtraData = b.ExtraData + return json.Marshal(&enc) +} + +// UnmarshalJSON unmarshals from JSON. +func (b *BlockMetadata) UnmarshalJSON(input []byte) error { + type BlockMetadata struct { + Beneficiary *common.Address `json:"beneficiary" gencodec:"required"` + GasLimit *uint64 `json:"gasLimit" gencodec:"required"` + Timestamp *hexutil.Uint64 `json:"timestamp" gencodec:"required"` + MixHash *common.Hash `json:"mixHash" gencodec:"required"` + TxList *hexutil.Bytes `json:"txList" gencodec:"required"` + HighestBlockID *big.Int `json:"highestBlockID" gencodec:"required"` + ExtraData []byte `json:"extraData" gencodec:"required"` + } + var dec BlockMetadata + if err := json.Unmarshal(input, &dec); err != nil { + return err + } + if dec.Beneficiary == nil { + return errors.New("missing required field 'beneficiary' for BlockMetadata") + } + b.Beneficiary = *dec.Beneficiary + if dec.GasLimit == nil { + return errors.New("missing required field 'gasLimit' for BlockMetadata") + } + b.GasLimit = *dec.GasLimit + if dec.Timestamp == nil { + return errors.New("missing required field 'timestamp' for BlockMetadata") + } + b.Timestamp = uint64(*dec.Timestamp) + if dec.MixHash == nil { + return errors.New("missing required field 'mixHash' for BlockMetadata") + } + b.MixHash = *dec.MixHash + if dec.TxList == nil { + return errors.New("missing required field 'txList' for BlockMetadata") + } + b.TxList = *dec.TxList + if dec.HighestBlockID == nil { + return errors.New("missing required field 'highestBlockID' for BlockMetadata") + } + b.HighestBlockID = dec.HighestBlockID + if dec.ExtraData == nil { + return errors.New("missing required field 'extraData' for BlockMetadata") + } + b.ExtraData = dec.ExtraData + return nil +}
diff --git ethereum/go-ethereum/beacon/engine/gen_blockparams.go taikoxyz/taiko-geth/beacon/engine/gen_blockparams.go index 0dd2b52597ad5ddc7fc46d97c6c8878edf29d471..e2ac09feef9b6ad8385b974c784377d565bef381 100644 --- ethereum/go-ethereum/beacon/engine/gen_blockparams.go +++ taikoxyz/taiko-geth/beacon/engine/gen_blockparams.go @@ -5,9 +5,11 @@ import ( "encoding/json" "errors" + "math/big"   "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common/hexutil" + "github.com/ethereum/go-ethereum/core/rawdb" "github.com/ethereum/go-ethereum/core/types" )   @@ -20,12 +22,20 @@ Timestamp hexutil.Uint64 `json:"timestamp" gencodec:"required"` Random common.Hash `json:"prevRandao" gencodec:"required"` SuggestedFeeRecipient common.Address `json:"suggestedFeeRecipient" gencodec:"required"` Withdrawals []*types.Withdrawal `json:"withdrawals"` + BeaconRoot *common.Hash `json:"parentBeaconBlockRoot"` + BaseFeePerGas *big.Int `json:"baseFeePerGas" gencodec:"required"` + BlockMetadata *BlockMetadata `json:"blockMetadata" gencodec:"required"` + L1Origin *rawdb.L1Origin `json:"l1Origin" gencodec:"required"` } var enc PayloadAttributes enc.Timestamp = hexutil.Uint64(p.Timestamp) enc.Random = p.Random enc.SuggestedFeeRecipient = p.SuggestedFeeRecipient enc.Withdrawals = p.Withdrawals + enc.BeaconRoot = p.BeaconRoot + enc.BaseFeePerGas = p.BaseFeePerGas + enc.BlockMetadata = p.BlockMetadata + enc.L1Origin = p.L1Origin return json.Marshal(&enc) }   @@ -36,6 +46,10 @@ Timestamp *hexutil.Uint64 `json:"timestamp" gencodec:"required"` Random *common.Hash `json:"prevRandao" gencodec:"required"` SuggestedFeeRecipient *common.Address `json:"suggestedFeeRecipient" gencodec:"required"` Withdrawals []*types.Withdrawal `json:"withdrawals"` + BeaconRoot *common.Hash `json:"parentBeaconBlockRoot"` + BaseFeePerGas *big.Int `json:"baseFeePerGas" gencodec:"required"` + BlockMetadata *BlockMetadata `json:"blockMetadata" gencodec:"required"` + L1Origin *rawdb.L1Origin `json:"l1Origin" gencodec:"required"` } var dec PayloadAttributes if err := json.Unmarshal(input, &dec); err != nil { @@ -56,5 +70,20 @@ p.SuggestedFeeRecipient = *dec.SuggestedFeeRecipient if dec.Withdrawals != nil { p.Withdrawals = dec.Withdrawals } + if dec.BeaconRoot != nil { + p.BeaconRoot = dec.BeaconRoot + } + if dec.BaseFeePerGas == nil { + return errors.New("missing required field 'baseFeePerGas' for PayloadAttributes") + } + p.BaseFeePerGas = dec.BaseFeePerGas + if dec.BlockMetadata == nil { + return errors.New("missing required field 'blockMetadata' for PayloadAttributes") + } + p.BlockMetadata = dec.BlockMetadata + if dec.L1Origin == nil { + return errors.New("missing required field 'l1Origin' for PayloadAttributes") + } + p.L1Origin = dec.L1Origin return nil }
diff --git ethereum/go-ethereum/beacon/engine/gen_ed.go taikoxyz/taiko-geth/beacon/engine/gen_ed.go index 6893d64a1626a8e172a80865a5ccec6e4e0f53f6..b3ea4ad2a70d53938b551c2efd01fddb032a9e9d 100644 --- ethereum/go-ethereum/beacon/engine/gen_ed.go +++ taikoxyz/taiko-geth/beacon/engine/gen_ed.go @@ -17,23 +17,26 @@ // MarshalJSON marshals as JSON. func (e ExecutableData) MarshalJSON() ([]byte, error) { type ExecutableData struct { - ParentHash common.Hash `json:"parentHash" gencodec:"required"` - FeeRecipient common.Address `json:"feeRecipient" gencodec:"required"` - StateRoot common.Hash `json:"stateRoot" gencodec:"required"` - ReceiptsRoot common.Hash `json:"receiptsRoot" gencodec:"required"` - LogsBloom hexutil.Bytes `json:"logsBloom" gencodec:"required"` - Random common.Hash `json:"prevRandao" gencodec:"required"` - Number hexutil.Uint64 `json:"blockNumber" gencodec:"required"` - GasLimit hexutil.Uint64 `json:"gasLimit" gencodec:"required"` - GasUsed hexutil.Uint64 `json:"gasUsed" gencodec:"required"` - Timestamp hexutil.Uint64 `json:"timestamp" gencodec:"required"` - ExtraData hexutil.Bytes `json:"extraData" gencodec:"required"` - BaseFeePerGas *hexutil.Big `json:"baseFeePerGas" gencodec:"required"` - BlockHash common.Hash `json:"blockHash" gencodec:"required"` - Transactions []hexutil.Bytes `json:"transactions" gencodec:"required"` - Withdrawals []*types.Withdrawal `json:"withdrawals"` - BlobGasUsed *hexutil.Uint64 `json:"blobGasUsed"` - ExcessBlobGas *hexutil.Uint64 `json:"excessBlobGas"` + ParentHash common.Hash `json:"parentHash" gencodec:"required"` + FeeRecipient common.Address `json:"feeRecipient" gencodec:"required"` + StateRoot common.Hash `json:"stateRoot" gencodec:"required"` + ReceiptsRoot common.Hash `json:"receiptsRoot" gencodec:"required"` + LogsBloom hexutil.Bytes `json:"logsBloom" gencodec:"required"` + Random common.Hash `json:"prevRandao" gencodec:"required"` + Number hexutil.Uint64 `json:"blockNumber" gencodec:"required"` + GasLimit hexutil.Uint64 `json:"gasLimit" gencodec:"required"` + GasUsed hexutil.Uint64 `json:"gasUsed" gencodec:"required"` + Timestamp hexutil.Uint64 `json:"timestamp" gencodec:"required"` + ExtraData hexutil.Bytes `json:"extraData" gencodec:"required"` + BaseFeePerGas *hexutil.Big `json:"baseFeePerGas" gencodec:"required"` + BlockHash common.Hash `json:"blockHash" gencodec:"required"` + Transactions []hexutil.Bytes `json:"transactions"` + Withdrawals []*types.Withdrawal `json:"withdrawals"` + BlobGasUsed *hexutil.Uint64 `json:"blobGasUsed"` + ExcessBlobGas *hexutil.Uint64 `json:"excessBlobGas"` + TxHash common.Hash `json:"txHash"` + WithdrawalsHash common.Hash `json:"withdrawalsHash"` + TaikoBlock bool } var enc ExecutableData enc.ParentHash = e.ParentHash @@ -58,29 +61,35 @@ } enc.Withdrawals = e.Withdrawals enc.BlobGasUsed = (*hexutil.Uint64)(e.BlobGasUsed) enc.ExcessBlobGas = (*hexutil.Uint64)(e.ExcessBlobGas) + enc.TxHash = e.TxHash + enc.WithdrawalsHash = e.WithdrawalsHash + enc.TaikoBlock = e.TaikoBlock return json.Marshal(&enc) }   // UnmarshalJSON unmarshals from JSON. func (e *ExecutableData) UnmarshalJSON(input []byte) error { type ExecutableData struct { - ParentHash *common.Hash `json:"parentHash" gencodec:"required"` - FeeRecipient *common.Address `json:"feeRecipient" gencodec:"required"` - StateRoot *common.Hash `json:"stateRoot" gencodec:"required"` - ReceiptsRoot *common.Hash `json:"receiptsRoot" gencodec:"required"` - LogsBloom *hexutil.Bytes `json:"logsBloom" gencodec:"required"` - Random *common.Hash `json:"prevRandao" gencodec:"required"` - Number *hexutil.Uint64 `json:"blockNumber" gencodec:"required"` - GasLimit *hexutil.Uint64 `json:"gasLimit" gencodec:"required"` - GasUsed *hexutil.Uint64 `json:"gasUsed" gencodec:"required"` - Timestamp *hexutil.Uint64 `json:"timestamp" gencodec:"required"` - ExtraData *hexutil.Bytes `json:"extraData" gencodec:"required"` - BaseFeePerGas *hexutil.Big `json:"baseFeePerGas" gencodec:"required"` - BlockHash *common.Hash `json:"blockHash" gencodec:"required"` - Transactions []hexutil.Bytes `json:"transactions" gencodec:"required"` - Withdrawals []*types.Withdrawal `json:"withdrawals"` - BlobGasUsed *hexutil.Uint64 `json:"blobGasUsed"` - ExcessBlobGas *hexutil.Uint64 `json:"excessBlobGas"` + ParentHash *common.Hash `json:"parentHash" gencodec:"required"` + FeeRecipient *common.Address `json:"feeRecipient" gencodec:"required"` + StateRoot *common.Hash `json:"stateRoot" gencodec:"required"` + ReceiptsRoot *common.Hash `json:"receiptsRoot" gencodec:"required"` + LogsBloom *hexutil.Bytes `json:"logsBloom" gencodec:"required"` + Random *common.Hash `json:"prevRandao" gencodec:"required"` + Number *hexutil.Uint64 `json:"blockNumber" gencodec:"required"` + GasLimit *hexutil.Uint64 `json:"gasLimit" gencodec:"required"` + GasUsed *hexutil.Uint64 `json:"gasUsed" gencodec:"required"` + Timestamp *hexutil.Uint64 `json:"timestamp" gencodec:"required"` + ExtraData *hexutil.Bytes `json:"extraData" gencodec:"required"` + BaseFeePerGas *hexutil.Big `json:"baseFeePerGas" gencodec:"required"` + BlockHash *common.Hash `json:"blockHash" gencodec:"required"` + Transactions []hexutil.Bytes `json:"transactions"` + Withdrawals []*types.Withdrawal `json:"withdrawals"` + BlobGasUsed *hexutil.Uint64 `json:"blobGasUsed"` + ExcessBlobGas *hexutil.Uint64 `json:"excessBlobGas"` + TxHash *common.Hash `json:"txHash"` + WithdrawalsHash *common.Hash `json:"withdrawalsHash"` + TaikoBlock *bool } var dec ExecutableData if err := json.Unmarshal(input, &dec); err != nil { @@ -138,12 +147,11 @@ if dec.BlockHash == nil { return errors.New("missing required field 'blockHash' for ExecutableData") } e.BlockHash = *dec.BlockHash - if dec.Transactions == nil { - return errors.New("missing required field 'transactions' for ExecutableData") - } - e.Transactions = make([][]byte, len(dec.Transactions)) - for k, v := range dec.Transactions { - e.Transactions[k] = v + if dec.Transactions != nil { + e.Transactions = make([][]byte, len(dec.Transactions)) + for k, v := range dec.Transactions { + e.Transactions[k] = v + } } if dec.Withdrawals != nil { e.Withdrawals = dec.Withdrawals @@ -153,6 +161,15 @@ e.BlobGasUsed = (*uint64)(dec.BlobGasUsed) } if dec.ExcessBlobGas != nil { e.ExcessBlobGas = (*uint64)(dec.ExcessBlobGas) + } + if dec.TxHash != nil { + e.TxHash = *dec.TxHash + } + if dec.WithdrawalsHash != nil { + e.WithdrawalsHash = *dec.WithdrawalsHash + } + if dec.TaikoBlock != nil { + e.TaikoBlock = *dec.TaikoBlock } return nil }
diff --git ethereum/go-ethereum/beacon/engine/gen_epe.go taikoxyz/taiko-geth/beacon/engine/gen_epe.go index 664a50fc5b299f6da84ec1c5f85ed44696862388..e69f9a5951a28deeaa9ad51f1b2d9e8733b2feca 100644 --- ethereum/go-ethereum/beacon/engine/gen_epe.go +++ taikoxyz/taiko-geth/beacon/engine/gen_epe.go @@ -18,11 +18,13 @@ type ExecutionPayloadEnvelope struct { ExecutionPayload *ExecutableData `json:"executionPayload" gencodec:"required"` BlockValue *hexutil.Big `json:"blockValue" gencodec:"required"` BlobsBundle *BlobsBundleV1 `json:"blobsBundle"` + Override bool `json:"shouldOverrideBuilder"` } var enc ExecutionPayloadEnvelope enc.ExecutionPayload = e.ExecutionPayload enc.BlockValue = (*hexutil.Big)(e.BlockValue) enc.BlobsBundle = e.BlobsBundle + enc.Override = e.Override return json.Marshal(&enc) }   @@ -32,6 +34,7 @@ type ExecutionPayloadEnvelope struct { ExecutionPayload *ExecutableData `json:"executionPayload" gencodec:"required"` BlockValue *hexutil.Big `json:"blockValue" gencodec:"required"` BlobsBundle *BlobsBundleV1 `json:"blobsBundle"` + Override *bool `json:"shouldOverrideBuilder"` } var dec ExecutionPayloadEnvelope if err := json.Unmarshal(input, &dec); err != nil { @@ -47,6 +50,9 @@ } e.BlockValue = (*big.Int)(dec.BlockValue) if dec.BlobsBundle != nil { e.BlobsBundle = dec.BlobsBundle + } + if dec.Override != nil { + e.Override = *dec.Override } return nil }
diff --git ethereum/go-ethereum/cmd/evm/internal/t8ntool/gen_header.go taikoxyz/taiko-geth/cmd/evm/internal/t8ntool/gen_header.go index 76228394dc1df033183f9de9ddd35095761140f4..a8c8668978ed9cdc1e120dece0f0b2dd72058d0a 100644 --- ethereum/go-ethereum/cmd/evm/internal/t8ntool/gen_header.go +++ taikoxyz/taiko-geth/cmd/evm/internal/t8ntool/gen_header.go @@ -18,23 +18,26 @@ // MarshalJSON marshals as JSON. func (h header) MarshalJSON() ([]byte, error) { type header struct { - ParentHash common.Hash `json:"parentHash"` - OmmerHash *common.Hash `json:"sha3Uncles"` - Coinbase *common.Address `json:"miner"` - Root common.Hash `json:"stateRoot" gencodec:"required"` - TxHash *common.Hash `json:"transactionsRoot"` - ReceiptHash *common.Hash `json:"receiptsRoot"` - Bloom types.Bloom `json:"logsBloom"` - Difficulty *math.HexOrDecimal256 `json:"difficulty"` - Number *math.HexOrDecimal256 `json:"number" gencodec:"required"` - GasLimit math.HexOrDecimal64 `json:"gasLimit" gencodec:"required"` - GasUsed math.HexOrDecimal64 `json:"gasUsed"` - Time math.HexOrDecimal64 `json:"timestamp" gencodec:"required"` - Extra hexutil.Bytes `json:"extraData"` - MixDigest common.Hash `json:"mixHash"` - Nonce *types.BlockNonce `json:"nonce"` - BaseFee *math.HexOrDecimal256 `json:"baseFeePerGas" rlp:"optional"` - WithdrawalsHash *common.Hash `json:"withdrawalsRoot" rlp:"optional"` + ParentHash common.Hash `json:"parentHash"` + OmmerHash *common.Hash `json:"sha3Uncles"` + Coinbase *common.Address `json:"miner"` + Root common.Hash `json:"stateRoot" gencodec:"required"` + TxHash *common.Hash `json:"transactionsRoot"` + ReceiptHash *common.Hash `json:"receiptsRoot"` + Bloom types.Bloom `json:"logsBloom"` + Difficulty *math.HexOrDecimal256 `json:"difficulty"` + Number *math.HexOrDecimal256 `json:"number" gencodec:"required"` + GasLimit math.HexOrDecimal64 `json:"gasLimit" gencodec:"required"` + GasUsed math.HexOrDecimal64 `json:"gasUsed"` + Time math.HexOrDecimal64 `json:"timestamp" gencodec:"required"` + Extra hexutil.Bytes `json:"extraData"` + MixDigest common.Hash `json:"mixHash"` + Nonce *types.BlockNonce `json:"nonce"` + BaseFee *math.HexOrDecimal256 `json:"baseFeePerGas" rlp:"optional"` + WithdrawalsHash *common.Hash `json:"withdrawalsRoot" rlp:"optional"` + BlobGasUsed *math.HexOrDecimal64 `json:"blobGasUsed" rlp:"optional"` + ExcessBlobGas *math.HexOrDecimal64 `json:"excessBlobGas" rlp:"optional"` + ParentBeaconBlockRoot *common.Hash `json:"parentBeaconBlockRoot" rlp:"optional"` } var enc header enc.ParentHash = h.ParentHash @@ -54,29 +57,35 @@ enc.MixDigest = h.MixDigest enc.Nonce = h.Nonce enc.BaseFee = (*math.HexOrDecimal256)(h.BaseFee) enc.WithdrawalsHash = h.WithdrawalsHash + enc.BlobGasUsed = (*math.HexOrDecimal64)(h.BlobGasUsed) + enc.ExcessBlobGas = (*math.HexOrDecimal64)(h.ExcessBlobGas) + enc.ParentBeaconBlockRoot = h.ParentBeaconBlockRoot return json.Marshal(&enc) }   // UnmarshalJSON unmarshals from JSON. func (h *header) UnmarshalJSON(input []byte) error { type header struct { - ParentHash *common.Hash `json:"parentHash"` - OmmerHash *common.Hash `json:"sha3Uncles"` - Coinbase *common.Address `json:"miner"` - Root *common.Hash `json:"stateRoot" gencodec:"required"` - TxHash *common.Hash `json:"transactionsRoot"` - ReceiptHash *common.Hash `json:"receiptsRoot"` - Bloom *types.Bloom `json:"logsBloom"` - Difficulty *math.HexOrDecimal256 `json:"difficulty"` - Number *math.HexOrDecimal256 `json:"number" gencodec:"required"` - GasLimit *math.HexOrDecimal64 `json:"gasLimit" gencodec:"required"` - GasUsed *math.HexOrDecimal64 `json:"gasUsed"` - Time *math.HexOrDecimal64 `json:"timestamp" gencodec:"required"` - Extra *hexutil.Bytes `json:"extraData"` - MixDigest *common.Hash `json:"mixHash"` - Nonce *types.BlockNonce `json:"nonce"` - BaseFee *math.HexOrDecimal256 `json:"baseFeePerGas" rlp:"optional"` - WithdrawalsHash *common.Hash `json:"withdrawalsRoot" rlp:"optional"` + ParentHash *common.Hash `json:"parentHash"` + OmmerHash *common.Hash `json:"sha3Uncles"` + Coinbase *common.Address `json:"miner"` + Root *common.Hash `json:"stateRoot" gencodec:"required"` + TxHash *common.Hash `json:"transactionsRoot"` + ReceiptHash *common.Hash `json:"receiptsRoot"` + Bloom *types.Bloom `json:"logsBloom"` + Difficulty *math.HexOrDecimal256 `json:"difficulty"` + Number *math.HexOrDecimal256 `json:"number" gencodec:"required"` + GasLimit *math.HexOrDecimal64 `json:"gasLimit" gencodec:"required"` + GasUsed *math.HexOrDecimal64 `json:"gasUsed"` + Time *math.HexOrDecimal64 `json:"timestamp" gencodec:"required"` + Extra *hexutil.Bytes `json:"extraData"` + MixDigest *common.Hash `json:"mixHash"` + Nonce *types.BlockNonce `json:"nonce"` + BaseFee *math.HexOrDecimal256 `json:"baseFeePerGas" rlp:"optional"` + WithdrawalsHash *common.Hash `json:"withdrawalsRoot" rlp:"optional"` + BlobGasUsed *math.HexOrDecimal64 `json:"blobGasUsed" rlp:"optional"` + ExcessBlobGas *math.HexOrDecimal64 `json:"excessBlobGas" rlp:"optional"` + ParentBeaconBlockRoot *common.Hash `json:"parentBeaconBlockRoot" rlp:"optional"` } var dec header if err := json.Unmarshal(input, &dec); err != nil { @@ -136,6 +145,15 @@ h.BaseFee = (*big.Int)(dec.BaseFee) } if dec.WithdrawalsHash != nil { h.WithdrawalsHash = dec.WithdrawalsHash + } + if dec.BlobGasUsed != nil { + h.BlobGasUsed = (*uint64)(dec.BlobGasUsed) + } + if dec.ExcessBlobGas != nil { + h.ExcessBlobGas = (*uint64)(dec.ExcessBlobGas) + } + if dec.ParentBeaconBlockRoot != nil { + h.ParentBeaconBlockRoot = dec.ParentBeaconBlockRoot } return nil }
diff --git ethereum/go-ethereum/cmd/evm/internal/t8ntool/gen_stenv.go taikoxyz/taiko-geth/cmd/evm/internal/t8ntool/gen_stenv.go index f50fee5e31c317eae5c5994d09e7473f9a2c4f8d..d47db4a8765ee3b14ba478506b79bf0a4ff9ecc0 100644 --- ethereum/go-ethereum/cmd/evm/internal/t8ntool/gen_stenv.go +++ taikoxyz/taiko-geth/cmd/evm/internal/t8ntool/gen_stenv.go @@ -17,25 +17,26 @@ // MarshalJSON marshals as JSON. func (s stEnv) MarshalJSON() ([]byte, error) { type stEnv struct { - Coinbase common.UnprefixedAddress `json:"currentCoinbase" gencodec:"required"` - Difficulty *math.HexOrDecimal256 `json:"currentDifficulty"` - Random *math.HexOrDecimal256 `json:"currentRandom"` - ParentDifficulty *math.HexOrDecimal256 `json:"parentDifficulty"` - ParentBaseFee *math.HexOrDecimal256 `json:"parentBaseFee,omitempty"` - ParentGasUsed math.HexOrDecimal64 `json:"parentGasUsed,omitempty"` - ParentGasLimit math.HexOrDecimal64 `json:"parentGasLimit,omitempty"` - GasLimit math.HexOrDecimal64 `json:"currentGasLimit" gencodec:"required"` - Number math.HexOrDecimal64 `json:"currentNumber" gencodec:"required"` - Timestamp math.HexOrDecimal64 `json:"currentTimestamp" gencodec:"required"` - ParentTimestamp math.HexOrDecimal64 `json:"parentTimestamp,omitempty"` - BlockHashes map[math.HexOrDecimal64]common.Hash `json:"blockHashes,omitempty"` - Ommers []ommer `json:"ommers,omitempty"` - Withdrawals []*types.Withdrawal `json:"withdrawals,omitempty"` - BaseFee *math.HexOrDecimal256 `json:"currentBaseFee,omitempty"` - ParentUncleHash common.Hash `json:"parentUncleHash"` - ExcessBlobGas *math.HexOrDecimal64 `json:"excessBlobGas,omitempty"` - ParentExcessBlobGas *math.HexOrDecimal64 `json:"parentExcessBlobGas,omitempty"` - ParentBlobGasUsed *math.HexOrDecimal64 `json:"parentBlobGasUsed,omitempty"` + Coinbase common.UnprefixedAddress `json:"currentCoinbase" gencodec:"required"` + Difficulty *math.HexOrDecimal256 `json:"currentDifficulty"` + Random *math.HexOrDecimal256 `json:"currentRandom"` + ParentDifficulty *math.HexOrDecimal256 `json:"parentDifficulty"` + ParentBaseFee *math.HexOrDecimal256 `json:"parentBaseFee,omitempty"` + ParentGasUsed math.HexOrDecimal64 `json:"parentGasUsed,omitempty"` + ParentGasLimit math.HexOrDecimal64 `json:"parentGasLimit,omitempty"` + GasLimit math.HexOrDecimal64 `json:"currentGasLimit" gencodec:"required"` + Number math.HexOrDecimal64 `json:"currentNumber" gencodec:"required"` + Timestamp math.HexOrDecimal64 `json:"currentTimestamp" gencodec:"required"` + ParentTimestamp math.HexOrDecimal64 `json:"parentTimestamp,omitempty"` + BlockHashes map[math.HexOrDecimal64]common.Hash `json:"blockHashes,omitempty"` + Ommers []ommer `json:"ommers,omitempty"` + Withdrawals []*types.Withdrawal `json:"withdrawals,omitempty"` + BaseFee *math.HexOrDecimal256 `json:"currentBaseFee,omitempty"` + ParentUncleHash common.Hash `json:"parentUncleHash"` + ExcessBlobGas *math.HexOrDecimal64 `json:"currentExcessBlobGas,omitempty"` + ParentExcessBlobGas *math.HexOrDecimal64 `json:"parentExcessBlobGas,omitempty"` + ParentBlobGasUsed *math.HexOrDecimal64 `json:"parentBlobGasUsed,omitempty"` + ParentBeaconBlockRoot *common.Hash `json:"parentBeaconBlockRoot"` } var enc stEnv enc.Coinbase = common.UnprefixedAddress(s.Coinbase) @@ -57,31 +58,33 @@ enc.ParentUncleHash = s.ParentUncleHash enc.ExcessBlobGas = (*math.HexOrDecimal64)(s.ExcessBlobGas) enc.ParentExcessBlobGas = (*math.HexOrDecimal64)(s.ParentExcessBlobGas) enc.ParentBlobGasUsed = (*math.HexOrDecimal64)(s.ParentBlobGasUsed) + enc.ParentBeaconBlockRoot = s.ParentBeaconBlockRoot return json.Marshal(&enc) }   // UnmarshalJSON unmarshals from JSON. func (s *stEnv) UnmarshalJSON(input []byte) error { type stEnv struct { - Coinbase *common.UnprefixedAddress `json:"currentCoinbase" gencodec:"required"` - Difficulty *math.HexOrDecimal256 `json:"currentDifficulty"` - Random *math.HexOrDecimal256 `json:"currentRandom"` - ParentDifficulty *math.HexOrDecimal256 `json:"parentDifficulty"` - ParentBaseFee *math.HexOrDecimal256 `json:"parentBaseFee,omitempty"` - ParentGasUsed *math.HexOrDecimal64 `json:"parentGasUsed,omitempty"` - ParentGasLimit *math.HexOrDecimal64 `json:"parentGasLimit,omitempty"` - GasLimit *math.HexOrDecimal64 `json:"currentGasLimit" gencodec:"required"` - Number *math.HexOrDecimal64 `json:"currentNumber" gencodec:"required"` - Timestamp *math.HexOrDecimal64 `json:"currentTimestamp" gencodec:"required"` - ParentTimestamp *math.HexOrDecimal64 `json:"parentTimestamp,omitempty"` - BlockHashes map[math.HexOrDecimal64]common.Hash `json:"blockHashes,omitempty"` - Ommers []ommer `json:"ommers,omitempty"` - Withdrawals []*types.Withdrawal `json:"withdrawals,omitempty"` - BaseFee *math.HexOrDecimal256 `json:"currentBaseFee,omitempty"` - ParentUncleHash *common.Hash `json:"parentUncleHash"` - ExcessBlobGas *math.HexOrDecimal64 `json:"excessBlobGas,omitempty"` - ParentExcessBlobGas *math.HexOrDecimal64 `json:"parentExcessBlobGas,omitempty"` - ParentBlobGasUsed *math.HexOrDecimal64 `json:"parentBlobGasUsed,omitempty"` + Coinbase *common.UnprefixedAddress `json:"currentCoinbase" gencodec:"required"` + Difficulty *math.HexOrDecimal256 `json:"currentDifficulty"` + Random *math.HexOrDecimal256 `json:"currentRandom"` + ParentDifficulty *math.HexOrDecimal256 `json:"parentDifficulty"` + ParentBaseFee *math.HexOrDecimal256 `json:"parentBaseFee,omitempty"` + ParentGasUsed *math.HexOrDecimal64 `json:"parentGasUsed,omitempty"` + ParentGasLimit *math.HexOrDecimal64 `json:"parentGasLimit,omitempty"` + GasLimit *math.HexOrDecimal64 `json:"currentGasLimit" gencodec:"required"` + Number *math.HexOrDecimal64 `json:"currentNumber" gencodec:"required"` + Timestamp *math.HexOrDecimal64 `json:"currentTimestamp" gencodec:"required"` + ParentTimestamp *math.HexOrDecimal64 `json:"parentTimestamp,omitempty"` + BlockHashes map[math.HexOrDecimal64]common.Hash `json:"blockHashes,omitempty"` + Ommers []ommer `json:"ommers,omitempty"` + Withdrawals []*types.Withdrawal `json:"withdrawals,omitempty"` + BaseFee *math.HexOrDecimal256 `json:"currentBaseFee,omitempty"` + ParentUncleHash *common.Hash `json:"parentUncleHash"` + ExcessBlobGas *math.HexOrDecimal64 `json:"currentExcessBlobGas,omitempty"` + ParentExcessBlobGas *math.HexOrDecimal64 `json:"parentExcessBlobGas,omitempty"` + ParentBlobGasUsed *math.HexOrDecimal64 `json:"parentBlobGasUsed,omitempty"` + ParentBeaconBlockRoot *common.Hash `json:"parentBeaconBlockRoot"` } var dec stEnv if err := json.Unmarshal(input, &dec); err != nil { @@ -147,6 +150,9 @@ s.ParentExcessBlobGas = (*uint64)(dec.ParentExcessBlobGas) } if dec.ParentBlobGasUsed != nil { s.ParentBlobGasUsed = (*uint64)(dec.ParentBlobGasUsed) + } + if dec.ParentBeaconBlockRoot != nil { + s.ParentBeaconBlockRoot = dec.ParentBeaconBlockRoot } return nil }
diff --git ethereum/go-ethereum/cmd/evm/testdata/28/env.json taikoxyz/taiko-geth/cmd/evm/testdata/28/env.json index 83c12dcfc3b456cb71fb7bb442e202a570ba5d0f..82f22ac62f4c42f6439c670a64385299c894b194 100644 --- ethereum/go-ethereum/cmd/evm/testdata/28/env.json +++ taikoxyz/taiko-geth/cmd/evm/testdata/28/env.json @@ -9,8 +9,7 @@ "parentTimestamp" : "0x03b6", "parentDifficulty" : "0x00", "parentUncleHash" : "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347", "currentRandom" : "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", - "withdrawals" : [ - ], + "withdrawals" : [], "parentBaseFee" : "0x0a", "parentGasUsed" : "0x00", "parentGasLimit" : "0x7fffffffffffffff", @@ -18,5 +17,6 @@ "parentExcessBlobGas" : "0x00", "parentBlobGasUsed" : "0x00", "blockHashes" : { "0" : "0x3a9b485972e7353edd9152712492f0c58d89ef80623686b6bf947a4a6dce6cb6" - } -} \ No newline at end of file + }, + "parentBeaconBlockRoot": "0x0000beac00beac00beac00beac00beac00beac00beac00beac00beac00beac00" +}
diff --git ethereum/go-ethereum/cmd/evm/testdata/28/exp.json taikoxyz/taiko-geth/cmd/evm/testdata/28/exp.json index a55ce0aec431d18ab5d42c413a7696ed4e089b2e..75c715e9722319c7d7cedf9cf24e6c41fe883ba6 100644 --- ethereum/go-ethereum/cmd/evm/testdata/28/exp.json +++ taikoxyz/taiko-geth/cmd/evm/testdata/28/exp.json @@ -42,6 +42,6 @@ "gasUsed": "0xa865", "currentBaseFee": "0x9", "withdrawalsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", "currentExcessBlobGas": "0x0", - "currentBlobGasUsed": "0x20000" + "blobGasUsed": "0x20000" } -} \ No newline at end of file +}
diff --git ethereum/go-ethereum/cmd/evm/testdata/29/alloc.json taikoxyz/taiko-geth/cmd/evm/testdata/29/alloc.json new file mode 100644 index 0000000000000000000000000000000000000000..d2c879a45c87f88d6edda3f35050adfeba718756 --- /dev/null +++ taikoxyz/taiko-geth/cmd/evm/testdata/29/alloc.json @@ -0,0 +1,16 @@ +{ + "0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b" : { + "balance" : "0x016345785d8a0000", + "code" : "0x", + "nonce" : "0x00", + "storage" : { + } + }, + "0x000F3df6D732807Ef1319fB7B8bB8522d0Beac02" : { + "balance" : "0x1", + "code" : "0x3373fffffffffffffffffffffffffffffffffffffffe14604457602036146024575f5ffd5b620180005f350680545f35146037575f5ffd5b6201800001545f5260205ff35b6201800042064281555f359062018000015500", + "nonce" : "0x00", + "storage" : { + } + } +} \ No newline at end of file
diff --git ethereum/go-ethereum/cmd/evm/testdata/29/env.json taikoxyz/taiko-geth/cmd/evm/testdata/29/env.json new file mode 100644 index 0000000000000000000000000000000000000000..e752a909ad3ff85e3ae385042a9d2c086fa579e5 --- /dev/null +++ taikoxyz/taiko-geth/cmd/evm/testdata/29/env.json @@ -0,0 +1,20 @@ +{ + "currentCoinbase" : "0x2adc25665018aa1fe0e6bc666dac8fc2697ff9ba", + "currentNumber" : "0x01", + "currentTimestamp" : "0x079e", + "currentGasLimit" : "0x7fffffffffffffff", + "previousHash" : "0x3a9b485972e7353edd9152712492f0c58d89ef80623686b6bf947a4a6dce6cb6", + "currentBlobGasUsed" : "0x00", + "parentTimestamp" : "0x03b6", + "parentDifficulty" : "0x00", + "parentUncleHash" : "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347", + "currentRandom" : "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", + "withdrawals" : [ + ], + "parentBaseFee" : "0x0a", + "parentGasUsed" : "0x00", + "parentGasLimit" : "0x7fffffffffffffff", + "parentExcessBlobGas" : "0x00", + "parentBlobGasUsed" : "0x00", + "parentBeaconBlockRoot": "0x0000beac00beac00beac00beac00beac00beac00beac00beac00beac00beac00" +} \ No newline at end of file
diff --git ethereum/go-ethereum/cmd/evm/testdata/29/exp.json taikoxyz/taiko-geth/cmd/evm/testdata/29/exp.json new file mode 100644 index 0000000000000000000000000000000000000000..c4c001ec14e3d090bf3650d82cf98bbc5b2de078 --- /dev/null +++ taikoxyz/taiko-geth/cmd/evm/testdata/29/exp.json @@ -0,0 +1,45 @@ +{ + "alloc": { + "0x000f3df6d732807ef1319fb7b8bb8522d0beac02": { + "code": "0x3373fffffffffffffffffffffffffffffffffffffffe14604457602036146024575f5ffd5b620180005f350680545f35146037575f5ffd5b6201800001545f5260205ff35b6201800042064281555f359062018000015500", + "storage": { + "0x000000000000000000000000000000000000000000000000000000000000079e": "0x000000000000000000000000000000000000000000000000000000000000079e", + "0x000000000000000000000000000000000000000000000000000000000001879e": "0x0000beac00beac00beac00beac00beac00beac00beac00beac00beac00beac00" + }, + "balance": "0x1" + }, + "0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b": { + "balance": "0x16345785d871db8", + "nonce": "0x1" + } + }, + "result": { + "stateRoot": "0x19a4f821a7c0a6f4c934f9acb0fe9ce5417b68086e12513ecbc3e3f57e01573c", + "txRoot": "0x248074fabe112f7d93917f292b64932394f835bb98da91f21501574d58ec92ab", + "receiptsRoot": "0xf78dfb743fbd92ade140711c8bbc542b5e307f0ab7984eff35d751969fe57efa", + "logsHash": "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347", + "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "receipts": [ + { + "type": "0x2", + "root": "0x", + "status": "0x1", + "cumulativeGasUsed": "0x5208", + "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "logs": null, + "transactionHash": "0x84f70aba406a55628a0620f26d260f90aeb6ccc55fed6ec2ac13dd4f727032ed", + "contractAddress": "0x0000000000000000000000000000000000000000", + "gasUsed": "0x5208", + "effectiveGasPrice": null, + "blockHash": "0x0000000000000000000000000000000000000000000000000000000000000000", + "transactionIndex": "0x0" + } + ], + "currentDifficulty": null, + "gasUsed": "0x5208", + "currentBaseFee": "0x9", + "withdrawalsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", + "currentExcessBlobGas": "0x0", + "blobGasUsed": "0x0" + } +}
diff --git ethereum/go-ethereum/cmd/evm/testdata/29/txs.json taikoxyz/taiko-geth/cmd/evm/testdata/29/txs.json new file mode 100644 index 0000000000000000000000000000000000000000..d6743cc4d24016d6d9a9b4d23db9f745748c82e1 --- /dev/null +++ taikoxyz/taiko-geth/cmd/evm/testdata/29/txs.json @@ -0,0 +1,19 @@ +[ + { + "input" : "0x", + "gas" : "0x10000000", + "nonce" : "0x0", + "to" : "0x1111111111111111111111111111111111111111", + "value" : "0x0", + "secretKey" : "0x45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8", + "chainId" : "0x1", + "type" : "0x2", + "v": "0x0", + "r": "0x0", + "s": "0x0", + "maxFeePerGas" : "0xfa0", + "maxPriorityFeePerGas" : "0x0", + "accessList" : [ + ] + } +] \ No newline at end of file
diff --git ethereum/go-ethereum/core/rawdb/gen_taiko_l1_origin.go taikoxyz/taiko-geth/core/rawdb/gen_taiko_l1_origin.go new file mode 100644 index 0000000000000000000000000000000000000000..6cbd6c3cdbc0a1f87d5e816e6103b2a2d082354b --- /dev/null +++ taikoxyz/taiko-geth/core/rawdb/gen_taiko_l1_origin.go @@ -0,0 +1,60 @@ +// Code generated by github.com/fjl/gencodec. DO NOT EDIT. + +package rawdb + +import ( + "encoding/json" + "errors" + "math/big" + + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/common/math" +) + +var _ = (*l1OriginMarshaling)(nil) + +// MarshalJSON marshals as JSON. +func (l L1Origin) MarshalJSON() ([]byte, error) { + type L1Origin struct { + BlockID *math.HexOrDecimal256 `json:"blockID" gencodec:"required"` + L2BlockHash common.Hash `json:"l2BlockHash"` + L1BlockHeight *math.HexOrDecimal256 `json:"l1BlockHeight" gencodec:"required"` + L1BlockHash common.Hash `json:"l1BlockHash" gencodec:"required"` + } + var enc L1Origin + enc.BlockID = (*math.HexOrDecimal256)(l.BlockID) + enc.L2BlockHash = l.L2BlockHash + enc.L1BlockHeight = (*math.HexOrDecimal256)(l.L1BlockHeight) + enc.L1BlockHash = l.L1BlockHash + return json.Marshal(&enc) +} + +// UnmarshalJSON unmarshals from JSON. +func (l *L1Origin) UnmarshalJSON(input []byte) error { + type L1Origin struct { + BlockID *math.HexOrDecimal256 `json:"blockID" gencodec:"required"` + L2BlockHash *common.Hash `json:"l2BlockHash"` + L1BlockHeight *math.HexOrDecimal256 `json:"l1BlockHeight" gencodec:"required"` + L1BlockHash *common.Hash `json:"l1BlockHash" gencodec:"required"` + } + var dec L1Origin + if err := json.Unmarshal(input, &dec); err != nil { + return err + } + if dec.BlockID == nil { + return errors.New("missing required field 'blockID' for L1Origin") + } + l.BlockID = (*big.Int)(dec.BlockID) + if dec.L2BlockHash != nil { + l.L2BlockHash = *dec.L2BlockHash + } + if dec.L1BlockHeight == nil { + return errors.New("missing required field 'l1BlockHeight' for L1Origin") + } + l.L1BlockHeight = (*big.Int)(dec.L1BlockHeight) + if dec.L1BlockHash == nil { + return errors.New("missing required field 'l1BlockHash' for L1Origin") + } + l.L1BlockHash = *dec.L1BlockHash + return nil +}
diff --git ethereum/go-ethereum/core/taiko_genesis/askja.json taikoxyz/taiko-geth/core/taiko_genesis/askja.json new file mode 100644 index 0000000000000000000000000000000000000000..24a016d8300dc14b6151fe35b12342c9938b9fef --- /dev/null +++ taikoxyz/taiko-geth/core/taiko_genesis/askja.json @@ -0,0 +1,117 @@ +{ + "0x6C671d2C641CE1b99F17755fd45441fa4326C3B1": { + "balance": "0xfffffffffffffacbbb7ca13a7fffffff" + }, + "0x09d4121CD4123F039390c7f5e99b15BED5e07222": { + "balance": "0xfffffffffffffacbbb7ca13a7fffffff" + }, + "0x9E5da4B6D25Ee5A68aa8c29B6B87C82f7F463893": { + "balance": "0xfffffffffffffacbbb7ca13a7fffffff" + }, + "0xB51f0f2bdCbf6cfabB35239921A5c672519F74ba": { + "contractName": "LibTrieProof", + "storage": {}, + "code": "0x73000000000000000000000000000000000000000030146080604052600436106100355760003560e01c8063960304391461003a575b600080fd5b61004d610048366004611938565b610061565b604051901515815260200160405180910390f35b6000808061007184860186611acc565b6040517fffffffffffffffffffffffffffffffffffffffff00000000000000000000000060608c901b166020820152919350915060009081906100c790603401604051602081830303815290604052858d610197565b915091508161011d5760405162461bcd60e51b815260206004820152601960248201527f4c54503a696e76616c6964206163636f756e742070726f6f660000000000000060448201526064015b60405180910390fd5b6000610128826101c0565b9050600061014f8260028151811061014257610142611b30565b60200260200101516101f9565b90506101868b60405160200161016791815260200190565b60405160208183030381529060405261017f8c6102fc565b878461030f565b9d9c50505050505050505050505050565b6000606060006101a686610329565b90506101b381868661035b565b9250925050935093915050565b6040805180820182526000808252602091820152815180830190925282518252808301908201526060906101f390610436565b92915050565b60006021826000015111156102505760405162461bcd60e51b815260206004820152601a60248201527f496e76616c696420524c5020627974657333322076616c75652e0000000000006044820152606401610114565b600080600061025e85610635565b91945092509050600081600181111561027957610279611b5f565b146102c65760405162461bcd60e51b815260206004820152601a60248201527f496e76616c696420524c5020627974657333322076616c75652e0000000000006044820152606401610114565b60008386602001516102d89190611bbd565b805190915060208410156102f25760208490036101000a90045b9695505050505050565b60606101f361030a83610986565b610aea565b60008061031b86610329565b90506102f281868686610b59565b6060818051906020012060405160200161034591815260200190565b6040516020818303038152906040529050919050565b60006060600061036a85610b96565b9050600080600061037c848a89610c8f565b815192955090935091501580806103905750815b6103dc5760405162461bcd60e51b815260206004820152601a60248201527f50726f76696465642070726f6f6620697320696e76616c69642e0000000000006044820152606401610114565b6000816103f85760405180602001604052806000815250610424565b61042486610407600188611bd0565b8151811061041757610417611b30565b6020026020010151611144565b919b919a509098505050505050505050565b606060008061044484610635565b9193509091506001905081600181111561046057610460611b5f565b146104ad5760405162461bcd60e51b815260206004820152601760248201527f496e76616c696420524c50206c6973742076616c75652e0000000000000000006044820152606401610114565b6040805160208082526104208201909252600091816020015b60408051808201909152600080825260208201528152602001906001900390816104c65790505090506000835b865181101561062a57602082106105725760405162461bcd60e51b815260206004820152602a60248201527f50726f766964656420524c50206c6973742065786365656473206d6178206c6960448201527f7374206c656e6774682e000000000000000000000000000000000000000000006064820152608401610114565b6000806105af6040518060400160405280858c600001516105939190611bd0565b8152602001858c602001516105a89190611bbd565b9052610635565b5091509150604051806040016040528083836105cb9190611bbd565b8152602001848b602001516105e09190611bbd565b8152508585815181106105f5576105f5611b30565b602090810291909101015261060b600185611bbd565b93506106178183611bbd565b6106219084611bbd565b925050506104f3565b508152949350505050565b60008060008084600001511161068d5760405162461bcd60e51b815260206004820152601860248201527f524c50206974656d2063616e6e6f74206265206e756c6c2e00000000000000006044820152606401610114565b6020840151805160001a607f81116106b257600060016000945094509450505061097f565b60b7811161072e5760006106c7608083611bd0565b90508087600001511161071c5760405162461bcd60e51b815260206004820152601960248201527f496e76616c696420524c502073686f727420737472696e672e000000000000006044820152606401610114565b6001955093506000925061097f915050565b60bf811161081d57600061074360b783611bd0565b9050808760000151116107985760405162461bcd60e51b815260206004820152601f60248201527f496e76616c696420524c50206c6f6e6720737472696e67206c656e6774682e006044820152606401610114565b600183015160208290036101000a90046107b28183611bbd565b8851116108015760405162461bcd60e51b815260206004820152601860248201527f496e76616c696420524c50206c6f6e6720737472696e672e00000000000000006044820152606401610114565b61080c826001611bbd565b965094506000935061097f92505050565b60f7811161089857600061083260c083611bd0565b9050808760000151116108875760405162461bcd60e51b815260206004820152601760248201527f496e76616c696420524c502073686f7274206c6973742e0000000000000000006044820152606401610114565b60019550935084925061097f915050565b60006108a560f783611bd0565b9050808760000151116108fa5760405162461bcd60e51b815260206004820152601d60248201527f496e76616c696420524c50206c6f6e67206c697374206c656e6774682e0000006044820152606401610114565b600183015160208290036101000a90046109148183611bbd565b8851116109635760405162461bcd60e51b815260206004820152601660248201527f496e76616c696420524c50206c6f6e67206c6973742e000000000000000000006044820152606401610114565b61096e826001611bbd565b965094506001935061097f92505050565b9193909250565b606060008260405160200161099d91815260200190565b604051602081830303815290604052905060005b6020811015610a0a578181815181106109cc576109cc611b30565b01602001517fff0000000000000000000000000000000000000000000000000000000000000016600003610a0a57610a0381611be3565b90506109b1565b6000610a17826020611bd0565b67ffffffffffffffff811115610a2f57610a2f6119f2565b6040519080825280601f01601f191660200182016040528015610a59576020820181803683370190505b50905060005b8151811015610ae1578383610a7381611be3565b945081518110610a8557610a85611b30565b602001015160f81c60f81b828281518110610aa257610aa2611b30565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a905350610ada81611be3565b9050610a5f565b50949350505050565b60608082516001148015610b185750608083600081518110610b0e57610b0e611b30565b016020015160f81c105b15610b245750816101f3565b610b308351608061116b565b83604051602001610b42929190611c4b565b604051602081830303815290604052905092915050565b6000806000610b6987868661035b565b91509150818015610b8b57508051602080830191909120875191880191909120145b979650505050505050565b60606000610ba3836101c0565b90506000815167ffffffffffffffff811115610bc157610bc16119f2565b604051908082528060200260200182016040528015610c0657816020015b6040805180820190915260608082526020820152815260200190600190039081610bdf5790505b50905060005b8251811015610c87576000610c39848381518110610c2c57610c2c611b30565b602002602001015161135d565b90506040518060400160405280610c4f836101c0565b815260200182815250838381518110610c6a57610c6a611b30565b60200260200101819052505080610c8090611be3565b9050610c0c565b509392505050565b600060606000806000610ca1876113ed565b90506000869050600080610cc8604051806040016040528060608152602001606081525090565b60005b8c51811015611100578c8181518110610ce657610ce6611b30565b602002602001015191508284610cfc9190611bbd565b9350610d09600188611bbd565b965083600003610d72578482602001518051906020012014610d6d5760405162461bcd60e51b815260206004820152601160248201527f496e76616c696420726f6f7420686173680000000000000000000000000000006044820152606401610114565b610e34565b602082602001515110610dd9578482602001518051906020012014610d6d5760405162461bcd60e51b815260206004820152601b60248201527f496e76616c6964206c6172676520696e7465726e616c206861736800000000006044820152606401610114565b84610de7836020015161156e565b14610e345760405162461bcd60e51b815260206004820152601a60248201527f496e76616c696420696e7465726e616c206e6f646520686173680000000000006044820152606401610114565b610e4060106001611c68565b60ff1682600001515103610eae5785518414611100576000868581518110610e6a57610e6a611b30565b01602001518351805160f89290921c925060009183908110610e8e57610e8e611b30565b60200260200101519050610ea181611596565b96506001945050506110f0565b8151517ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016110a8576000610ee2836115cc565b9050600081600081518110610ef957610ef9611b30565b016020015160f81c90506000610f10600283611cb0565b610f1b906002611cd2565b90506000610f2c848360ff166115f0565b90506000610f3a8b8a6115f0565b90506000610f488383611626565b905060ff851660021480610f5f575060ff85166003145b15610fb557808351148015610f745750808251145b15610f8657610f83818b611bbd565b99505b507f80000000000000000000000000000000000000000000000000000000000000009950611100945050505050565b60ff85161580610fc8575060ff85166001145b1561103a578251811461100457507f80000000000000000000000000000000000000000000000000000000000000009950611100945050505050565b61102b886000015160018151811061101e5761101e611b30565b6020026020010151611596565b9a5097506110f0945050505050565b60405162461bcd60e51b815260206004820152602660248201527f52656365697665642061206e6f6465207769746820616e20756e6b6e6f776e2060448201527f70726566697800000000000000000000000000000000000000000000000000006064820152608401610114565b60405162461bcd60e51b815260206004820152601d60248201527f526563656976656420616e20756e706172736561626c65206e6f64652e0000006044820152606401610114565b6110f981611be3565b9050610ccb565b507f800000000000000000000000000000000000000000000000000000000000000084148661112f87866115f0565b909e909d50909b509950505050505050505050565b805180516060916101f39161115b90600190611bd0565b81518110610c2c57610c2c611b30565b60608060388410156111ea57604080516001808252818301909252906020820181803683370190505090506111a08385611c68565b60f81b816000815181106111b6576111b6611b30565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a905350611356565b600060015b6111f98187611ceb565b1561121c5761120782611be3565b915061121561010082611cff565b90506111ef565b611227826001611bbd565b67ffffffffffffffff81111561123f5761123f6119f2565b6040519080825280601f01601f191660200182016040528015611269576020820181803683370190505b5092506112768583611c68565b611281906037611c68565b60f81b8360008151811061129757611297611b30565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a905350600190505b818111611353576101006112df8284611bd0565b6112eb90610100611e36565b6112f59088611ceb565b6112ff9190611e42565b60f81b83828151811061131457611314611b30565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a90535061134c81611be3565b90506112cb565b50505b9392505050565b6060600080600061136d85610635565b91945092509050600081600181111561138857611388611b5f565b146113d55760405162461bcd60e51b815260206004820152601860248201527f496e76616c696420524c502062797465732076616c75652e00000000000000006044820152606401610114565b6113e4856020015184846116d0565b95945050505050565b60606000825160026113ff9190611cff565b67ffffffffffffffff811115611417576114176119f2565b6040519080825280601f01601f191660200182016040528015611441576020820181803683370190505b50905060005b835181101561156757600484828151811061146457611464611b30565b01602001517fff0000000000000000000000000000000000000000000000000000000000000016901c82611499836002611cff565b815181106114a9576114a9611b30565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a90535060108482815181106114ec576114ec611b30565b01602001516114fe919060f81c611cb0565b60f81b8261150d836002611cff565b611518906001611bbd565b8151811061152857611528611b30565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a90535061156081611be3565b9050611447565b5092915050565b600060208251101561158257506020015190565b818060200190518101906101f39190611e56565b600060606020836000015110156115b7576115b083611779565b90506115c3565b6115c08361135d565b90505b6113568161156e565b60606101f36115eb8360000151600081518110610c2c57610c2c611b30565b6113ed565b60608251821061160f57506040805160208101909152600081526101f3565b61135683838486516116219190611bd0565b611784565b6000805b80845111801561163a5750808351115b80156116bb575082818151811061165357611653611b30565b602001015160f81c60f81b7effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff191684828151811061169257611692611b30565b01602001517fff0000000000000000000000000000000000000000000000000000000000000016145b15611356576116c981611be3565b905061162a565b606060008267ffffffffffffffff8111156116ed576116ed6119f2565b6040519080825280601f01601f191660200182016040528015611717576020820181803683370190505b509050805160000361172a579050611356565b8484016020820160005b8581101561174c578281015182820152602001611734565b5060006001602087066020036101000a039050808251168119845116178252839450505050509392505050565b60606101f382611922565b60608161179281601f611bbd565b10156117e05760405162461bcd60e51b815260206004820152600e60248201527f736c6963655f6f766572666c6f770000000000000000000000000000000000006044820152606401610114565b826117eb8382611bbd565b10156118395760405162461bcd60e51b815260206004820152600e60248201527f736c6963655f6f766572666c6f770000000000000000000000000000000000006044820152606401610114565b6118438284611bbd565b845110156118935760405162461bcd60e51b815260206004820152601160248201527f736c6963655f6f75744f66426f756e64730000000000000000000000000000006044820152606401610114565b6060821580156118b25760405191506000825260208201604052610ae1565b6040519150601f8416801560200281840101858101878315602002848b0101015b818310156118eb5780518352602092830192016118d3565b5050858452601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0166040525050949350505050565b60606101f38260200151600084600001516116d0565b60008060008060008060a0878903121561195157600080fd5b86359550602087013573ffffffffffffffffffffffffffffffffffffffff8116811461197c57600080fd5b94506040870135935060608701359250608087013567ffffffffffffffff808211156119a757600080fd5b818901915089601f8301126119bb57600080fd5b8135818111156119ca57600080fd5b8a60208285010111156119dc57600080fd5b6020830194508093505050509295509295509295565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b600082601f830112611a3257600080fd5b813567ffffffffffffffff80821115611a4d57611a4d6119f2565b604051601f83017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f01168101908282118183101715611a9357611a936119f2565b81604052838152866020858801011115611aac57600080fd5b836020870160208301376000602085830101528094505050505092915050565b60008060408385031215611adf57600080fd5b823567ffffffffffffffff80821115611af757600080fd5b611b0386838701611a21565b93506020850135915080821115611b1957600080fd5b50611b2685828601611a21565b9150509250929050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b808201808211156101f3576101f3611b8e565b818103818111156101f3576101f3611b8e565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8203611c1457611c14611b8e565b5060010190565b6000815160005b81811015611c3c5760208185018101518683015201611c22565b50600093019283525090919050565b6000611c60611c5a8386611c1b565b84611c1b565b949350505050565b60ff81811683821601908111156101f3576101f3611b8e565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b600060ff831680611cc357611cc3611c81565b8060ff84160691505092915050565b60ff82811682821603908111156101f3576101f3611b8e565b600082611cfa57611cfa611c81565b500490565b80820281158282048414176101f3576101f3611b8e565b600181815b80851115611d6f57817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff04821115611d5557611d55611b8e565b80851615611d6257918102915b93841c9390800290611d1b565b509250929050565b600082611d86575060016101f3565b81611d93575060006101f3565b8160018114611da95760028114611db357611dcf565b60019150506101f3565b60ff841115611dc457611dc4611b8e565b50506001821b6101f3565b5060208310610133831016604e8410600b8410161715611df2575081810a6101f3565b611dfc8383611d16565b807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff04821115611e2e57611e2e611b8e565b029392505050565b60006113568383611d77565b600082611e5157611e51611c81565b500690565b600060208284031215611e6857600080fd5b505191905056fea264697066735822122022f5cdb126db09c3c43e2fa6a17aab0115cbc5363507839bf8f77203759fb3af64736f6c63430008120033", + "balance": "0x0" + }, + "0x7C96157d384E99B04fE912f7E8Fa6d032073a0DD": { + "contractName": "LibBridgeRetry", + "storage": {}, + "code": "0x73000000000000000000000000000000000000000030146080604052600080fdfea2646970667358221220032710b16720cdb7bfee28fecace22d2e4fd9f5731db2aaefd90be3a941623a364736f6c63430008120033", + "balance": "0x0" + }, + "0x13E419A8F4A246Fe22F3Acc054354258B068A7A3": { + "contractName": "LibBridgeProcess", + "storage": {}, + "code": "0x73000000000000000000000000000000000000000030146080604052600080fdfea2646970667358221220d4832ed4ef0b67bed2c2d982e30c1a789312b6584967438335056c5c4005497e64736f6c63430008120033", + "balance": "0x0" + }, + "0x658d9Ff6257D5254FC536d29641E43144Fbe8d8C": { + "contractName": "LibTxDecoder", + "storage": {}, + "code": "0x73000000000000000000000000000000000000000030146080604052600436106100405760003560e01c80634eb7f19914610045578063a946c1de1461006e575b600080fd5b61005861005336600461175f565b61008e565b60405161006591906118cf565b60405180910390f35b61008161007c366004611988565b610214565b6040516100659190611a61565b604080516020810190915260608152811561020d5760006100e484848080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152506104d992505050565b90506000815167ffffffffffffffff81111561010257610102611959565b60405190808252806020026020018201604052801561019757816020015b610184604051806101000160405280600060ff168152602001600073ffffffffffffffffffffffffffffffffffffffff1681526020016060815260200160008152602001600060ff1681526020016000815260200160008152602001606081525090565b8152602001906001900390816101205790505b50905060005b82518110156101fa576101cc8761007c8584815181106101bf576101bf611a74565b6020026020010151610512565b8282815181106101de576101de611a74565b6020026020010181905250806101f390611ad2565b905061019d565b5060408051602081019091529081529150505b9392505050565b610278604051806101000160405280600060ff168152602001600073ffffffffffffffffffffffffffffffffffffffff1681526020016060815260200160008152602001600060ff1681526020016000815260200160008152602001606081525090565b602082015160e0820183905260001a60c0811080159061029c575060fe8160ff1611155b156103235760008083526102af846104d9565b905060006102bd86836105a2565b60408082015160608088019190915282015173ffffffffffffffffffffffffffffffffffffffff16602087015260c08083015160ff16608088015260e083015160a080890191909152610100840151918801919091529091015190850152506104d29050565b607f8160ff161161048a5760ff8116825260006103496103448560016107ba565b6104d9565b90508160ff166001036103c0576000610361826107f0565b6060808201519086015260808082015173ffffffffffffffffffffffffffffffffffffffff16602087015261010082015160ff169086015261012081015160a086015261014081015160c0808701919091520151604085015250610484565b825160ff166002036104375760006103d782610a31565b608080820151606087015260a08083015173ffffffffffffffffffffffffffffffffffffffff16602088015261012083015160ff16918701919091526101408201519086015261016081015160c086015260e00151604085015250610484565b60405162461bcd60e51b815260206004820152600e60248201527f696e76616c69642074785479706500000000000000000000000000000000000060448201526064015b60405180910390fd5b506104d2565b60405162461bcd60e51b815260206004820152600e60248201527f696e76616c696420707265666978000000000000000000000000000000000000604482015260640161047b565b5092915050565b60408051808201825260008082526020918201528151808301909252825182528083019082015260609061050c90610c86565b92915050565b6060600080600061052285610e85565b91945092509050600081600181111561053d5761053d611b0a565b1461058a5760405162461bcd60e51b815260206004820152601860248201527f496e76616c696420524c502062797465732076616c75652e0000000000000000604482015260640161047b565b610599856020015184846111d6565b95945050505050565b61060a604051806101200160405280600081526020016000815260200160008152602001600073ffffffffffffffffffffffffffffffffffffffff1681526020016000815260200160608152602001600060ff16815260200160008152602001600081525090565b815160091461065b5760405162461bcd60e51b815260206004820152601460248201527f696e76616c6964206974656d73206c656e677468000000000000000000000000604482015260640161047b565b61067e8260008151811061067157610671611a74565b602002602001015161127f565b81528151610699908390600190811061067157610671611a74565b602082015281516106b7908390600290811061067157610671611a74565b604082015281516106e290839060039081106106d5576106d5611a74565b602002602001015161128a565b73ffffffffffffffffffffffffffffffffffffffff1660608201528151610716908390600490811061067157610671611a74565b6080820152815161073490839060059081106101bf576101bf611a74565b60a0820152610744836002611b39565b61075a8360068151811061067157610671611a74565b6107649190611b50565b61076f906023611b63565b60ff1660c08201528151610790908390600790811061067157610671611a74565b60e082015281516107ae908390600890811061067157610671611a74565b61010082015292915050565b6060825182106107d9575060408051602081019091526000815261050c565b61020d83838486516107eb9190611b50565b6112f8565b61086660405180610160016040528060008152602001600081526020016000815260200160008152602001600073ffffffffffffffffffffffffffffffffffffffff168152602001600081526020016060815260200160608152602001600060ff16815260200160008152602001600081525090565b8151600b146108b75760405162461bcd60e51b815260206004820152601460248201527f696e76616c6964206974656d73206c656e677468000000000000000000000000604482015260640161047b565b6108cd8260008151811061067157610671611a74565b815281516108e8908390600190811061067157610671611a74565b60208201528151610906908390600290811061067157610671611a74565b60408201528151610924908390600390811061067157610671611a74565b6060820152815161094290839060049081106106d5576106d5611a74565b73ffffffffffffffffffffffffffffffffffffffff1660808201528151610976908390600590811061067157610671611a74565b60a0820152815161099490839060069081106101bf576101bf611a74565b8160c001819052506109c76109c2836007815181106109b5576109b5611a74565b6020026020010151610c86565b611497565b8160e001819052506109e58260088151811061067157610671611a74565b60ff166101008201528151610a07908390600990811061067157610671611a74565b6101208201528151610a26908390600a90811061067157610671611a74565b610140820152919050565b610aae6040518061018001604052806000815260200160008152602001600081526020016000815260200160008152602001600073ffffffffffffffffffffffffffffffffffffffff168152602001600081526020016060815260200160608152602001600060ff16815260200160008152602001600081525090565b8151600c14610aff5760405162461bcd60e51b815260206004820152601460248201527f696e76616c6964206974656d73206c656e677468000000000000000000000000604482015260640161047b565b610b158260008151811061067157610671611a74565b81528151610b30908390600190811061067157610671611a74565b60208201528151610b4e908390600290811061067157610671611a74565b60408201528151610b6c908390600390811061067157610671611a74565b60608201528151610b8a908390600490811061067157610671611a74565b60808201528151610ba890839060059081106106d5576106d5611a74565b73ffffffffffffffffffffffffffffffffffffffff1660a08201528151610bdc908390600690811061067157610671611a74565b60c08201528151610bfa90839060079081106101bf576101bf611a74565b8160e00181905250610c1b6109c2836008815181106109b5576109b5611a74565b816101000181905250610c3a8260098151811061067157610671611a74565b60ff166101208201528151610c5c908390600a90811061067157610671611a74565b6101408201528151610c7b908390600b90811061067157610671611a74565b610160820152919050565b6060600080610c9484610e85565b91935090915060019050816001811115610cb057610cb0611b0a565b14610cfd5760405162461bcd60e51b815260206004820152601760248201527f496e76616c696420524c50206c6973742076616c75652e000000000000000000604482015260640161047b565b6040805160208082526104208201909252600091816020015b6040805180820190915260008082526020820152815260200190600190039081610d165790505090506000835b8651811015610e7a5760208210610dc25760405162461bcd60e51b815260206004820152602a60248201527f50726f766964656420524c50206c6973742065786365656473206d6178206c6960448201527f7374206c656e6774682e00000000000000000000000000000000000000000000606482015260840161047b565b600080610dff6040518060400160405280858c60000151610de39190611b50565b8152602001858c60200151610df89190611b63565b9052610e85565b509150915060405180604001604052808383610e1b9190611b63565b8152602001848b60200151610e309190611b63565b815250858581518110610e4557610e45611a74565b6020908102919091010152610e5b600185611b63565b9350610e678183611b63565b610e719084611b63565b92505050610d43565b508152949350505050565b600080600080846000015111610edd5760405162461bcd60e51b815260206004820152601860248201527f524c50206974656d2063616e6e6f74206265206e756c6c2e0000000000000000604482015260640161047b565b6020840151805160001a607f8111610f025760006001600094509450945050506111cf565b60b78111610f7e576000610f17608083611b50565b905080876000015111610f6c5760405162461bcd60e51b815260206004820152601960248201527f496e76616c696420524c502073686f727420737472696e672e00000000000000604482015260640161047b565b600195509350600092506111cf915050565b60bf811161106d576000610f9360b783611b50565b905080876000015111610fe85760405162461bcd60e51b815260206004820152601f60248201527f496e76616c696420524c50206c6f6e6720737472696e67206c656e6774682e00604482015260640161047b565b600183015160208290036101000a90046110028183611b63565b8851116110515760405162461bcd60e51b815260206004820152601860248201527f496e76616c696420524c50206c6f6e6720737472696e672e0000000000000000604482015260640161047b565b61105c826001611b63565b96509450600093506111cf92505050565b60f781116110e857600061108260c083611b50565b9050808760000151116110d75760405162461bcd60e51b815260206004820152601760248201527f496e76616c696420524c502073686f7274206c6973742e000000000000000000604482015260640161047b565b6001955093508492506111cf915050565b60006110f560f783611b50565b90508087600001511161114a5760405162461bcd60e51b815260206004820152601d60248201527f496e76616c696420524c50206c6f6e67206c697374206c656e6774682e000000604482015260640161047b565b600183015160208290036101000a90046111648183611b63565b8851116111b35760405162461bcd60e51b815260206004820152601660248201527f496e76616c696420524c50206c6f6e67206c6973742e00000000000000000000604482015260640161047b565b6111be826001611b63565b96509450600193506111cf92505050565b9193909250565b606060008267ffffffffffffffff8111156111f3576111f3611959565b6040519080825280601f01601f19166020018201604052801561121d576020820181803683370190505b509050805160000361123057905061020d565b8484016020820160005b8581101561125257828101518282015260200161123a565b5060006001602087066020036101000a039050808251168119845116178252839450505050509392505050565b600061050c8261165c565b805160009060010361129e57506000919050565b81516015146112ef5760405162461bcd60e51b815260206004820152601a60248201527f496e76616c696420524c5020616464726573732076616c75652e000000000000604482015260640161047b565b61050c8261127f565b60608161130681601f611b63565b10156113545760405162461bcd60e51b815260206004820152600e60248201527f736c6963655f6f766572666c6f77000000000000000000000000000000000000604482015260640161047b565b8261135f8382611b63565b10156113ad5760405162461bcd60e51b815260206004820152600e60248201527f736c6963655f6f766572666c6f77000000000000000000000000000000000000604482015260640161047b565b6113b78284611b63565b845110156114075760405162461bcd60e51b815260206004820152601160248201527f736c6963655f6f75744f66426f756e6473000000000000000000000000000000604482015260640161047b565b606082158015611426576040519150600082526020820160405261148e565b6040519150601f8416801560200281840101858101878315602002848b0101015b8183101561145f578051835260209283019201611447565b5050858452601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016604052505b50949350505050565b6060815167ffffffffffffffff8111156114b3576114b3611959565b6040519080825280602002602001820160405280156114f957816020015b6040805180820190915260008152606060208201528152602001906001900390816114d15790505b50905060005b825181101561165657600061151f8483815181106109b5576109b5611a74565b90506000611539826000815181106106d5576106d5611a74565b90506000611553836001815181106109b5576109b5611a74565b90506000815167ffffffffffffffff81111561157157611571611959565b60405190808252806020026020018201604052801561159a578160200160208202803683370190505b50905060005b82518110156115f8576115cb8382815181106115be576115be611a74565b602002602001015161165c565b8282815181106115dd576115dd611a74565b60209081029190910101526115f181611ad2565b90506115a0565b5060405180604001604052808473ffffffffffffffffffffffffffffffffffffffff1681526020018281525086868151811061163657611636611a74565b6020026020010181905250505050508061164f90611ad2565b90506114ff565b50919050565b60006021826000015111156116b35760405162461bcd60e51b815260206004820152601a60248201527f496e76616c696420524c5020627974657333322076616c75652e000000000000604482015260640161047b565b60008060006116c185610e85565b9194509250905060008160018111156116dc576116dc611b0a565b146117295760405162461bcd60e51b815260206004820152601a60248201527f496e76616c696420524c5020627974657333322076616c75652e000000000000604482015260640161047b565b600083866020015161173b9190611b63565b805190915060208410156117555760208490036101000a90045b9695505050505050565b60008060006040848603121561177457600080fd5b83359250602084013567ffffffffffffffff8082111561179357600080fd5b818601915086601f8301126117a757600080fd5b8135818111156117b657600080fd5b8760208285010111156117c857600080fd5b6020830194508093505050509250925092565b6000815180845260005b81811015611801576020818501810151868301820152016117e5565b5060006020828601015260207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f83011685010191505092915050565b600061010060ff835116845273ffffffffffffffffffffffffffffffffffffffff60208401511660208501526040830151816040860152611882828601826117db565b9150506060830151606085015260808301516118a3608086018260ff169052565b5060a083015160a085015260c083015160c085015260e083015184820360e086015261059982826117db565b60006020808352604083018451828386015281815180845260608701915060608160051b8801019350848301925060005b8181101561194c577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa088860301835261193a85855161183f565b94509285019291850191600101611900565b5092979650505050505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6000806040838503121561199b57600080fd5b82359150602083013567ffffffffffffffff808211156119ba57600080fd5b818501915085601f8301126119ce57600080fd5b8135818111156119e0576119e0611959565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f01168101908382118183101715611a2657611a26611959565b81604052828152886020848701011115611a3f57600080fd5b8260208601602083013760006020848301015280955050505050509250929050565b60208152600061020d602083018461183f565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8203611b0357611b03611aa3565b5060010190565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b808202811582820484141761050c5761050c611aa3565b8181038181111561050c5761050c611aa3565b8082018082111561050c5761050c611aa356fea2646970667358221220977255eb91ee0bc83da7d64c4ccd4610769dfef0575766e3b1d355d99af47f7d64736f6c63430008120033", + "balance": "0x0" + }, + "0x0000777700000000000000000000000000000006": { + "contractName": "AddressManager", + "storage": { + "0x0000000000000000000000000000000000000000000000000000000000000000": "0x0000000000000000000000000000000000000000000000000000000000000001", + "0x0000000000000000000000000000000000000000000000000000000000000033": "0x00000000000000000000000019b4f9c381c7927fe33d853e48b560141a380c44", + "0xfb2e436f19bdbec4da734cf0919b4423eb4c7a14d4f249db9211e6070a6a653d": "0x0000000000000000000000000000777700000000000000000000000000000001", + "0x0aa3204ceb554139e74fc959b75d2c0961a8274eee43ddfb4c452fa0d56e55c3": "0x0000000000000000000000000000777700000000000000000000000000000004", + "0xc19602c1e190099bda9f0217b29220086721ab0cc7df1664d5392c1062c6d6a0": "0x0000000000000000000000000000777700000000000000000000000000000002", + "0x2230df1245aba8de92051ca9155400ea7ed51d37f62ecf6ceb23a360b8066ac7": "0x0000000000000000000000000000777700000000000000000000000000000003", + "0x61566bd8aa85fc0cba510177307735c5887d55659d67a1f0f76bfcaa381cbca5": "0x0000000000000000000000000000777700000000000000000000000000000007" + }, + "code": "0x608060405234801561001057600080fd5b50600436106100725760003560e01c8063bf40fac111610050578063bf40fac1146100d7578063e1c7392a14610115578063f2fde38b1461011d57600080fd5b8063715018a6146100775780638da5cb5b146100815780639b2ea4bd146100c4575b600080fd5b61007f610130565b005b60335473ffffffffffffffffffffffffffffffffffffffff165b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200160405180910390f35b61007f6100d2366004610796565b610144565b61009b6100e53660046107e4565b805160209182012060009081526065909152604090205473ffffffffffffffffffffffffffffffffffffffff1690565b61007f610216565b61007f61012b366004610821565b6103ad565b610138610461565b61014260006104e2565b565b61014c610461565b815160208084019190912060008181526065909252604091829020805473ffffffffffffffffffffffffffffffffffffffff8581167fffffffffffffffffffffffff00000000000000000000000000000000000000008316179092559251919216906101b9908590610843565b6040805191829003822073ffffffffffffffffffffffffffffffffffffffff808716845284166020840152917f9416a153a346f93d95f94b064ae3f148b6460473c6e82b3f9fc2521b873fcd6c910160405180910390a250505050565b600054610100900460ff16158080156102365750600054600160ff909116105b806102505750303b158015610250575060005460ff166001145b6102e1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a656400000000000000000000000000000000000060648201526084015b60405180910390fd5b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001179055801561033f57600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff166101001790555b610347610559565b80156103aa57600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b50565b6103b5610461565b73ffffffffffffffffffffffffffffffffffffffff8116610458576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201527f646472657373000000000000000000000000000000000000000000000000000060648201526084016102d8565b6103aa816104e2565b60335473ffffffffffffffffffffffffffffffffffffffff163314610142576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657260448201526064016102d8565b6033805473ffffffffffffffffffffffffffffffffffffffff8381167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b600054610100900460ff166105f0576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e6700000000000000000000000000000000000000000060648201526084016102d8565b610142600054610100900460ff1661068a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e6700000000000000000000000000000000000000000060648201526084016102d8565b610142336104e2565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b600082601f8301126106d357600080fd5b813567ffffffffffffffff808211156106ee576106ee610693565b604051601f83017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f0116810190828211818310171561073457610734610693565b8160405283815286602085880101111561074d57600080fd5b836020870160208301376000602085830101528094505050505092915050565b803573ffffffffffffffffffffffffffffffffffffffff8116811461079157600080fd5b919050565b600080604083850312156107a957600080fd5b823567ffffffffffffffff8111156107c057600080fd5b6107cc858286016106c2565b9250506107db6020840161076d565b90509250929050565b6000602082840312156107f657600080fd5b813567ffffffffffffffff81111561080d57600080fd5b610819848285016106c2565b949350505050565b60006020828403121561083357600080fd5b61083c8261076d565b9392505050565b6000825160005b81811015610864576020818601810151858301520161084a565b50600092019182525091905056fea2646970667358221220d05082af8e0e2cbc9ddc35de7e94b4f45055b3cbd8e60239532b1697a91218c864736f6c63430008120033", + "balance": "0x0" + }, + "0x0000777700000000000000000000000000000001": { + "contractName": "TaikoL2", + "storage": { + "0x0000000000000000000000000000000000000000000000000000000000000032": "0x0000000000000000000000000000000000000000000000000000000000000001", + "0x0000000000000000000000000000000000000000000000000000000000000000": "0x0000000000000000000000000000777700000000000000000000000000000006", + "0x0000000000000000000000000000000000000000000000000000000000000035": "0x68ce81c266ebf073d5146e3a6a2145d4d2c1ed50490002a530826beee087fd9e" + }, + "code": "0x608060405234801561001057600080fd5b50600436106100be5760003560e01c8063975e09a011610076578063c3f909d41161005b578063c3f909d41461019e578063c7b96908146102dd578063ee82ac5e146102e657600080fd5b8063975e09a014610176578063a0ca2d081461018b57600080fd5b806325bf86f2116100a757806325bf86f2146101135780633ab76e9f146101415780635155ce9f1461015f57600080fd5b80630ca4dffd146100c35780631be2bfa714610100575b600080fd5b6100d66100d1366004612415565b6102f9565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020015b60405180910390f35b6100d661010e366004612463565b61030f565b6101336101213660046124ba565b60009081526034602052604090205490565b6040519081526020016100f7565b60005473ffffffffffffffffffffffffffffffffffffffff166100d6565b603654600090815260346020526040902054610133565b6101896101843660046124d3565b610326565b005b610189610199366004612560565b61040f565b6101a6610485565b6040516100f79190815181526020808301519082015260408083015190820152606080830151908201526080808301519082015260a0808301519082015260c0808301519082015260e08083015190820152610100808301519082015261012080830151908201526101408083015190820152610160808301519082015261018080830151908201526101a080830151908201526101c080830151908201526101e080830151908201526102008083015167ffffffffffffffff90811691830191909152610220808401518216908301526102408084015182169083015261026080840151821690830152610280808401518216908301526102a080840151909116908201526102c0808301511515908201526102e080830151151590820152610300918201511515918101919091526103200190565b61013360365481565b6101336102f43660046124ba565b610596565b6000610306468484610677565b90505b92915050565b600061031c848484610677565b90505b9392505050565b3371777735367b36bc9b61c50022d9d0700db4ec14610371576040517f6494e9f700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b3a156103a9576040517f497d3b1500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006103b3610485565b90506103c281868686866107ad565b806102e00151156103d5576103d5610a53565b6103df8585610b5e565b6040517f64b299ff9f8ba674288abb53380419048a4271dda03b837ecba6b40e6ddea4a290600090a25050505050565b6000610419610485565b9050806102e001511561042e5761042e610a53565b6036839055600083815260346020526040908190208390555183907f58313b60ec6c5bfc381e52f0de3ede0faac3cdffea26f7d6bcc3d09b61018691906104789085815260200190565b60405180910390a2505050565b61058660405180610320016040528060008152602001600081526020016000815260200160008152602001600081526020016000815260200160008152602001600081526020016000815260200160008152602001600081526020016000815260200160008152602001600081526020016000815260200160008152602001600067ffffffffffffffff168152602001600067ffffffffffffffff168152602001600067ffffffffffffffff168152602001600067ffffffffffffffff168152602001600067ffffffffffffffff168152602001600067ffffffffffffffff1681526020016000151581526020016000151581526020016000151581525090565b61058e610b80565b468152919050565b60004382106105a757506000919050565b43821080156105c157506105bd610100436125b1565b8210155b156105cb57504090565b5060009081526033602052604090205490565b919050565b73ffffffffffffffffffffffffffffffffffffffff8116610630576040517f9a109b0a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600080547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff92909216919091179055565b60008061068385610d60565b846040516020016106959291906125e8565b60408051601f19818403018152908290526000547fbf40fac100000000000000000000000000000000000000000000000000000000835290925073ffffffffffffffffffffffffffffffffffffffff169063bf40fac1906106fa908490600401612640565b602060405180830381865afa158015610717573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061073b9190612697565b9150826107a55760405173ffffffffffffffffffffffffffffffffffffffff831615159061076d9083906020016126b2565b604051602081830303815290604052906107a35760405162461bcd60e51b815260040161079a9190612640565b60405180910390fd5b505b509392505050565b60e08501518311156107c8576107c38282610e1e565b610a4c565b84516040517f4eb7f19900000000000000000000000000000000000000000000000000000000815273658d9Ff6257D5254FC536d29641E43144Fbe8d8C91634eb7f1999161081d9190889088906004016126f7565b600060405180830381865af492505050801561085b57506040513d6000823e601f3d908101601f19168201604052610858919081019061278b565b60015b61089f573d808015610889576040519150601f19603f3d011682016040523d82523d6000602084013e61088e565b606091505b506108998383610e1e565b50610a4c565b60c086015181515111156108b7576108998383610e1e565b8560a001516108c582610e79565b11156108d5576108998383610e1e565b8051518210610910576040517fb431f3fc00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000816000015183815181106109285761092861292b565b60200260200101519050600160028111156109455761094561295a565b8460028111156109575761095761295a565b036109bf57865160009061096b9083610ecb565b73ffffffffffffffffffffffffffffffffffffffff16146109b8576040517ff8092d1600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5050610a4c565b60028460028111156109d3576109d361295a565b03610a1a578661010001518160600151106109b8576040517ff8092d1600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040517f9343055600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5050505050565b610a5b6122bb565b434660025b6101008111158015610a725750808310155b15610abe57610a8181846125b1565b408460ff610a8f84876125b1565b610a9991906129b8565b60ff8110610aa957610aa961292b565b6020020152610ab7816129cc565b9050610a60565b506000610acc6001846125b1565b90508040610add8383600088610f5c565b60355414610b17576040517fd719258d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8085610b2460ff856129b8565b60ff8110610b3457610b3461292b565b6020020152610b468385600088610f5c565b60355560009182526033602052604090912055505050565b60008282604051610b70929190612a04565b6040518091039020905092915050565b610c8160405180610320016040528060008152602001600081526020016000815260200160008152602001600081526020016000815260200160008152602001600081526020016000815260200160008152602001600081526020016000815260200160008152602001600081526020016000815260200160008152602001600067ffffffffffffffff168152602001600067ffffffffffffffff168152602001600067ffffffffffffffff168152602001600067ffffffffffffffff168152602001600067ffffffffffffffff168152602001600067ffffffffffffffff1681526020016000151581526020016000151581526020016000151581525090565b50604080516103208101825262028c5c81526108016020820152602891810191909152600a606082015260006080820152625b8d8060a0820152604f60c08201526201d4c060e08201526152086101008201526203d090610120820152620e71d9610140820152606461016082015260196101808201526104006101a082018190526101c082018190526101e0820152610190610200820181905260c8610220830152610240820152603c61026082015261070861028082015262278d006102a082015260016102c082018190526102e0820181905261030082015290565b60606000610d6d83610f95565b600101905060008167ffffffffffffffff811115610d8d57610d8d6122da565b6040519080825280601f01601f191660200182016040528015610db7576020820181803683370190505b5090508181016020015b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff017f3031323334353637383961626364656600000000000000000000000000000000600a86061a8153600a8504945084610dc157509392505050565b6000826002811115610e3257610e3261295a565b141580610e3e57508015155b15610e75576040517f11abdc5c00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5050565b8051600090815b8151811015610ec457818181518110610e9b57610e9b61292b565b60200260200101516060015183610eb29190612a14565b9250610ebd816129cc565b9050610e80565b5050919050565b60006001610ed98484611077565b6080840151610ee990601b612a27565b60a085015160c0860151604080516000815260200190819052610f28949392919093845260ff9290921660208401526040830152606082015260800190565b6020604051602081039080840390855afa158015610f4a573d6000803e3d6000fd5b5050604051601f190151949350505050565b600084848484604051602001610f759493929190612a40565b604051602081830303815290604052805190602001209050949350505050565b6000807a184f03e93ff9f4daa797ed6e38ed64bf6a1f0100000000000000008310610fde577a184f03e93ff9f4daa797ed6e38ed64bf6a1f010000000000000000830492506040015b6d04ee2d6d415b85acef8100000000831061100a576d04ee2d6d415b85acef8100000000830492506020015b662386f26fc10000831061102857662386f26fc10000830492506010015b6305f5e1008310611040576305f5e100830492506008015b612710831061105457612710830492506004015b60648310611066576064830492506002015b600a83106103095760010192915050565b60006060826000015160ff1660000361109e576110978360e00151611465565b90506110b8565b6110b56110b08460e001516001611498565b611465565b90505b825160ff1660000361111a5780516009146111155760405162461bcd60e51b815260206004820152601160248201527f696e76616c696420726c70206974656d73000000000000000000000000000000604482015260640161079a565b61121c565b825160ff16600103611177578051600b146111155760405162461bcd60e51b815260206004820152601160248201527f696e76616c696420726c70206974656d73000000000000000000000000000000604482015260640161079a565b825160ff166002036111d4578051600c146111155760405162461bcd60e51b815260206004820152601160248201527f696e76616c696420726c70206974656d73000000000000000000000000000000604482015260640161079a565b60405162461bcd60e51b815260206004820152600e60248201527f696e76616c696420747854797065000000000000000000000000000000000000604482015260640161079a565b825160009060ff161561123c576003825161123791906125b1565b61123f565b81515b67ffffffffffffffff811115611257576112576122da565b60405190808252806020026020018201604052801561128a57816020015b60608152602001906001900390816112755790505b50905060005b815181101561141257845160ff16158015906112b85750600182516112b591906125b1565b81145b15611301576112df8382815181106112d2576112d261292b565b60200260200101516114ce565b8282815181106112f1576112f161292b565b6020026020010181905250611402565b61132b6113268483815181106113195761131961292b565b60200260200101516114d9565b611569565b82828151811061133d5761133d61292b565b6020908102919091010152845160ff1615801561136657506004825161136391906125b1565b81145b1561140257611374866115d8565b82611380836001612a14565b815181106113905761139061292b565b60200260200101819052506113a560006115e6565b826113b1836002612a14565b815181106113c1576113c161292b565b60200260200101819052506113d660006115e6565b826113e2836003612a14565b815181106113f2576113f261292b565b6020026020010181905250611412565b61140b816129cc565b9050611290565b50600061141e826115fe565b855190915060ff16156114545784516040516114429160f81b908390602001612a8b565b60405160208183030381529060405290505b805160209091012095945050505050565b60408051808201825260008082526020918201528151808301909252825182528083019082015260609061030990611642565b6060825182106114b75750604080516020810190915260008152610309565b61030683838486516114c991906125b1565b611841565b6060610309826119c2565b606060008060006114e9856119d8565b9194509250905060008160018111156115045761150461295a565b146115515760405162461bcd60e51b815260206004820152601860248201527f496e76616c696420524c502062797465732076616c75652e0000000000000000604482015260640161079a565b61156085602001518484611d29565b95945050505050565b60608082516001148015611597575060808360008151811061158d5761158d61292b565b016020015160f81c105b156115a3575081610309565b6115af83516080611dd2565b836040516020016115c1929190612ad3565b604051602081830303815290604052905092915050565b606061030961132683611fba565b60606103096113268367ffffffffffffffff16611fba565b6060600061160b83612115565b9050611619815160c0611dd2565b8160405160200161162b929190612ad3565b604051602081830303815290604052915050919050565b6060600080611650846119d8565b9193509091506001905081600181111561166c5761166c61295a565b146116b95760405162461bcd60e51b815260206004820152601760248201527f496e76616c696420524c50206c6973742076616c75652e000000000000000000604482015260640161079a565b6040805160208082526104208201909252600091816020015b60408051808201909152600080825260208201528152602001906001900390816116d25790505090506000835b8651811015611836576020821061177e5760405162461bcd60e51b815260206004820152602a60248201527f50726f766964656420524c50206c6973742065786365656473206d6178206c6960448201527f7374206c656e6774682e00000000000000000000000000000000000000000000606482015260840161079a565b6000806117bb6040518060400160405280858c6000015161179f91906125b1565b8152602001858c602001516117b49190612a14565b90526119d8565b5091509150604051806040016040528083836117d79190612a14565b8152602001848b602001516117ec9190612a14565b8152508585815181106118015761180161292b565b6020908102919091010152611817600185612a14565b93506118238183612a14565b61182d9084612a14565b925050506116ff565b508152949350505050565b60608161184f81601f612a14565b101561189d5760405162461bcd60e51b815260206004820152600e60248201527f736c6963655f6f766572666c6f77000000000000000000000000000000000000604482015260640161079a565b826118a88382612a14565b10156118f65760405162461bcd60e51b815260206004820152600e60248201527f736c6963655f6f766572666c6f77000000000000000000000000000000000000604482015260640161079a565b6119008284612a14565b845110156119505760405162461bcd60e51b815260206004820152601160248201527f736c6963655f6f75744f66426f756e6473000000000000000000000000000000604482015260640161079a565b60608215801561196f57604051915060008252602082016040526119b9565b6040519150601f8416801560200281840101858101878315602002848b0101015b818310156119a8578051835260209283019201611990565b5050858452601f01601f1916604052505b50949350505050565b6060610309826020015160008460000151611d29565b600080600080846000015111611a305760405162461bcd60e51b815260206004820152601860248201527f524c50206974656d2063616e6e6f74206265206e756c6c2e0000000000000000604482015260640161079a565b6020840151805160001a607f8111611a55576000600160009450945094505050611d22565b60b78111611ad1576000611a6a6080836125b1565b905080876000015111611abf5760405162461bcd60e51b815260206004820152601960248201527f496e76616c696420524c502073686f727420737472696e672e00000000000000604482015260640161079a565b60019550935060009250611d22915050565b60bf8111611bc0576000611ae660b7836125b1565b905080876000015111611b3b5760405162461bcd60e51b815260206004820152601f60248201527f496e76616c696420524c50206c6f6e6720737472696e67206c656e6774682e00604482015260640161079a565b600183015160208290036101000a9004611b558183612a14565b885111611ba45760405162461bcd60e51b815260206004820152601860248201527f496e76616c696420524c50206c6f6e6720737472696e672e0000000000000000604482015260640161079a565b611baf826001612a14565b9650945060009350611d2292505050565b60f78111611c3b576000611bd560c0836125b1565b905080876000015111611c2a5760405162461bcd60e51b815260206004820152601760248201527f496e76616c696420524c502073686f7274206c6973742e000000000000000000604482015260640161079a565b600195509350849250611d22915050565b6000611c4860f7836125b1565b905080876000015111611c9d5760405162461bcd60e51b815260206004820152601d60248201527f496e76616c696420524c50206c6f6e67206c697374206c656e6774682e000000604482015260640161079a565b600183015160208290036101000a9004611cb78183612a14565b885111611d065760405162461bcd60e51b815260206004820152601660248201527f496e76616c696420524c50206c6f6e67206c6973742e00000000000000000000604482015260640161079a565b611d11826001612a14565b9650945060019350611d2292505050565b9193909250565b606060008267ffffffffffffffff811115611d4657611d466122da565b6040519080825280601f01601f191660200182016040528015611d70576020820181803683370190505b5090508051600003611d8357905061031f565b8484016020820160005b85811015611da5578281015182820152602001611d8d565b5060006001602087066020036101000a039050808251168119845116178252839450505050509392505050565b6060806038841015611e515760408051600180825281830190925290602082018180368337019050509050611e078385612a27565b60f81b81600081518110611e1d57611e1d61292b565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a905350610306565b600060015b611e608187612b02565b15611e8357611e6e826129cc565b9150611e7c61010082612b16565b9050611e56565b611e8e826001612a14565b67ffffffffffffffff811115611ea657611ea66122da565b6040519080825280601f01601f191660200182016040528015611ed0576020820181803683370190505b509250611edd8583612a27565b611ee8906037612a27565b60f81b83600081518110611efe57611efe61292b565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a905350600190505b8181116107a357610100611f4682846125b1565b611f5290610100612c4d565b611f5c9088612b02565b611f6691906129b8565b60f81b838281518110611f7b57611f7b61292b565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a905350611fb3816129cc565b9050611f32565b6060600082604051602001611fd191815260200190565b604051602081830303815290604052905060005b602081101561203e578181815181106120005761200061292b565b01602001517fff000000000000000000000000000000000000000000000000000000000000001660000361203e57612037816129cc565b9050611fe5565b600061204b8260206125b1565b67ffffffffffffffff811115612063576120636122da565b6040519080825280601f01601f19166020018201604052801561208d576020820181803683370190505b50905060005b81518110156119b95783836120a7816129cc565b9450815181106120b9576120b961292b565b602001015160f81c60f81b8282815181106120d6576120d661292b565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a90535061210e816129cc565b9050612093565b6060815160000361213457505060408051600081526020810190915290565b6000805b8351811015612179578381815181106121535761215361292b565b602002602001015151826121679190612a14565b9150612172816129cc565b9050612138565b60008267ffffffffffffffff811115612194576121946122da565b6040519080825280601f01601f1916602001820160405280156121be576020820181803683370190505b50600092509050602081015b85518310156119b95760008684815181106121e7576121e761292b565b60200260200101519050600060208201905061220583828451612240565b8785815181106122175761221761292b565b6020026020010151518361222b9190612a14565b9250505082612239906129cc565b92506121ca565b8282825b6020811061227c578151835261225b602084612a14565b9250612268602083612a14565b91506122756020826125b1565b9050612244565b905182516020929092036101000a7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0180199091169116179052505050565b60405180611fe0016040528060ff906020820280368337509192915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6040516020810167ffffffffffffffff8111828210171561232c5761232c6122da565b60405290565b604051610100810167ffffffffffffffff8111828210171561232c5761232c6122da565b604051601f8201601f1916810167ffffffffffffffff8111828210171561237f5761237f6122da565b604052919050565b600067ffffffffffffffff8211156123a1576123a16122da565b50601f01601f191660200190565b600082601f8301126123c057600080fd5b81356123d36123ce82612387565b612356565b8181528460208386010111156123e857600080fd5b816020850160208301376000918101602001919091529392505050565b803580151581146105de57600080fd5b6000806040838503121561242857600080fd5b823567ffffffffffffffff81111561243f57600080fd5b61244b858286016123af565b92505061245a60208401612405565b90509250929050565b60008060006060848603121561247857600080fd5b83359250602084013567ffffffffffffffff81111561249657600080fd5b6124a2868287016123af565b9250506124b160408501612405565b90509250925092565b6000602082840312156124cc57600080fd5b5035919050565b600080600080606085870312156124e957600080fd5b843567ffffffffffffffff8082111561250157600080fd5b818701915087601f83011261251557600080fd5b81358181111561252457600080fd5b88602082850101111561253657600080fd5b602092830196509450508501356003811061255057600080fd5b9396929550929360400135925050565b6000806040838503121561257357600080fd5b50508035926020909101359150565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b8181038181111561030957610309612582565b60005b838110156125df5781810151838201526020016125c7565b50506000910152565b600083516125fa8184602088016125c4565b7f2e0000000000000000000000000000000000000000000000000000000000000090830190815283516126348160018401602088016125c4565b01600101949350505050565b602081526000825180602084015261265f8160408501602087016125c4565b601f01601f19169190910160400192915050565b805173ffffffffffffffffffffffffffffffffffffffff811681146105de57600080fd5b6000602082840312156126a957600080fd5b61030682612673565b7f41523a7a65726f416464723a00000000000000000000000000000000000000008152600082516126ea81600c8501602087016125c4565b91909101600c0192915050565b83815260406020820152816040820152818360608301376000818301606090810191909152601f909201601f1916010192915050565b805160ff811681146105de57600080fd5b600082601f83011261274f57600080fd5b815161275d6123ce82612387565b81815284602083860101111561277257600080fd5b6127838260208301602087016125c4565b949350505050565b6000602080838503121561279e57600080fd5b825167ffffffffffffffff808211156127b657600080fd5b81850191508282870312156127ca57600080fd5b6127d2612309565b8251828111156127e157600080fd5b80840193505086601f8401126127f657600080fd5b825182811115612808576128086122da565b8060051b612817868201612356565b918252848101860191868101908a84111561283157600080fd5b87870192505b8383101561291b5782518681111561284e57600080fd5b8701610100818d03601f190181131561286657600080fd5b61286e612332565b6128798b840161272d565b815261288760408401612673565b8b82015260608301518981111561289d57600080fd5b6128ab8f8d8387010161273e565b6040830152506080830151606082015260a06128c881850161272d565b608083015260c0808501518284015260e09150818501518184015250828401519250898311156128f85760008081fd5b6129068f8d8587010161273e565b90820152845250509187019190870190612837565b8452509198975050505050505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b6000826129c7576129c7612989565b500690565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82036129fd576129fd612582565b5060010190565b8183823760009101908152919050565b8082018082111561030957610309612582565b60ff818116838216019081111561030957610309612582565b848152600060208581840152846040840152606083018460005b60ff811015612a7757815183529183019190830190600101612a5a565b505050506120408201905095945050505050565b7fff000000000000000000000000000000000000000000000000000000000000008316815260008251612ac58160018501602087016125c4565b919091016001019392505050565b60008351612ae58184602088016125c4565b835190830190612af98183602088016125c4565b01949350505050565b600082612b1157612b11612989565b500490565b808202811582820484141761030957610309612582565b600181815b80851115612b8657817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff04821115612b6c57612b6c612582565b80851615612b7957918102915b93841c9390800290612b32565b509250929050565b600082612b9d57506001610309565b81612baa57506000610309565b8160018114612bc05760028114612bca57612be6565b6001915050610309565b60ff841115612bdb57612bdb612582565b50506001821b610309565b5060208310610133831016604e8410600b8410161715612c09575081810a610309565b612c138383612b2d565b807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff04821115612c4557612c45612582565b029392505050565b60006103068383612b8e56fea2646970667358221220b0e2d2df211dd589d063e24dc61098a0aec86ea03c1fcd3241c1634bae25d5dd64736f6c63430008120033", + "balance": "0x0" + }, + "0x0000777700000000000000000000000000000004": { + "contractName": "Bridge", + "storage": { + "0x0000000000000000000000000000000000000000000000000000000000000000": "0x0000000000000000000000000000000000000000000000000000000000000001", + "0x0000000000000000000000000000000000000000000000000000000000000001": "0x0000000000000000000000000000000000000000000000000000000000000001", + "0x0000000000000000000000000000000000000000000000000000000000000065": "0x00000000000000000000000019b4f9c381c7927fe33d853e48b560141a380c44", + "0x0000000000000000000000000000000000000000000000000000000000000097": "0x0000000000000000000000000000777700000000000000000000000000000006" + }, + "code": "0x6080604052600436106101635760003560e01c8063715018a6116100c0578063ce70f39b11610074578063f2fde38b11610059578063f2fde38b1461051a578063f98039191461053a578063fee99b221461055a57600080fd5b8063ce70f39b1461048b578063d0496d6a146104ab57600080fd5b806396e17852116100a557806396e1785214610438578063a4444efd1461044b578063bac443e21461046b57600080fd5b8063715018a6146104055780638da5cb5b1461041a57600080fd5b80635075a9d4116101175780635817b0c3116100fc5780635817b0c3146103975780635d0bd986146103c5578063606b5b74146103e557600080fd5b80635075a9d41461034a578063540be6a31461037757600080fd5b80631be2bfa7116101485780631be2bfa7146102cc578063343b643c146102ec5780633ab76e9f1461032c57600080fd5b80630ca4dffd1461026f57806319ab453c146102ac57600080fd5b3661026a576101a86040518060400160405280600b81526020017f746f6b656e5f7661756c74000000000000000000000000000000000000000000815250600161057a565b6001600160a01b0316336001600160a01b03161415801561021a57506102046040518060400160405280600b81526020017f65746865725f7661756c74000000000000000000000000000000000000000000815250600161057a565b6001600160a01b0316336001600160a01b031614155b801561023157506065546001600160a01b03163314155b15610268576040517f8bba088a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b005b600080fd5b34801561027b57600080fd5b5061028f61028a366004613914565b61057a565b6040516001600160a01b0390911681526020015b60405180910390f35b3480156102b857600080fd5b506102686102c7366004613986565b610590565b3480156102d857600080fd5b5061028f6102e73660046139a3565b610729565b3480156102f857600080fd5b5061031c6103073660046139fe565b600090815260cd602052604090205460ff1690565b60405190151581526020016102a3565b34801561033857600080fd5b506097546001600160a01b031661028f565b34801561035657600080fd5b5061036a6103653660046139fe565b61073e565b6040516102a39190613a81565b34801561038357600080fd5b5061031c6103923660046139fe565b610749565b3480156103a357600080fd5b506103b76103b2366004613aa8565b610755565b6040519081526020016102a3565b3480156103d157600080fd5b5061031c6103e03660046139fe565b610768565b3480156103f157600080fd5b506103b76104003660046139fe565b61077b565b34801561041157600080fd5b50610268610786565b34801561042657600080fd5b506065546001600160a01b031661028f565b6103b7610446366004613aa8565b61079a565b34801561045757600080fd5b5061031c610466366004613b26565b6107c8565b34801561047757600080fd5b50610268610486366004613b79565b6107e0565b34801561049757600080fd5b5061031c6104a6366004613b26565b610804565b3480156104b757600080fd5b50604080516060808201835260008083526020808401829052928401528251808201845260ca5480825260cb546001600160a01b0390811683860190815260cc5493870193845286519283525116938101939093525192820192909252016102a3565b34801561052657600080fd5b50610268610535366004613986565b610813565b34801561054657600080fd5b50610268610555366004613be2565b6108bd565b34801561056657600080fd5b50610268610575366004613b79565b6108db565b60006105874684846108f1565b90505b92915050565b600054610100900460ff16158080156105b05750600054600160ff909116105b806105ca5750303b1580156105ca575060005460ff166001145b61065b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a656400000000000000000000000000000000000060648201526084015b60405180910390fd5b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016600117905580156106b957600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff166101001790555b6106c282610a3c565b801561072557600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b5050565b60006107368484846108f1565b949350505050565b600061058a82610a55565b600061058a3083610a78565b600061058a61076383613c18565b610bbd565b60006107743083610bed565b5092915050565b600061058a82610cc5565b61078e610d00565b6107986000610d74565b565b60006107a4610dde565b6107b860c9306107b385613c18565b610e51565b90506107c360018055565b919050565b60006107d73086868686611239565b95945050505050565b6107e8610dde565b6107f660c930858585611435565b6107ff60018055565b505050565b60006107d73086868686611823565b61081b610d00565b6001600160a01b0381166108b1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201527f64647265737300000000000000000000000000000000000000000000000000006064820152608401610652565b6108ba81610d74565b50565b6108c5610dde565b6108d260c9308484611ba6565b61072560018055565b6108e3610dde565b6107f660c930858585611e82565b6000806108fd856124f5565b8460405160200161090f929190613d3e565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152908290526097547fbf40fac10000000000000000000000000000000000000000000000000000000083529092506001600160a01b03169063bf40fac190610985908490600401613de0565b602060405180830381865afa1580156109a2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906109c69190613df3565b915082610a34576040516001600160a01b0383161515906109eb908390602001613e10565b60405160208183030381529060405290610a32576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016106529190613de0565b505b509392505050565b610a44612595565b610a4c612634565b6108ba816126d3565b600080610a6183610cc5565b805490915080600381111561073657610736613a17565b604080517f0ca4dffd0000000000000000000000000000000000000000000000000000000081526004810191909152600e60448201527f7369676e616c5f736572766963650000000000000000000000000000000000006064820152600060248201819052906001600160a01b03841690630ca4dffd90608401602060405180830381865afa158015610b0f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b339190613df3565b6040517f32676bc6000000000000000000000000000000000000000000000000000000008152306004820152602481018490526001600160a01b0391909116906332676bc690604401602060405180830381865afa158015610b99573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105879190613e55565b600081604051602001610bd09190613f65565b604051602081830303815290604052805190602001209050919050565b6040517f1be2bfa70000000000000000000000000000000000000000000000000000000081526004810182905260606024820152600660648201527f627269646765000000000000000000000000000000000000000000000000000060848201526001604482015260009081906001600160a01b03851690631be2bfa79060a401602060405180830381865afa158015610c8b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610caf9190613df3565b6001600160a01b03811615159590945092505050565b6040517f4d4553534147455f5354415455530000000000000000000000000000000000006020820152602e8101829052600090604e01610bd0565b6065546001600160a01b03163314610798576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610652565b606580546001600160a01b038381167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b600260015403610e4a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c006044820152606401610652565b6002600155565b60808101516000906001600160a01b0316610e98576040517fd8c3418000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600080610ea9858560600151610bed565b91509150811580610ebd5750468460600151145b15610ef4576040517fe822b48d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60a08401516001600160a01b03161580610f235750806001600160a01b03168460a001516001600160a01b0316145b15610f5a576040517fb9ad6a0f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008461012001518561010001518660e00151610f779190613fdb565b610f819190613fdb565b9050348114610fbc576040517f9826865c00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b604080517f0ca4dffd0000000000000000000000000000000000000000000000000000000081526004810191909152600b60448201527f65746865725f7661756c740000000000000000000000000000000000000000006064820152600160248201526000906001600160a01b03881690630ca4dffd90608401602060405180830381865afa158015611053573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110779190613df3565b90506001600160a01b0381161561109b5761109b6001600160a01b0382168361274d565b87548860006110a983613fee565b9091555086523360208701524660408701526110c486610bbd565b604080517f0ca4dffd0000000000000000000000000000000000000000000000000000000081526004810191909152600e60448201527f7369676e616c5f736572766963650000000000000000000000000000000000006064820152600060248201529095506001600160a01b03881690630ca4dffd90608401602060405180830381865afa15801561115b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061117f9190613df3565b6001600160a01b03166366ca2bc0866040518263ffffffff1660e01b81526004016111ac91815260200190565b6020604051808303816000875af11580156111cb573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111ef9190614008565b50847f47866f7dacd4a276245be6ed543cae03c9c17eb17e6980cee28e3dd168b7f9f3876040516112209190614021565b60405180910390a2505050509392505050565b60018055565b6040517f1be2bfa70000000000000000000000000000000000000000000000000000000081526004810184905260606024820152600660648201527f627269646765000000000000000000000000000000000000000000000000000060848201526000604482018190529081906001600160a01b03881690631be2bfa79060a401602060405180830381865afa1580156112d7573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112fb9190613df3565b604080517f0ca4dffd0000000000000000000000000000000000000000000000000000000081526004810191909152600e60448201527f7369676e616c5f736572766963650000000000000000000000000000000000006064820152600060248201529091506001600160a01b03881690630ca4dffd90608401602060405180830381865afa158015611392573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906113b69190613df3565b6001600160a01b0316635221f61386838988886040518663ffffffff1660e01b81526004016113e9959493929190614034565b602060405180830381865afa158015611406573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061142a9190613e55565b979650505050505050565b600061144760a0850160808601613986565b6001600160a01b031603611487576040517fd8c3418000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b468360400135146114c4576040517fe822b48d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006114d261076385613c18565b600081815260048801602052604090205490915060ff161515600103611524576040517fafde133500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b611535858286606001358686611823565b61156b576040517f498b0b1d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000818152600487016020526040812080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660011790556115b761010086013560e0870135613fdb565b905080156117c757604080517f0ca4dffd0000000000000000000000000000000000000000000000000000000081526004810191909152600b60448201527f65746865725f7661756c740000000000000000000000000000000000000000006064820152600160248201526000906001600160a01b03881690630ca4dffd90608401602060405180830381865afa158015611656573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061167a9190613df3565b90506001600160a01b03811615611727576001600160a01b03811663ba0bbd956116aa60a0890160808a01613986565b6040517fffffffff0000000000000000000000000000000000000000000000000000000060e084901b1681526001600160a01b03909116600482015260248101859052604401600060405180830381600087803b15801561170a57600080fd5b505af115801561171e573d6000803e3d6000fd5b505050506117c5565b600061173960a0880160808901613986565b6001600160a01b03168360405160006040518083038185875af1925050503d8060008114611783576040519150601f19603f3d011682016040523d82523d6000602084013e611788565b606091505b50509050806117c3576040517ff6664cf100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b505b505b817fea00c741e39d1d9ab1c6703152d71f9da09a782ed4ae128414730dadbb9bd8476117f960a0880160808901613986565b604080516001600160a01b039092168252602082018590520160405180910390a250505050505050565b600046840361185e576040517fe822b48d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000859003611899576040517fa6407c9300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006118a783850185614145565b604080517f0ca4dffd0000000000000000000000000000000000000000000000000000000081526004810191909152600560448201527f7461696b6f00000000000000000000000000000000000000000000000000000060648201526000602482018190529192506001600160a01b03891690630ca4dffd90608401602060405180830381865afa158015611940573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906119649190613df3565b825161010001516040517f25bf86f20000000000000000000000000000000000000000000000000000000081526fffffffffffffffffffffffffffffffff90911660048201526001600160a01b0391909116906325bf86f290602401602060405180830381865afa1580156119dd573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611a019190614008565b9050801580611a1a57508151611a1690612810565b8114155b15611a2a576000925050506107d7565b81516060908101516040517f1be2bfa7000000000000000000000000000000000000000000000000000000008152600481018990526024810192909252600660648301527f627269646765000000000000000000000000000000000000000000000000000060848301526000604483015273B51f0f2bdCbf6cfabB35239921A5c672519F74ba91639603043991906001600160a01b038c1690631be2bfa79060a401602060405180830381865afa158015611ae9573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611b0d9190613df3565b611b168b610cc5565b602087015160405160e086901b7fffffffff00000000000000000000000000000000000000000000000000000000168152611b59949392916003916004016142ea565b602060405180830381865af4158015611b76573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611b9a9190613e55565b98975050505050505050565b6101408201351580611bb55750805b15611c1457611bca60a0830160808401613986565b6001600160a01b0316336001600160a01b031614611c14576040517fd7f4fc9f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000611c2261076384613c18565b90506001611c2f82610a55565b6003811115611c4057611c40613a17565b14611c77576040517f1f6646b500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b604080517f0ca4dffd0000000000000000000000000000000000000000000000000000000081526004810191909152600b60448201527f65746865725f7661756c740000000000000000000000000000000000000000006064820152600160248201526000906001600160a01b03861690630ca4dffd90608401602060405180830381865afa158015611d0e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611d329190613df3565b90506001600160a01b03811615611dbb576040517fd73bb3d000000000000000000000000000000000000000000000000000000000815261010085013560048201526001600160a01b0382169063d73bb3d090602401600060405180830381600087803b158015611da257600080fd5b505af1158015611db6573d6000803e3d6000fd5b505050505b611dc78685845a612835565b15611ddc57611dd78260026129d6565b611e7a565b8215611e5357611ded8260036129d6565b600080611e0060e0870160c08801613986565b6001600160a01b031614611e2357611e1e60e0860160c08701613986565b611e33565b611e3360a0860160808701613986565b9050611e4d6001600160a01b03821661010087013561274d565b50611e7a565b6001600160a01b03811615611e7a57611e7a6001600160a01b03821661010086013561274d565b505050505050565b610140830135158015611eb65750611ea060a0840160808501613986565b6001600160a01b0316336001600160a01b031614155b15611eed576040517fe62d8d6400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b46836060013514611f2a576040517fe822b48d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000611f3861076385613c18565b90506000611f4582610a55565b6003811115611f5657611f56613a17565b14611f8d576040517f2c3b0c4b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b604080517f1be2bfa700000000000000000000000000000000000000000000000000000000815290850135600482015260606024820152600660648201527f62726964676500000000000000000000000000000000000000000000000000006084820152600060448201819052906001600160a01b03871690631be2bfa79060a401602060405180830381865afa15801561202c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906120509190613df3565b604080517f0ca4dffd0000000000000000000000000000000000000000000000000000000081526004810191909152600e60448201527f7369676e616c5f736572766963650000000000000000000000000000000000006064820152600060248201529091506001600160a01b03871690630ca4dffd90608401602060405180830381865afa1580156120e7573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061210b9190613df3565b6001600160a01b0316635221f6138660400135838588886040518663ffffffff1660e01b8152600401612142959493929190614034565b602060405180830381865afa15801561215f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906121839190613e55565b6121b9576040517fa282639800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006101208601356121d461010088013560e0890135613fdb565b6121de9190613fdb565b604080517f0ca4dffd0000000000000000000000000000000000000000000000000000000081526004810191909152600b60448201527f65746865725f7661756c740000000000000000000000000000000000000000006064820152600160248201529091506000906001600160a01b03891690630ca4dffd90608401602060405180830381865afa158015612278573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061229c9190613df3565b90506001600160a01b038116158015906122b65750600082115b1561232f576040517fd73bb3d0000000000000000000000000000000000000000000000000000000008152600481018390526001600160a01b0382169063d73bb3d090602401600060405180830381600087803b15801561231657600080fd5b505af115801561232a573d6000803e3d6000fd5b505050505b60e0870135156123605761236060e088013561235160a08a0160808b01613986565b6001600160a01b03169061274d565b6000803061237460c08b0160a08c01613986565b6001600160a01b031614806123a15750600061239660c08b0160a08c01613986565b6001600160a01b0316145b156123b657506002905061010088013561243c565b60006123c860a08b0160808c01613986565b6001600160a01b0316336001600160a01b0316146123eb578961014001356123ed565b5a5b905060006123fd8d8c8a85612835565b9050801561240e5760029350612439565b600193506001600160a01b03851615612439576124396001600160a01b0386166101008d013561274d565b50505b61244686836129d6565b60008061245960e08c0160c08d01613986565b6001600160a01b03161461247c5761247760e08b0160c08c01613986565b61248c565b61248c60a08b0160808c01613986565b90506001600160a01b03811633036124c5576124c06124b0836101208d0135613fdb565b6001600160a01b0383169061274d565b6124e7565b6124d4336101208c013561274d565b6124e76001600160a01b0382168361274d565b505050505050505050505050565b6060600061250283612a4f565b600101905060008167ffffffffffffffff811115612522576125226137bb565b6040519080825280601f01601f19166020018201604052801561254c576020820181803683370190505b5090508181016020015b600019017f3031323334353637383961626364656600000000000000000000000000000000600a86061a8153600a850494508461255657509392505050565b600054610100900460ff1661262c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401610652565b610798612b31565b600054610100900460ff166126cb576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401610652565b610798612bc8565b6001600160a01b038116612713576040517f9a109b0a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b609780547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b0392909216919091179055565b8015610725576000826001600160a01b03168260405160006040518083038185875af1925050503d80600081146127a0576040519150601f19603f3d011682016040523d82523d6000602084013e6127a5565b606091505b50509050806107ff576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601360248201527f455448207472616e73666572206661696c6564000000000000000000000000006044820152606401610652565b600080612826612821846000612c68565b6130ac565b80516020909101209392505050565b600081600003612871576040517ffe1d2c1200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60405180606001604052808481526020018560200160208101906128959190613986565b6001600160a01b039081168252604087810135602093840152835160018a0155918301516002890180547fffffffffffffffffffffffff00000000000000000000000000000000000000001691909216179055015160038601556128ff60c0850160a08601613986565b6001600160a01b03168261010086013561291d61016088018861434d565b60405161292b9291906143b2565b600060405180830381858888f193505050503d8060008114612969576040519150601f19603f3d011682016040523d82523d6000602084013e61296e565b606091505b505060408051606081018252600180825260208201819052600019919092018190528782018290556002880180547fffffffffffffffffffffffff00000000000000000000000000000000000000001690921790915560039096019590955550929392505050565b8060038111156129e8576129e8613a17565b6129f183610a55565b6003811115612a0257612a02613a17565b1461072557612a1182826130f0565b817f0af4d5247f6a4028d6699afb62871a76b398da1d1a626c8a9b90e0bd5f54c73c8233604051612a439291906143c2565b60405180910390a25050565b6000807a184f03e93ff9f4daa797ed6e38ed64bf6a1f0100000000000000008310612a98577a184f03e93ff9f4daa797ed6e38ed64bf6a1f010000000000000000830492506040015b6d04ee2d6d415b85acef81000000008310612ac4576d04ee2d6d415b85acef8100000000830492506020015b662386f26fc100008310612ae257662386f26fc10000830492506010015b6305f5e1008310612afa576305f5e100830492506008015b6127108310612b0e57612710830492506004015b60648310612b20576064830492506002015b600a831061058a5760010192915050565b600054610100900460ff16611233576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401610652565b600054610100900460ff16612c5f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401610652565b61079833610d74565b61020082015160609015612cd457612c81826011613fdb565b67ffffffffffffffff811115612c9957612c996137bb565b604051908082528060200260200182016040528015612ccc57816020015b6060815260200190600190039081612cb75790505b509050612d44565b6101e083015115612cea57612c81826010613fdb565b612cf582600f613fdb565b67ffffffffffffffff811115612d0d57612d0d6137bb565b604051908082528060200260200182016040528015612d4057816020015b6060815260200190600190039081612d2b5790505b5090505b8251612d4f90613119565b81600081518110612d6257612d626143e6565b6020026020010181905250612d7a8360200151613119565b81600181518110612d8d57612d8d6143e6565b6020026020010181905250612da5836040015161312c565b81600281518110612db857612db86143e6565b6020026020010181905250612dd08360600151613119565b81600381518110612de357612de36143e6565b6020026020010181905250612dfb8360800151613119565b81600481518110612e0e57612e0e6143e6565b6020026020010181905250612e268360a00151613119565b81600581518110612e3957612e396143e6565b6020026020010181905250612e708360c00151604051602001612e5c9190614415565b604051602081830303815290604052613168565b81600681518110612e8357612e836143e6565b6020026020010181905250612e9b8360e001516131d7565b81600781518110612eae57612eae6143e6565b6020026020010181905250612ed98361010001516fffffffffffffffffffffffffffffffff166131d7565b81600881518110612eec57612eec6143e6565b6020026020010181905250612f058361012001516131e5565b81600981518110612f1857612f186143e6565b6020026020010181905250612f318361014001516131e5565b81600a81518110612f4457612f446143e6565b6020026020010181905250612f5d8361016001516131e5565b81600b81518110612f7057612f706143e6565b6020026020010181905250612f89836101800151613168565b81600c81518110612f9c57612f9c6143e6565b6020026020010181905250612fb5836101a00151613119565b81600d81518110612fc857612fc86143e6565b6020026020010181905250613017836101c00151604051602001612e5c919060c09190911b7fffffffffffffffff00000000000000000000000000000000000000000000000016815260080190565b81600e8151811061302a5761302a6143e6565b6020026020010181905250826101e0015160001461306f57613050836101e001516131d7565b81600f81518110613063576130636143e6565b60200260200101819052505b6102008301511561058a57613088836102000151613119565b8160108151811061309b5761309b6143e6565b602002602001018190525092915050565b606060006130b9836131fd565b90506130c7815160c0613333565b816040516020016130d992919061444a565b604051602081830303815290604052915050919050565b60006130fb83610cc5565b9050600082600381111561311157613111613a17565b909155505050565b606061058a6131278361351b565b613168565b604051606082811b7fffffffffffffffffffffffffffffffffffffffff0000000000000000000000001660208301529061058a90603401612e5c565b60608082516001148015613196575060808360008151811061318c5761318c6143e6565b016020015160f81c105b156131a257508161058a565b6131ae83516080613333565b836040516020016131c092919061444a565b604051602081830303815290604052905092915050565b606061058a61312783613603565b606061058a6131278367ffffffffffffffff16613603565b6060815160000361321e576040805160008082526020820190925290610774565b6000805b83518110156132635783818151811061323d5761323d6143e6565b602002602001015151826132519190613fdb565b915061325c81613fee565b9050613222565b60008267ffffffffffffffff81111561327e5761327e6137bb565b6040519080825280601f01601f1916602001820160405280156132a8576020820181803683370190505b50600092509050602081015b855183101561332a5760008684815181106132d1576132d16143e6565b6020026020010151905060006020820190506132ef8382845161375e565b878581518110613301576133016143e6565b602002602001015151836133159190613fdb565b925050508261332390613fee565b92506132b4565b50949350505050565b60608060388410156133b257604080516001808252818301909252906020820181803683370190505090506133688385614479565b60f81b8160008151811061337e5761337e6143e6565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a905350610587565b600060015b6133c18187614492565b156133e4576133cf82613fee565b91506133dd610100826144a6565b90506133b7565b6133ef826001613fdb565b67ffffffffffffffff811115613407576134076137bb565b6040519080825280601f01601f191660200182016040528015613431576020820181803683370190505b50925061343e8583614479565b613449906037614479565b60f81b8360008151811061345f5761345f6143e6565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a905350600190505b818111610a32576101006134a782846144bd565b6134b3906101006145b4565b6134bd9088614492565b6134c791906145c0565b60f81b8382815181106134dc576134dc6143e6565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a90535061351481613fee565b9050613493565b606060008260405160200161353291815260200190565b604080518083037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe001815260208084528383019092529250600091829160208201818036833701905050905060005b815181101561332a57838361359581613fee565b9450815181106135a7576135a76143e6565b602001015160f81c60f81b8282815181106135c4576135c46143e6565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a9053506135fc81613fee565b9050613581565b606060008260405160200161361a91815260200190565b604051602081830303815290604052905060005b602081101561368757818181518110613649576136496143e6565b01602001517fff00000000000000000000000000000000000000000000000000000000000000166000036136875761368081613fee565b905061362e565b60006136948260206144bd565b67ffffffffffffffff8111156136ac576136ac6137bb565b6040519080825280601f01601f1916602001820160405280156136d6576020820181803683370190505b50905060005b815181101561332a5783836136f081613fee565b945081518110613702576137026143e6565b602001015160f81c60f81b82828151811061371f5761371f6143e6565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a90535061375781613fee565b90506136dc565b8282825b6020811061379a5781518352613779602084613fdb565b9250613786602083613fdb565b91506137936020826144bd565b9050613762565b905182516020929092036101000a6000190180199091169116179052505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6040516101a0810167ffffffffffffffff8111828210171561380e5761380e6137bb565b60405290565b6040805190810167ffffffffffffffff8111828210171561380e5761380e6137bb565b604051610220810167ffffffffffffffff8111828210171561380e5761380e6137bb565b600082601f83011261386c57600080fd5b813567ffffffffffffffff80821115613887576138876137bb565b604051601f83017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f011681019082821181831017156138cd576138cd6137bb565b816040528381528660208588010111156138e657600080fd5b836020870160208301376000602085830101528094505050505092915050565b80151581146108ba57600080fd5b6000806040838503121561392757600080fd5b823567ffffffffffffffff81111561393e57600080fd5b61394a8582860161385b565b925050602083013561395b81613906565b809150509250929050565b6001600160a01b03811681146108ba57600080fd5b80356107c381613966565b60006020828403121561399857600080fd5b813561058781613966565b6000806000606084860312156139b857600080fd5b83359250602084013567ffffffffffffffff8111156139d657600080fd5b6139e28682870161385b565b92505060408401356139f381613906565b809150509250925092565b600060208284031215613a1057600080fd5b5035919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b60048110613a7d577f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b9052565b6020810161058a8284613a46565b60006101a08284031215613aa257600080fd5b50919050565b600060208284031215613aba57600080fd5b813567ffffffffffffffff811115613ad157600080fd5b61073684828501613a8f565b60008083601f840112613aef57600080fd5b50813567ffffffffffffffff811115613b0757600080fd5b602083019150836020828501011115613b1f57600080fd5b9250929050565b60008060008060608587031215613b3c57600080fd5b8435935060208501359250604085013567ffffffffffffffff811115613b6157600080fd5b613b6d87828801613add565b95989497509550505050565b600080600060408486031215613b8e57600080fd5b833567ffffffffffffffff80821115613ba657600080fd5b613bb287838801613a8f565b94506020860135915080821115613bc857600080fd5b50613bd586828701613add565b9497909650939450505050565b60008060408385031215613bf557600080fd5b823567ffffffffffffffff811115613c0c57600080fd5b61394a85828601613a8f565b60006101a08236031215613c2b57600080fd5b613c336137ea565b82358152613c436020840161397b565b60208201526040830135604082015260608301356060820152613c686080840161397b565b6080820152613c7960a0840161397b565b60a0820152613c8a60c0840161397b565b60c082015260e083810135908201526101008084013590820152610120808401359082015261014080840135908201526101608084013567ffffffffffffffff80821115613cd757600080fd5b613ce33683880161385b565b83850152610180925082860135915080821115613cff57600080fd5b50613d0c3682870161385b565b918301919091525092915050565b60005b83811015613d35578181015183820152602001613d1d565b50506000910152565b60008351613d50818460208801613d1a565b7f2e000000000000000000000000000000000000000000000000000000000000009083019081528351613d8a816001840160208801613d1a565b01600101949350505050565b60008151808452613dae816020860160208601613d1a565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b6020815260006105876020830184613d96565b600060208284031215613e0557600080fd5b815161058781613966565b7f41523a7a65726f416464723a0000000000000000000000000000000000000000815260008251613e4881600c850160208701613d1a565b91909101600c0192915050565b600060208284031215613e6757600080fd5b815161058781613906565b60006101a0825184526020830151613e9560208601826001600160a01b03169052565b5060408301516040850152606083015160608501526080830151613ec460808601826001600160a01b03169052565b5060a0830151613edf60a08601826001600160a01b03169052565b5060c0830151613efa60c08601826001600160a01b03169052565b5060e0838101519085015261010080840151908501526101208084015190850152610140808401519085015261016080840151818601839052613f3f83870182613d96565b925050506101808084015185830382870152613f5b8382613d96565b9695505050505050565b60408152601460408201527f5441494b4f5f4252494447455f4d45535341474500000000000000000000000060608201526080602082015260006105876080830184613e72565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b8082018082111561058a5761058a613fac565b6000600019820361400157614001613fac565b5060010190565b60006020828403121561401a57600080fd5b5051919050565b6020815260006105876020830184613e72565b8581526001600160a01b038516602082015283604082015260806060820152816080820152818360a0830137600081830160a090810191909152601f9092017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0160101949350505050565b600082601f8301126140b057600080fd5b60405161010080820182811067ffffffffffffffff821117156140d5576140d56137bb565b604052830181858211156140e857600080fd5b845b828110156141025780358252602091820191016140ea565b509195945050505050565b80356fffffffffffffffffffffffffffffffff811681146107c357600080fd5b803567ffffffffffffffff811681146107c357600080fd5b60006020828403121561415757600080fd5b813567ffffffffffffffff8082111561416f57600080fd5b908301906040828603121561418357600080fd5b61418b613814565b82358281111561419a57600080fd5b830161030081880312156141ad57600080fd5b6141b5613837565b81358152602082013560208201526141cf6040830161397b565b6040820152606082013560608201526080820135608082015260a082013560a08201526141ff8860c0840161409f565b60c08201526101c08083013560e08301526101e061421e81850161410d565b61010084015261020061423281860161412d565b610120850152614245610220860161412d565b610140850152614258610240860161412d565b6101608501526102608501358781111561427157600080fd5b61427d8c82880161385b565b610180860152506102808501356101a085015261429d6102a0860161412d565b838501526102c0850135828501526102e08501358185015250505080835250506020830135828111156142cf57600080fd5b6142db8782860161385b565b60208301525095945050505050565b8581526001600160a01b038516602082015283604082015282606082015260a06080820152600061142a60a0830184613d96565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe184360301811261438257600080fd5b83018035915067ffffffffffffffff82111561439d57600080fd5b602001915036819003821315613b1f57600080fd5b8183823760009101908152919050565b604081016143d08285613a46565b6001600160a01b03831660208301529392505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b60008183825b600881101561443a57815183526020928301929091019060010161441b565b5050506101008201905092915050565b6000835161445c818460208801613d1a565b835190830190614470818360208801613d1a565b01949350505050565b60ff818116838216019081111561058a5761058a613fac565b6000826144a1576144a161431e565b500490565b808202811582820484141761058a5761058a613fac565b8181038181111561058a5761058a613fac565b600181815b8085111561450b5781600019048211156144f1576144f1613fac565b808516156144fe57918102915b93841c93908002906144d5565b509250929050565b6000826145225750600161058a565b8161452f5750600061058a565b8160018114614545576002811461454f5761456b565b600191505061058a565b60ff84111561456057614560613fac565b50506001821b61058a565b5060208310610133831016604e8410600b841016171561458e575081810a61058a565b61459883836144d0565b80600019048211156145ac576145ac613fac565b029392505050565b60006105878383614513565b6000826145cf576145cf61431e565b50069056fea2646970667358221220ec239ef73d6cbee8dbd31c663f4221c77b52ed6e7ce663cdda28f4eaa6af115964736f6c63430008120033", + "balance": "0x0" + }, + "0x0000777700000000000000000000000000000002": { + "contractName": "TokenVault", + "storage": { + "0x0000000000000000000000000000000000000000000000000000000000000000": "0x0000000000000000000000000000000000000000000000000000000000000001", + "0x0000000000000000000000000000000000000000000000000000000000000001": "0x0000000000000000000000000000000000000000000000000000000000000001", + "0x0000000000000000000000000000000000000000000000000000000000000065": "0x00000000000000000000000019b4f9c381c7927fe33d853e48b560141a380c44", + "0x0000000000000000000000000000000000000000000000000000000000000097": "0x0000000000000000000000000000777700000000000000000000000000000006" + }, + "code": "0x6080604052600436106100e85760003560e01c8063715018a61161008a5780639aa8605c116100595780639aa8605c146102b0578063c287e578146102e1578063ee1490b214610321578063f2fde38b1461033457600080fd5b8063715018a6146101fe578063780b64f0146102135780638da5cb5b146102725780639754149b1461029057600080fd5b80631be2bfa7116100c65780631be2bfa71461016c57806339da33ba1461018c5780633ab76e9f1461019f57806367090ccf146101bd57600080fd5b80630c6fab82146100ed5780630ca4dffd1461010f57806319ab453c1461014c575b600080fd5b3480156100f957600080fd5b5061010d6101083660046128f5565b610354565b005b34801561011b57600080fd5b5061012f61012a366004612a50565b610609565b6040516001600160a01b0390911681526020015b60405180910390f35b34801561015857600080fd5b5061010d610167366004612aa2565b61061f565b34801561017857600080fd5b5061012f610187366004612abf565b61079e565b61010d61019a366004612b1a565b6107b5565b3480156101ab57600080fd5b506097546001600160a01b031661012f565b3480156101c957600080fd5b5061012f6101d8366004612b98565b60cb6020908152600092835260408084209091529082529020546001600160a01b031681565b34801561020a57600080fd5b5061010d610adb565b34801561021f57600080fd5b5061025361022e366004612bbd565b60cc60205260009081526040902080546001909101546001600160a01b039091169082565b604080516001600160a01b039093168352602083019190915201610143565b34801561027e57600080fd5b506065546001600160a01b031661012f565b34801561029c57600080fd5b5061010d6102ab366004612bd6565b610aef565b3480156102bc57600080fd5b506102d06102cb366004612aa2565b610f16565b604051610143959493929190612cc6565b3480156102ed57600080fd5b506103116102fc366004612aa2565b60c96020526000908152604090205460ff1681565b6040519015158152602001610143565b61010d61032f366004612d15565b611078565b34801561034057600080fd5b5061010d61034f366004612aa2565b611a29565b61035c611ab9565b6040518060400160405280600681526020017f627269646765000000000000000000000000000000000000000000000000000081525061039d816000610609565b6001600160a01b0316336001600160a01b0316146103e7576040517f1b0b999e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000336001600160a01b031663d0496d6a6040518163ffffffff1660e01b8152600401606060405180830381865afa158015610427573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061044b9190612db1565b905061049281604001516040518060400160405280600b81526020017f746f6b656e5f7661756c74000000000000000000000000000000000000000000815250600061079e565b6001600160a01b031681602001516001600160a01b0316146104e0576040517f80962e1c00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600046873503610515576104fa6040880160208901612aa2565b90506105106001600160a01b0382168686611b12565b61059e565b61051e87611bbb565b6040517f42e91bb30000000000000000000000000000000000000000000000000000000081526001600160a01b03878116600483015260248201879052919250908216906342e91bb390604401600060405180830381600087803b15801561058557600080fd5b505af1158015610599573d6000803e3d6000fd5b505050505b815160408084015181519081526001600160a01b0384811660208301529181018790528188169291891691907fe5da926519fc972010fe65b35c1e3339e6dc72b35ffaec203999c2a2a2593eac9060600160405180910390a450505061060360018055565b50505050565b6000610616468484611c1a565b90505b92915050565b600054610100900460ff161580801561063f5750600054600160ff909116105b806106595750303b158015610659575060005460ff166001145b6106d05760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a656400000000000000000000000000000000000060648201526084015b60405180910390fd5b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001179055801561072e57600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff166101001790555b61073782611d2d565b801561079a57600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b5050565b60006107ab848484611c1a565b90505b9392505050565b6107bd611ab9565b6001600160a01b0385161580610824575061080f866040518060400160405280600b81526020017f746f6b656e5f7661756c74000000000000000000000000000000000000000000815250600061079e565b6001600160a01b0316856001600160a01b0316145b1561085b576040517f4694641b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b823411610894576040517fae3718b400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610923604051806101a001604052806000815260200160006001600160a01b03168152602001600081526020016000815260200160006001600160a01b0316815260200160006001600160a01b0316815260200160006001600160a01b031681526020016000815260200160008152602001600081526020016000815260200160608152602001606081525090565b606081018790523360808201526001600160a01b03861660a0820152610140810185905261012081018490526109598434612e13565b60e08201526001600160a01b03831660c08201526101808101829052610100810151156109b2576040517f3dd99f7e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006109f46040518060400160405280600681526020017f62726964676500000000000000000000000000000000000000000000000000008152506000610609565b6001600160a01b03166396e1785234846040518363ffffffff1660e01b8152600401610a209190612e4d565b60206040518083038185885af1158015610a3e573d6000803e3d6000fd5b50505050506040513d601f19601f82011682018060405250810190610a639190612f47565b90508160a001516001600160a01b031682608001516001600160a01b0316827fe2f39179c279514a7b46983846e33f95a561128e0660602a211cc1e61cddb9bd8b8660e00151604051610ac0929190918252602082015260400190565b60405180910390a45050610ad360018055565b505050505050565b610ae3611d46565b610aed6000611da0565b565b610af7611ab9565b6000610b0960a0850160808601612aa2565b6001600160a01b031603610b49576040517f72b41cdf00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b46836040013514610b86576040517f48bc100500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000610bc86040518060400160405280600681526020017f62726964676500000000000000000000000000000000000000000000000000008152506000610609565b90506000816001600160a01b0316635817b0c3866040518263ffffffff1660e01b8152600401610bf89190612ff6565b602060405180830381865afa158015610c15573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c399190612f47565b600081815260cc6020526040902080546001909101549192506001600160a01b03169081610c93576040517f7c6addb700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040517fce70f39b0000000000000000000000000000000000000000000000000000000081526001600160a01b0385169063ce70f39b90610ce290869060608c0135908b908b90600401613114565b602060405180830381865afa158015610cff573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d239190613134565b610d59576040517f45d24f2800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040805180820182526000808252602080830182815287835260cc909152929020905181547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b0390911617815590516001909101558015610e9d576001600160a01b038216600090815260c9602052604090205460ff1615610e79576001600160a01b0382166342e91bb3610dfc60a08a0160808b01612aa2565b6040517fffffffff0000000000000000000000000000000000000000000000000000000060e084901b1681526001600160a01b03909116600482015260248101849052604401600060405180830381600087803b158015610e5c57600080fd5b505af1158015610e70573d6000803e3d6000fd5b50505050610e9d565b610e9d610e8c60a0890160808a01612aa2565b6001600160a01b0384169083611b12565b610ead60a0880160808901612aa2565b6001600160a01b0316837fc5d9f7cd7998e24ecf12ad69eca9339764e2cb13788d5d9616f502601b219af68484604051610efc9291906001600160a01b03929092168252602082015260400190565b60405180910390a350505050610f1160018055565b505050565b60ca6020526000908152604090208054600182015460028301805492936001600160a01b038316937401000000000000000000000000000000000000000090930460ff1692909190610f6790613151565b80601f0160208091040260200160405190810160405280929190818152602001828054610f9390613151565b8015610fe05780601f10610fb557610100808354040283529160200191610fe0565b820191906000526020600020905b815481529060010190602001808311610fc357829003601f168201915b505050505090806003018054610ff590613151565b80601f016020809104026020016040519081016040528092919081815260200182805461102190613151565b801561106e5780601f106110435761010080835404028352916020019161106e565b820191906000526020600020905b81548152906001019060200180831161105157829003601f168201915b5050505050905085565b611080611ab9565b6001600160a01b03871615806110e757506110d2886040518060400160405280600b81526020017f746f6b656e5f7661756c74000000000000000000000000000000000000000000815250600061079e565b6001600160a01b0316876001600160a01b0316145b1561111e576040517f4694641b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6001600160a01b03861661115e576040517f7c6addb700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b84600003611198576040517f015f093200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040805160a08101825260008082526020820181905291810191909152606080820181905260808201526001600160a01b038716600090815260c9602052604081205460ff1615611432576040517f77be18a8000000000000000000000000000000000000000000000000000000008152336004820152602481018890526001600160a01b038916906377be18a890604401600060405180830381600087803b15801561124457600080fd5b505af1158015611258573d6000803e3d6000fd5b505050506001600160a01b03888116600090815260ca6020908152604091829020825160a081018452815481526001820154948516928101929092527401000000000000000000000000000000000000000090930460ff16918101919091526002820180549192916060840191906112cf90613151565b80601f01602080910402602001604051908101604052809291908181526020018280546112fb90613151565b80156113485780601f1061131d57610100808354040283529160200191611348565b820191906000526020600020905b81548152906001019060200180831161132b57829003601f168201915b5050505050815260200160038201805461136190613151565b80601f016020809104026020016040519081016040528092919081815260200182805461138d90613151565b80156113da5780601f106113af576101008083540402835291602001916113da565b820191906000526020600020905b8154815290600101906020018083116113bd57829003601f168201915b5050509190925250505060208101519092506001600160a01b031661142b576040517ff91680d400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b50856116c4565b60008890506040518060a001604052804681526020018a6001600160a01b03168152602001826001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa158015611495573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906114b991906131b3565b60ff168152602001826001600160a01b03166395d89b416040518163ffffffff1660e01b8152600401600060405180830381865afa1580156114ff573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405261152791908101906131d0565b8152602001826001600160a01b03166306fdde036040518163ffffffff1660e01b8152600401600060405180830381865afa15801561156a573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405261159291908101906131d0565b90526040517f70a082310000000000000000000000000000000000000000000000000000000081523060048201529093506000906001600160a01b038316906370a0823190602401602060405180830381865afa1580156115f7573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061161b9190612f47565b90506116326001600160a01b03831633308c611e0a565b6040517f70a0823100000000000000000000000000000000000000000000000000000000815230600482015281906001600160a01b038416906370a0823190602401602060405180830381865afa158015611691573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906116b59190612f47565b6116bf9190612e13565b925050505b611753604051806101a001604052806000815260200160006001600160a01b03168152602001600081526020016000815260200160006001600160a01b0316815260200160006001600160a01b0316815260200160006001600160a01b031681526020016000815260200160008152602001600081526020016000815260200160608152602001606081525090565b606081018b905233608082015260408051808201909152600b81527f746f6b656e5f7661756c7400000000000000000000000000000000000000000060208201526117a1908c90600061079e565b6001600160a01b031660a082015260808101516040517f0c6fab8200000000000000000000000000000000000000000000000000000000916117ec918691908e908790602401613247565b60408051601f198184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff00000000000000000000000000000000000000000000000000000000909316929092179091526101608201526101408101879052610120810186905261186b8634612e13565b60e08201526001600160a01b03851660c0820152610180810184905260408051808201909152600681527f627269646765000000000000000000000000000000000000000000000000000060208201526000906118c89082610609565b6001600160a01b03166396e1785234846040518363ffffffff1660e01b81526004016118f49190612e4d565b60206040518083038185885af1158015611912573d6000803e3d6000fd5b50505050506040513d601f19601f820116820180604052508101906119379190612f47565b905060405180604001604052808b6001600160a01b031681526020018481525060cc600083815260200190815260200160002060008201518160000160006101000a8154816001600160a01b0302191690836001600160a01b03160217905550602082015181600101559050508a6001600160a01b031682608001516001600160a01b0316827f325cab7553038374e17f39bb45e2a2c90f66c6a52798cb5f95c20d94c11c95e28f8e88604051611a0a939291909283526001600160a01b03919091166020830152604082015260600190565b60405180910390a450505050611a1f60018055565b5050505050505050565b611a31611d46565b6001600160a01b038116611aad5760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201527f646472657373000000000000000000000000000000000000000000000000000060648201526084016106c7565b611ab681611da0565b50565b600260015403611b0b5760405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c0060448201526064016106c7565b6002600155565b6040516001600160a01b038316602482015260448101829052610f119084907fa9059cbb00000000000000000000000000000000000000000000000000000000906064015b60408051601f198184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff0000000000000000000000000000000000000000000000000000000090931692909217909152611e5b565b8035600090815260cb60209081526040808320839290918391611be2918701908701612aa2565b6001600160a01b0390811682526020820192909252604001600020541690508061061957611c0f83611f40565b6107ae565b60018055565b600080611c26856121f7565b84604051602001611c389291906132fe565b60408051601f19818403018152908290526097547fbf40fac10000000000000000000000000000000000000000000000000000000083529092506001600160a01b03169063bf40fac190611c90908490600401613356565b602060405180830381865afa158015611cad573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611cd19190613369565b915082611d25576040516001600160a01b038316151590611cf6908390602001613386565b60405160208183030381529060405290611d235760405162461bcd60e51b81526004016106c79190613356565b505b509392505050565b611d356122b5565b611d3d61233a565b611ab6816123bf565b6065546001600160a01b03163314610aed5760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657260448201526064016106c7565b606580546001600160a01b038381167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b6040516001600160a01b03808516602483015283166044820152606481018290526106039085907f23b872dd0000000000000000000000000000000000000000000000000000000090608401611b57565b6000611eb0826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b03166124399092919063ffffffff16565b805190915015610f115780806020019051810190611ece9190613134565b610f115760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f7420737563636565640000000000000000000000000000000000000000000060648201526084016106c7565b6000611fd5818335611f586040860160208701612aa2565b604051602001611f9792919091825260601b7fffffffffffffffffffffffffffffffffffffffff00000000000000000000000016602082015260340190565b6040516020818303038152906040528051906020012060405180602001611fbd906128c3565b601f1982820381018352601f90910116604052612448565b6097549091506001600160a01b0380831691636c0db62b9116611ffe6040860160208701612aa2565b853561201060608801604089016133cb565b61201d60608901896133e8565b61202a60808b018b6133e8565b60405161203e9291908d359060200161344d565b6040516020818303038152906040526040518863ffffffff1660e01b815260040161206f97969594939291906134d0565b600060405180830381600087803b15801561208957600080fd5b505af115801561209d573d6000803e3d6000fd5b5050506001600160a01b038216600090815260c96020908152604080832080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016600117905560ca90915290208391506120f8828261366f565b50508135600090815260cb6020908152604080832084939092909161212291908701908701612aa2565b6001600160a01b03166001600160a01b0316815260200190815260200160002060006101000a8154816001600160a01b0302191690836001600160a01b03160217905550806001600160a01b03168260200160208101906121839190612aa2565b6001600160a01b031683357f9e465b29e576a3e01584e31d607353f21b80c055e813af907c0a495f6cf4f7bc6121bc60608701876133e8565b6121c960808901896133e8565b6121d960608b0160408c016133cb565b6040516121ea95949392919061371d565b60405180910390a4919050565b606060006122048361254c565b600101905060008167ffffffffffffffff81111561222457612224612964565b6040519080825280601f01601f19166020018201604052801561224e576020820181803683370190505b5090508181016020015b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff017f3031323334353637383961626364656600000000000000000000000000000000600a86061a8153600a850494508461225857509392505050565b600054610100900460ff166123325760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e6700000000000000000000000000000000000000000060648201526084016106c7565b610aed61262e565b600054610100900460ff166123b75760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e6700000000000000000000000000000000000000000060648201526084016106c7565b610aed6126ab565b6001600160a01b0381166123ff576040517f9a109b0a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b609780547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b0392909216919091179055565b60606107ab8484600085612731565b60008347101561249a5760405162461bcd60e51b815260206004820152601d60248201527f437265617465323a20696e73756666696369656e742062616c616e636500000060448201526064016106c7565b81516000036124eb5760405162461bcd60e51b815260206004820181905260248201527f437265617465323a2062797465636f6465206c656e677468206973207a65726f60448201526064016106c7565b8282516020840186f590506001600160a01b0381166107ae5760405162461bcd60e51b815260206004820152601960248201527f437265617465323a204661696c6564206f6e206465706c6f790000000000000060448201526064016106c7565b6000807a184f03e93ff9f4daa797ed6e38ed64bf6a1f0100000000000000008310612595577a184f03e93ff9f4daa797ed6e38ed64bf6a1f010000000000000000830492506040015b6d04ee2d6d415b85acef810000000083106125c1576d04ee2d6d415b85acef8100000000830492506020015b662386f26fc1000083106125df57662386f26fc10000830492506010015b6305f5e10083106125f7576305f5e100830492506008015b612710831061260b57612710830492506004015b6064831061261d576064830492506002015b600a83106106195760010192915050565b600054610100900460ff16611c145760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e6700000000000000000000000000000000000000000060648201526084016106c7565b600054610100900460ff166127285760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e6700000000000000000000000000000000000000000060648201526084016106c7565b610aed33611da0565b6060824710156127a95760405162461bcd60e51b815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f60448201527f722063616c6c000000000000000000000000000000000000000000000000000060648201526084016106c7565b600080866001600160a01b031685876040516127c5919061375a565b60006040518083038185875af1925050503d8060008114612802576040519150601f19603f3d011682016040523d82523d6000602084013e612807565b606091505b509150915061281887838387612825565b925050505b949350505050565b6060831561289457825160000361288d576001600160a01b0385163b61288d5760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e747261637400000060448201526064016106c7565b508161281d565b61281d83838151156128a95781518083602001fd5b8060405162461bcd60e51b81526004016106c79190613356565b6121518061377783390190565b6001600160a01b0381168114611ab657600080fd5b80356128f0816128d0565b919050565b6000806000806080858703121561290b57600080fd5b843567ffffffffffffffff81111561292257600080fd5b850160a0818803121561293457600080fd5b93506020850135612944816128d0565b92506040850135612954816128d0565b9396929550929360600135925050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b604051601f8201601f1916810167ffffffffffffffff811182821017156129bc576129bc612964565b604052919050565b600067ffffffffffffffff8211156129de576129de612964565b50601f01601f191660200190565b600082601f8301126129fd57600080fd5b8135612a10612a0b826129c4565b612993565b818152846020838601011115612a2557600080fd5b816020850160208301376000918101602001919091529392505050565b8015158114611ab657600080fd5b60008060408385031215612a6357600080fd5b823567ffffffffffffffff811115612a7a57600080fd5b612a86858286016129ec565b9250506020830135612a9781612a42565b809150509250929050565b600060208284031215612ab457600080fd5b81356107ae816128d0565b600080600060608486031215612ad457600080fd5b83359250602084013567ffffffffffffffff811115612af257600080fd5b612afe868287016129ec565b9250506040840135612b0f81612a42565b809150509250925092565b60008060008060008060c08789031215612b3357600080fd5b863595506020870135612b45816128d0565b945060408701359350606087013592506080870135612b63816128d0565b915060a087013567ffffffffffffffff811115612b7f57600080fd5b612b8b89828a016129ec565b9150509295509295509295565b60008060408385031215612bab57600080fd5b823591506020830135612a97816128d0565b600060208284031215612bcf57600080fd5b5035919050565b600080600060408486031215612beb57600080fd5b833567ffffffffffffffff80821115612c0357600080fd5b908501906101a08288031215612c1857600080fd5b90935060208501359080821115612c2e57600080fd5b818601915086601f830112612c4257600080fd5b813581811115612c5157600080fd5b876020828501011115612c6357600080fd5b6020830194508093505050509250925092565b60005b83811015612c91578181015183820152602001612c79565b50506000910152565b60008151808452612cb2816020860160208601612c76565b601f01601f19169290920160200192915050565b8581526001600160a01b038516602082015260ff8416604082015260a060608201526000612cf760a0830185612c9a565b8281036080840152612d098185612c9a565b98975050505050505050565b600080600080600080600080610100898b031215612d3257600080fd5b883597506020890135612d44816128d0565b96506040890135612d54816128d0565b9550606089013594506080890135935060a0890135925060c0890135612d79816128d0565b915060e089013567ffffffffffffffff811115612d9557600080fd5b612da18b828c016129ec565b9150509295985092959890939650565b600060608284031215612dc357600080fd5b6040516060810181811067ffffffffffffffff82111715612de657612de6612964565b604052825181526020830151612dfb816128d0565b60208201526040928301519281019290925250919050565b81810381811115610619577f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b602081528151602082015260006020830151612e7460408401826001600160a01b03169052565b5060408301516060830152606083015160808301526080830151612ea360a08401826001600160a01b03169052565b5060a08301516001600160a01b03811660c08401525060c08301516001600160a01b03811660e08401525060e0830151610100838101919091528301516101208084019190915283015161014080840191909152830151610160808401919091528301516101a0610180808501829052612f216101c0860184612c9a565b90860151858203601f190183870152909250612f3d8382612c9a565b9695505050505050565b600060208284031215612f5957600080fd5b5051919050565b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe1843603018112612f9557600080fd5b830160208101925035905067ffffffffffffffff811115612fb557600080fd5b803603821315612fc457600080fd5b9250929050565b818352818160208501375060006020828401015260006020601f19601f840116840101905092915050565b6020815281356020820152600061300f602084016128e5565b6001600160a01b038116604084015250604083013560608301526060830135608083015261303f608084016128e5565b6001600160a01b03811660a08401525061305b60a084016128e5565b6001600160a01b03811660c08401525061307760c084016128e5565b6001600160a01b03811660e08401525061010060e0840135818401526101208185013581850152610140915080850135828501525061016081850135818501526130c381860186612f60565b925090506101a061018081818701526130e16101c087018585612fcb565b93506130ef81880188612f60565b93509050601f198685030182870152613109848483612fcb565b979650505050505050565b848152836020820152606060408201526000612f3d606083018486612fcb565b60006020828403121561314657600080fd5b81516107ae81612a42565b600181811c9082168061316557607f821691505b60208210810361319e577f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b50919050565b60ff81168114611ab657600080fd5b6000602082840312156131c557600080fd5b81516107ae816131a4565b6000602082840312156131e257600080fd5b815167ffffffffffffffff8111156131f957600080fd5b8201601f8101841361320a57600080fd5b8051613218612a0b826129c4565b81815285602083850101111561322d57600080fd5b61323e826020830160208601612c76565b95945050505050565b6080815284516080820152600060208601516001600160a01b0380821660a085015260ff60408901511660c08501526060880151915060a060e0850152613292610120850183612c9a565b915060808801517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff80858403016101008601526132ce8382612c9a565b9188166020860152506001600160a01b038616604085015291506132ef9050565b82606083015295945050505050565b60008351613310818460208801612c76565b7f2e00000000000000000000000000000000000000000000000000000000000000908301908152835161334a816001840160208801612c76565b01600101949350505050565b6020815260006106166020830184612c9a565b60006020828403121561337b57600080fd5b81516107ae816128d0565b7f41523a7a65726f416464723a00000000000000000000000000000000000000008152600082516133be81600c850160208701612c76565b91909101600c0192915050565b6000602082840312156133dd57600080fd5b81356107ae816131a4565b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe184360301811261341d57600080fd5b83018035915067ffffffffffffffff82111561343857600080fd5b602001915036819003821315612fc457600080fd5b828482377f286272696467656400000000000000000000000000000000000000000000000092019182527ff09f8c88000000000000000000000000000000000000000000000000000000006008830152600c8201527f2900000000000000000000000000000000000000000000000000000000000000602c820152602d01919050565b60006001600160a01b03808a16835280891660208401525086604083015260ff8616606083015260c0608083015261350c60c083018587612fcb565b82810360a084015261351e8185612c9a565b9a9950505050505050505050565b601f821115610f1157600081815260208120601f850160051c810160208610156135535750805b601f850160051c820191505b81811015610ad35782815560010161355f565b67ffffffffffffffff83111561358a5761358a612964565b61359e836135988354613151565b8361352c565b6000601f8411600181146135f057600085156135ba5750838201355b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600387901b1c1916600186901b178355613668565b600083815260209020601f19861690835b828110156136215786850135825560209485019460019092019101613601565b508682101561365c577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff60f88860031b161c19848701351681555b505060018560011b0183555b5050505050565b81358155600181016020830135613685816128d0565b81546040850135613695816131a4565b74ff00000000000000000000000000000000000000008160a01b166001600160a01b0384167fffffffffffffffffffffff000000000000000000000000000000000000000000841617178455505050506136f260608301836133e8565b613700818360028601613572565b505061370f60808301836133e8565b610603818360038601613572565b606081526000613731606083018789612fcb565b8281036020840152613744818688612fcb565b91505060ff831660408301529695505050505050565b6000825161376c818460208701612c76565b919091019291505056fe608060405234801561001057600080fd5b50612131806100206000396000f3fe608060405234801561001057600080fd5b506004361061018d5760003560e01c806367e828bf116100e35780638da5cb5b1161008c578063a9059cbb11610066578063a9059cbb146103b4578063dd62ed3e146103c7578063f2fde38b1461040d57600080fd5b80638da5cb5b1461037b57806395d89b4114610399578063a457c2d7146103a157600080fd5b8063715018a6116100bd578063715018a61461034057806377be18a8146103485780637cf8ed0d1461035b57600080fd5b806367e828bf146102a75780636c0db62b146102f757806370a082311461030a57600080fd5b806323b872dd116101455780633ab76e9f1161011f5780633ab76e9f1461026b57806342e91bb31461028957806349d126051461029e57600080fd5b806323b872dd14610230578063313ce56714610243578063395093511461025857600080fd5b80630ca4dffd116101765780630ca4dffd146101d357806318160ddd1461020b5780631be2bfa71461021d57600080fd5b806306fdde0314610192578063095ea7b3146101b0575b600080fd5b61019a610420565b6040516101a79190611abd565b60405180910390f35b6101c36101be366004611b30565b6104b2565b60405190151581526020016101a7565b6101e66101e1366004611c4b565b6104cc565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016101a7565b60cb545b6040519081526020016101a7565b6101e661022b366004611c99565b6104e0565b6101c361023e366004611cf0565b6104f5565b60ce5460405160ff90911681526020016101a7565b6101c3610266366004611b30565b610551565b60975473ffffffffffffffffffffffffffffffffffffffff166101e6565b61029c610297366004611b30565b61059d565b005b61020f60fc5481565b6102cb60fb5460fc5473ffffffffffffffffffffffffffffffffffffffff90911691565b6040805173ffffffffffffffffffffffffffffffffffffffff90931683526020830191909152016101a7565b61029c610305366004611d31565b6106a1565b61020f610318366004611ddb565b73ffffffffffffffffffffffffffffffffffffffff16600090815260c9602052604090205490565b61029c6108eb565b61029c610356366004611b30565b6108ff565b60fb546101e69073ffffffffffffffffffffffffffffffffffffffff1681565b60655473ffffffffffffffffffffffffffffffffffffffff166101e6565b61019a6109f6565b6101c36103af366004611b30565b610a05565b6101c36103c2366004611b30565b610ac7565b61020f6103d5366004611df8565b73ffffffffffffffffffffffffffffffffffffffff918216600090815260ca6020908152604080832093909416825291909152205490565b61029c61041b366004611ddb565b610b22565b606060cc805461042f90611e31565b80601f016020809104026020016040519081016040528092919081815260200182805461045b90611e31565b80156104a85780601f1061047d576101008083540402835291602001916104a8565b820191906000526020600020905b81548152906001019060200180831161048b57829003601f168201915b5050505050905090565b6000336104c0818585610bbf565b60019150505b92915050565b60006104d9468484610d3e565b9392505050565b60006104ed848484610d3e565b949350505050565b60003073ffffffffffffffffffffffffffffffffffffffff841603610546576040517f669bcddc00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6104ed848484610e89565b33600081815260ca6020908152604080832073ffffffffffffffffffffffffffffffffffffffff871684529091528120549091906104c09082908690610598908790611eb3565b610bbf565b6040518060400160405280600b81526020017f746f6b656e5f7661756c740000000000000000000000000000000000000000008152506105de8160006104cc565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614610642576040517f1b0b999e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61064c8383610ea2565b8273ffffffffffffffffffffffffffffffffffffffff167f397b33b307fc137878ebfc75b295289ec0ee25a31bb5bf034f33256fe8ea2aa68360405161069491815260200190565b60405180910390a2505050565b600054610100900460ff16158080156106c15750600054600160ff909116105b806106db5750303b1580156106db575060005460ff166001145b6107525760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a656400000000000000000000000000000000000060648201526084015b60405180910390fd5b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016600117905580156107b057600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff166101001790555b73ffffffffffffffffffffffffffffffffffffffff861615806107d1575084155b806107db57504685145b806107e557508251155b806107ef57508151155b15610826576040517ff12d598000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61082f87610f60565b61083a828486610f79565b60fb80547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff881617905560fc85905580156108e257600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b50505050505050565b6108f3611006565b6108fd600061106d565b565b6040518060400160405280600b81526020017f746f6b656e5f7661756c740000000000000000000000000000000000000000008152506109408160006104cc565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16146109a4576040517f1b0b999e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6109ae83836110e4565b8273ffffffffffffffffffffffffffffffffffffffff167f9b5b9a05e4726d8bb959f1440e05c6b8109443f2083bc4e386237d76545265538360405161069491815260200190565b606060cd805461042f90611e31565b33600081815260ca6020908152604080832073ffffffffffffffffffffffffffffffffffffffff8716845290915281205490919083811015610aaf5760405162461bcd60e51b815260206004820152602560248201527f45524332303a2064656372656173656420616c6c6f77616e63652062656c6f7760448201527f207a65726f0000000000000000000000000000000000000000000000000000006064820152608401610749565b610abc8286868403610bbf565b506001949350505050565b60003073ffffffffffffffffffffffffffffffffffffffff841603610b18576040517f669bcddc00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6104d98383611255565b610b2a611006565b73ffffffffffffffffffffffffffffffffffffffff8116610bb35760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201527f64647265737300000000000000000000000000000000000000000000000000006064820152608401610749565b610bbc8161106d565b50565b73ffffffffffffffffffffffffffffffffffffffff8316610c475760405162461bcd60e51b8152602060048201526024808201527f45524332303a20617070726f76652066726f6d20746865207a65726f2061646460448201527f72657373000000000000000000000000000000000000000000000000000000006064820152608401610749565b73ffffffffffffffffffffffffffffffffffffffff8216610cd05760405162461bcd60e51b815260206004820152602260248201527f45524332303a20617070726f766520746f20746865207a65726f20616464726560448201527f73730000000000000000000000000000000000000000000000000000000000006064820152608401610749565b73ffffffffffffffffffffffffffffffffffffffff838116600081815260ca602090815260408083209487168084529482529182902085905590518481527f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925910160405180910390a3505050565b600080610d4a85611263565b84604051602001610d5c929190611ec6565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152908290526097547fbf40fac100000000000000000000000000000000000000000000000000000000835290925073ffffffffffffffffffffffffffffffffffffffff169063bf40fac190610ddf908490600401611abd565b602060405180830381865afa158015610dfc573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e209190611f1e565b915082610e815760405173ffffffffffffffffffffffffffffffffffffffff8316151590610e52908390602001611f3b565b60405160208183030381529060405290610e7f5760405162461bcd60e51b81526004016107499190611abd565b505b509392505050565b600033610e97858285611321565b610abc8585856113de565b73ffffffffffffffffffffffffffffffffffffffff8216610f055760405162461bcd60e51b815260206004820152601f60248201527f45524332303a206d696e7420746f20746865207a65726f2061646472657373006044820152606401610749565b8060cb6000828254610f179190611eb3565b909155505073ffffffffffffffffffffffffffffffffffffffff8216600090815260c9602052604081208054839290610f51908490611eb3565b90915550610f5c9050565b5050565b610f68611643565b610f706116c8565b610bbc8161174d565b600054610100900460ff16610ff65760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401610749565b6110018383836117e1565b505050565b60655473ffffffffffffffffffffffffffffffffffffffff1633146108fd5760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610749565b6065805473ffffffffffffffffffffffffffffffffffffffff8381167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b73ffffffffffffffffffffffffffffffffffffffff821661116d5760405162461bcd60e51b815260206004820152602160248201527f45524332303a206275726e2066726f6d20746865207a65726f2061646472657360448201527f73000000000000000000000000000000000000000000000000000000000000006064820152608401610749565b73ffffffffffffffffffffffffffffffffffffffff8216600090815260c96020526040902054818110156112095760405162461bcd60e51b815260206004820152602260248201527f45524332303a206275726e20616d6f756e7420657863656564732062616c616e60448201527f63650000000000000000000000000000000000000000000000000000000000006064820152608401610749565b73ffffffffffffffffffffffffffffffffffffffff8316600090815260c960205260408120838303905560cb8054849290611245908490611f80565b9091555061100190508360008483565b6000336104c08185856113de565b60606000611270836118ae565b600101905060008167ffffffffffffffff81111561129057611290611b5c565b6040519080825280601f01601f1916602001820160405280156112ba576020820181803683370190505b5090508181016020015b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff017f3031323334353637383961626364656600000000000000000000000000000000600a86061a8153600a85049450846112c457509392505050565b73ffffffffffffffffffffffffffffffffffffffff838116600090815260ca60209081526040808320938616835292905220547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff81146113d857818110156113cb5760405162461bcd60e51b815260206004820152601d60248201527f45524332303a20696e73756666696369656e7420616c6c6f77616e63650000006044820152606401610749565b6113d88484848403610bbf565b50505050565b73ffffffffffffffffffffffffffffffffffffffff83166114675760405162461bcd60e51b815260206004820152602560248201527f45524332303a207472616e736665722066726f6d20746865207a65726f20616460448201527f64726573730000000000000000000000000000000000000000000000000000006064820152608401610749565b73ffffffffffffffffffffffffffffffffffffffff82166114f05760405162461bcd60e51b815260206004820152602360248201527f45524332303a207472616e7366657220746f20746865207a65726f206164647260448201527f65737300000000000000000000000000000000000000000000000000000000006064820152608401610749565b73ffffffffffffffffffffffffffffffffffffffff8316600090815260c960205260409020548181101561158c5760405162461bcd60e51b815260206004820152602660248201527f45524332303a207472616e7366657220616d6f756e742065786365656473206260448201527f616c616e636500000000000000000000000000000000000000000000000000006064820152608401610749565b73ffffffffffffffffffffffffffffffffffffffff808516600090815260c960205260408082208585039055918516815290812080548492906115d0908490611eb3565b925050819055508273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef8460405161163691815260200190565b60405180910390a36113d8565b600054610100900460ff166116c05760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401610749565b6108fd611990565b600054610100900460ff166117455760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401610749565b6108fd611a13565b73ffffffffffffffffffffffffffffffffffffffff811661179a576040517f9a109b0a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b609780547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff92909216919091179055565b600054610100900460ff1661185e5760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401610749565b60cc61186a8482611fe1565b5060cd6118778382611fe1565b5060ce80547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660ff929092169190911790555050565b6000807a184f03e93ff9f4daa797ed6e38ed64bf6a1f01000000000000000083106118f7577a184f03e93ff9f4daa797ed6e38ed64bf6a1f010000000000000000830492506040015b6d04ee2d6d415b85acef81000000008310611923576d04ee2d6d415b85acef8100000000830492506020015b662386f26fc10000831061194157662386f26fc10000830492506010015b6305f5e1008310611959576305f5e100830492506008015b612710831061196d57612710830492506004015b6064831061197f576064830492506002015b600a83106104c65760010192915050565b600054610100900460ff16611a0d5760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401610749565b60018055565b600054610100900460ff16611a905760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401610749565b6108fd3361106d565b60005b83811015611ab4578181015183820152602001611a9c565b50506000910152565b6020815260008251806020840152611adc816040850160208701611a99565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169190910160400192915050565b73ffffffffffffffffffffffffffffffffffffffff81168114610bbc57600080fd5b60008060408385031215611b4357600080fd5b8235611b4e81611b0e565b946020939093013593505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b600082601f830112611b9c57600080fd5b813567ffffffffffffffff80821115611bb757611bb7611b5c565b604051601f83017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f01168101908282118183101715611bfd57611bfd611b5c565b81604052838152866020858801011115611c1657600080fd5b836020870160208301376000602085830101528094505050505092915050565b80358015158114611c4657600080fd5b919050565b60008060408385031215611c5e57600080fd5b823567ffffffffffffffff811115611c7557600080fd5b611c8185828601611b8b565b925050611c9060208401611c36565b90509250929050565b600080600060608486031215611cae57600080fd5b83359250602084013567ffffffffffffffff811115611ccc57600080fd5b611cd886828701611b8b565b925050611ce760408501611c36565b90509250925092565b600080600060608486031215611d0557600080fd5b8335611d1081611b0e565b92506020840135611d2081611b0e565b929592945050506040919091013590565b60008060008060008060c08789031215611d4a57600080fd5b8635611d5581611b0e565b95506020870135611d6581611b0e565b945060408701359350606087013560ff81168114611d8257600080fd5b9250608087013567ffffffffffffffff80821115611d9f57600080fd5b611dab8a838b01611b8b565b935060a0890135915080821115611dc157600080fd5b50611dce89828a01611b8b565b9150509295509295509295565b600060208284031215611ded57600080fd5b81356104d981611b0e565b60008060408385031215611e0b57600080fd5b8235611e1681611b0e565b91506020830135611e2681611b0e565b809150509250929050565b600181811c90821680611e4557607f821691505b602082108103611e7e577f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b50919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b808201808211156104c6576104c6611e84565b60008351611ed8818460208801611a99565b7f2e000000000000000000000000000000000000000000000000000000000000009083019081528351611f12816001840160208801611a99565b01600101949350505050565b600060208284031215611f3057600080fd5b81516104d981611b0e565b7f41523a7a65726f416464723a0000000000000000000000000000000000000000815260008251611f7381600c850160208701611a99565b91909101600c0192915050565b818103818111156104c6576104c6611e84565b601f82111561100157600081815260208120601f850160051c81016020861015611fba5750805b601f850160051c820191505b81811015611fd957828155600101611fc6565b505050505050565b815167ffffffffffffffff811115611ffb57611ffb611b5c565b61200f816120098454611e31565b84611f93565b602080601f831160018114612062576000841561202c5750858301515b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600386901b1c1916600185901b178555611fd9565b6000858152602081207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08616915b828110156120af57888601518255948401946001909101908401612090565b50858210156120eb57878501517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600388901b60f8161c191681555b5050505050600190811b0190555056fea264697066735822122097aea87c926aeac94c95489d7f3674e61115440bca078ca4ef2af4eae4f9fea364736f6c63430008120033a264697066735822122089e27a345c7c6ec2e044b333ee9138d2f0743901e70542a655eb5279da9b965b64736f6c63430008120033", + "balance": "0x0" + }, + "0x0000777700000000000000000000000000000003": { + "contractName": "EtherVault", + "storage": { + "0x0000000000000000000000000000000000000000000000000000000000000000": "0x0000000000000000000000000000000000000000000000000000000000000001", + "0x0000000000000000000000000000000000000000000000000000000000000001": "0x0000000000000000000000000000000000000000000000000000000000000001", + "0x0000000000000000000000000000000000000000000000000000000000000065": "0x00000000000000000000000019b4f9c381c7927fe33d853e48b560141a380c44", + "0x0000000000000000000000000000000000000000000000000000000000000097": "0x0000000000000000000000000000777700000000000000000000000000000006", + "0x029ae2e2f1d6964720a0fa7e6ffa902f995c156242f4f5a930aa9d9765d167d0": "0x0000000000000000000000000000000000000000000000000000000000000001" + }, + "code": "0x6080604052600436106100c05760003560e01c8063715018a611610074578063d73bb3d01161004e578063d73bb3d014610257578063f2fde38b14610277578063fe9fbb801461029757600080fd5b8063715018a6146101f75780638da5cb5b1461020c578063ba0bbd951461023757600080fd5b80631be2bfa7116100a55780631be2bfa71461018c5780632d1fb389146101ac5780633ab76e9f146101cc57600080fd5b80630ca4dffd1461012257806319ab453c1461016c57600080fd5b3661011d5747158015906100e4575033600090815260c9602052604090205460ff16155b1561011b576040517f4fa3f24500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b005b600080fd5b34801561012e57600080fd5b5061014261013d36600461119e565b6102ed565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020015b60405180910390f35b34801561017857600080fd5b5061011b61018736600461120e565b610301565b34801561019857600080fd5b506101426101a736600461122b565b61049a565b3480156101b857600080fd5b5061011b6101c7366004611282565b6104af565b3480156101d857600080fd5b5060975473ffffffffffffffffffffffffffffffffffffffff16610142565b34801561020357600080fd5b5061011b6105c6565b34801561021857600080fd5b5060655473ffffffffffffffffffffffffffffffffffffffff16610142565b34801561024357600080fd5b5061011b6102523660046112ae565b6105da565b34801561026357600080fd5b5061011b6102723660046112da565b6106f1565b34801561028357600080fd5b5061011b61029236600461120e565b61078d565b3480156102a357600080fd5b506102dd6102b236600461120e565b73ffffffffffffffffffffffffffffffffffffffff16600090815260c9602052604090205460ff1690565b6040519015158152602001610163565b60006102fa468484610841565b9392505050565b600054610100900460ff16158080156103215750600054600160ff909116105b8061033b5750303b15801561033b575060005460ff166001145b6103cc576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a656400000000000000000000000000000000000060648201526084015b60405180910390fd5b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001179055801561042a57600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff166101001790555b610433826109a6565b801561049657600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b5050565b60006104a7848484610841565b949350505050565b6104b76109bf565b73ffffffffffffffffffffffffffffffffffffffff82161580610505575073ffffffffffffffffffffffffffffffffffffffff8216600090815260c9602052604090205460ff161515811515145b1561053c576040517f6faf7e9c00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff8216600081815260c9602090815260409182902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001685151590811790915591519182527f4c0079b9bcd37cd5d29a13938effd97c881798cbc6bd52a3026a29d94b27d1bf910160405180910390a25050565b6105ce6109bf565b6105d86000610a40565b565b33600090815260c9602052604090205460ff16610623576040517f4fa3f24500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61062b610ab7565b73ffffffffffffffffffffffffffffffffffffffff8216610678576040517f687563df00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61069873ffffffffffffffffffffffffffffffffffffffff831682610b2a565b8173ffffffffffffffffffffffffffffffffffffffff167f7b9f77d35803cd201eac9c4ed739bc1fcd3f1be6ab8877d925d1e55517b6fd6e826040516106e091815260200190565b60405180910390a261049660018055565b33600090815260c9602052604090205460ff1661073a576040517f4fa3f24500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610742610ab7565b61074c3382610b2a565b60405181815233907f7b9f77d35803cd201eac9c4ed739bc1fcd3f1be6ab8877d925d1e55517b6fd6e9060200160405180910390a261078a60018055565b50565b6107956109bf565b73ffffffffffffffffffffffffffffffffffffffff8116610838576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201527f646472657373000000000000000000000000000000000000000000000000000060648201526084016103c3565b61078a81610a40565b60008061084d85610c05565b8460405160200161085f929190611317565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152908290526097547fbf40fac100000000000000000000000000000000000000000000000000000000835290925073ffffffffffffffffffffffffffffffffffffffff169063bf40fac1906108e290849060040161136f565b602060405180830381865afa1580156108ff573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061092391906113c0565b91508261099e5760405173ffffffffffffffffffffffffffffffffffffffff83161515906109559083906020016113dd565b6040516020818303038152906040529061099c576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016103c3919061136f565b505b509392505050565b6109ae610cc3565b6109b6610d62565b61078a81610e01565b60655473ffffffffffffffffffffffffffffffffffffffff1633146105d8576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657260448201526064016103c3565b6065805473ffffffffffffffffffffffffffffffffffffffff8381167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b600260015403610b23576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c0060448201526064016103c3565b6002600155565b80156104965760008273ffffffffffffffffffffffffffffffffffffffff168260405160006040518083038185875af1925050503d8060008114610b8a576040519150601f19603f3d011682016040523d82523d6000602084013e610b8f565b606091505b5050905080610bfa576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601360248201527f455448207472616e73666572206661696c65640000000000000000000000000060448201526064016103c3565b505050565b60018055565b60606000610c1283610e95565b600101905060008167ffffffffffffffff811115610c3257610c326110af565b6040519080825280601f01601f191660200182016040528015610c5c576020820181803683370190505b5090508181016020015b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff017f3031323334353637383961626364656600000000000000000000000000000000600a86061a8153600a8504945084610c6657509392505050565b600054610100900460ff16610d5a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e6700000000000000000000000000000000000000000060648201526084016103c3565b6105d8610f78565b600054610100900460ff16610df9576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e6700000000000000000000000000000000000000000060648201526084016103c3565b6105d861100f565b73ffffffffffffffffffffffffffffffffffffffff8116610e4e576040517f9a109b0a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b609780547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff92909216919091179055565b6000807a184f03e93ff9f4daa797ed6e38ed64bf6a1f0100000000000000008310610ede577a184f03e93ff9f4daa797ed6e38ed64bf6a1f010000000000000000830492506040015b6d04ee2d6d415b85acef81000000008310610f0a576d04ee2d6d415b85acef8100000000830492506020015b662386f26fc100008310610f2857662386f26fc10000830492506010015b6305f5e1008310610f40576305f5e100830492506008015b6127108310610f5457612710830492506004015b60648310610f66576064830492506002015b600a8310610f72576001015b92915050565b600054610100900460ff16610bff576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e6700000000000000000000000000000000000000000060648201526084016103c3565b600054610100900460ff166110a6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e6700000000000000000000000000000000000000000060648201526084016103c3565b6105d833610a40565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b600082601f8301126110ef57600080fd5b813567ffffffffffffffff8082111561110a5761110a6110af565b604051601f83017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f01168101908282118183101715611150576111506110af565b8160405283815286602085880101111561116957600080fd5b836020870160208301376000602085830101528094505050505092915050565b8035801515811461119957600080fd5b919050565b600080604083850312156111b157600080fd5b823567ffffffffffffffff8111156111c857600080fd5b6111d4858286016110de565b9250506111e360208401611189565b90509250929050565b73ffffffffffffffffffffffffffffffffffffffff8116811461078a57600080fd5b60006020828403121561122057600080fd5b81356102fa816111ec565b60008060006060848603121561124057600080fd5b83359250602084013567ffffffffffffffff81111561125e57600080fd5b61126a868287016110de565b92505061127960408501611189565b90509250925092565b6000806040838503121561129557600080fd5b82356112a0816111ec565b91506111e360208401611189565b600080604083850312156112c157600080fd5b82356112cc816111ec565b946020939093013593505050565b6000602082840312156112ec57600080fd5b5035919050565b60005b8381101561130e5781810151838201526020016112f6565b50506000910152565b600083516113298184602088016112f3565b7f2e0000000000000000000000000000000000000000000000000000000000000090830190815283516113638160018401602088016112f3565b01600101949350505050565b602081526000825180602084015261138e8160408501602087016112f3565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169190910160400192915050565b6000602082840312156113d257600080fd5b81516102fa816111ec565b7f41523a7a65726f416464723a000000000000000000000000000000000000000081526000825161141581600c8501602087016112f3565b91909101600c019291505056fea26469706673582212205ba76b4da10c920143efe8a59a5126aa1d82a4e0405a1710388f185b06f3d9e964736f6c63430008120033", + "balance": "0xffffffffffffff59776f94274fffffff" + }, + "0x0000777700000000000000000000000000000007": { + "contractName": "SignalService", + "storage": { + "0x0000000000000000000000000000000000000000000000000000000000000000": "0x0000000000000000000000000000000000000000000000000000000000000001", + "0x0000000000000000000000000000000000000000000000000000000000000001": "0x0000000000000000000000000000000000000000000000000000000000000001", + "0x0000000000000000000000000000000000000000000000000000000000000065": "0x00000000000000000000000019b4f9c381c7927fe33d853e48b560141a380c44", + "0x0000000000000000000000000000000000000000000000000000000000000097": "0x0000000000000000000000000000777700000000000000000000000000000006" + }, + "code": "0x608060405234801561001057600080fd5b50600436106100c95760003560e01c80635221f613116100815780638da5cb5b1161005b5780638da5cb5b146101b0578063f2fde38b146101ce578063f8f3f844146101e157600080fd5b80635221f6131461017457806366ca2bc014610187578063715018a6146101a857600080fd5b80631be2bfa7116100b25780631be2bfa71461012057806332676bc6146101335780633ab76e9f1461015657600080fd5b80630ca4dffd146100ce57806319ab453c1461010b575b600080fd5b6100e16100dc366004611c53565b61020b565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020015b60405180910390f35b61011e610119366004611cd7565b610221565b005b6100e161012e366004611cf4565b6103ba565b610146610141366004611d4f565b6103cf565b6040519015158152602001610102565b60975473ffffffffffffffffffffffffffffffffffffffff166100e1565b610146610182366004611d7b565b61047a565b61019a610195366004611e11565b610767565b604051908152602001610102565b61011e6107c3565b60655473ffffffffffffffffffffffffffffffffffffffff166100e1565b61011e6101dc366004611cd7565b6107d7565b61019a6101ef366004611d4f565b6040805192835260208301919091528082206060909201905290565b600061021846848461088e565b90505b92915050565b600054610100900460ff16158080156102415750600054600160ff909116105b8061025b5750303b15801561025b575060005460ff166001145b6102ec576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a656400000000000000000000000000000000000060648201526084015b60405180910390fd5b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001179055801561034a57600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff166101001790555b610353826109f3565b80156103b657600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b5050565b60006103c784848461088e565b949350505050565b600073ffffffffffffffffffffffffffffffffffffffff831661041e576040517fa99bf91a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000829003610459576040517f053c769c00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b50604080519283526020830191909152808220606090920190525460011490565b60004686036104b5576040517fe822b48d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff8516610502576040517fa99bf91a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600084900361053d576040517f053c769c00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600061054b83850185611ed0565b9050600061058f6040518060400160405280600581526020017f7461696b6f000000000000000000000000000000000000000000000000000000815250600061020b565b825161010001516040517f25bf86f20000000000000000000000000000000000000000000000000000000081526fffffffffffffffffffffffffffffffff909116600482015273ffffffffffffffffffffffffffffffffffffffff91909116906325bf86f290602401602060405180830381865afa158015610615573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906106399190612075565b905080158015906106535750815161065090610a0c565b81145b801561075b575073B51f0f2bdCbf6cfabB35239921A5c672519F74ba63960304398360000151606001516106be8b6040518060400160405280600e81526020017f7369676e616c5f7365727669636500000000000000000000000000000000000081525060006103ba565b604080518c8152602081018c9052818120606090910190915260208701516040517fffffffff0000000000000000000000000000000000000000000000000000000060e087901b16815261071a949392916001916004016120fc565b602060405180830381865af4158015610737573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061075b9190612148565b98975050505050505050565b60008181036107a2576040517f053c769c00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b50604080513381526020810192909252808220606090920190526001815590565b6107cb610a31565b6107d56000610ab2565b565b6107df610a31565b73ffffffffffffffffffffffffffffffffffffffff8116610882576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201527f646472657373000000000000000000000000000000000000000000000000000060648201526084016102e3565b61088b81610ab2565b50565b60008061089a85610b29565b846040516020016108ac929190612165565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152908290526097547fbf40fac100000000000000000000000000000000000000000000000000000000835290925073ffffffffffffffffffffffffffffffffffffffff169063bf40fac19061092f9084906004016121bd565b602060405180830381865afa15801561094c573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061097091906121d0565b9150826109eb5760405173ffffffffffffffffffffffffffffffffffffffff83161515906109a29083906020016121ed565b604051602081830303815290604052906109e9576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016102e391906121bd565b505b509392505050565b6109fb610be7565b610a03610c86565b61088b81610d25565b600080610a22610a1d846000610db9565b6111fd565b80516020909101209392505050565b60655473ffffffffffffffffffffffffffffffffffffffff1633146107d5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657260448201526064016102e3565b6065805473ffffffffffffffffffffffffffffffffffffffff8381167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b60606000610b3683611241565b600101905060008167ffffffffffffffff811115610b5657610b56611b1e565b6040519080825280601f01601f191660200182016040528015610b80576020820181803683370190505b5090508181016020015b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff017f3031323334353637383961626364656600000000000000000000000000000000600a86061a8153600a8504945084610b8a57509392505050565b600054610100900460ff16610c7e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e6700000000000000000000000000000000000000000060648201526084016102e3565b6107d5611323565b600054610100900460ff16610d1d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e6700000000000000000000000000000000000000000060648201526084016102e3565b6107d56113c0565b73ffffffffffffffffffffffffffffffffffffffff8116610d72576040517f9a109b0a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b609780547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff92909216919091179055565b61020082015160609015610e2557610dd2826011612290565b67ffffffffffffffff811115610dea57610dea611b1e565b604051908082528060200260200182016040528015610e1d57816020015b6060815260200190600190039081610e085790505b509050610e95565b6101e083015115610e3b57610dd2826010612290565b610e4682600f612290565b67ffffffffffffffff811115610e5e57610e5e611b1e565b604051908082528060200260200182016040528015610e9157816020015b6060815260200190600190039081610e7c5790505b5090505b8251610ea090611460565b81600081518110610eb357610eb36122a3565b6020026020010181905250610ecb8360200151611460565b81600181518110610ede57610ede6122a3565b6020026020010181905250610ef68360400151611473565b81600281518110610f0957610f096122a3565b6020026020010181905250610f218360600151611460565b81600381518110610f3457610f346122a3565b6020026020010181905250610f4c8360800151611460565b81600481518110610f5f57610f5f6122a3565b6020026020010181905250610f778360a00151611460565b81600581518110610f8a57610f8a6122a3565b6020026020010181905250610fc18360c00151604051602001610fad91906122d2565b6040516020818303038152906040526114af565b81600681518110610fd457610fd46122a3565b6020026020010181905250610fec8360e0015161151e565b81600781518110610fff57610fff6122a3565b602002602001018190525061102a8361010001516fffffffffffffffffffffffffffffffff1661151e565b8160088151811061103d5761103d6122a3565b602002602001018190525061105683610120015161152c565b81600981518110611069576110696122a3565b602002602001018190525061108283610140015161152c565b81600a81518110611095576110956122a3565b60200260200101819052506110ae83610160015161152c565b81600b815181106110c1576110c16122a3565b60200260200101819052506110da8361018001516114af565b81600c815181106110ed576110ed6122a3565b6020026020010181905250611106836101a00151611460565b81600d81518110611119576111196122a3565b6020026020010181905250611168836101c00151604051602001610fad919060c09190911b7fffffffffffffffff00000000000000000000000000000000000000000000000016815260080190565b81600e8151811061117b5761117b6122a3565b6020026020010181905250826101e001516000146111c0576111a1836101e0015161151e565b81600f815181106111b4576111b46122a3565b60200260200101819052505b6102008301511561021b576111d9836102000151611460565b816010815181106111ec576111ec6122a3565b602002602001018190525092915050565b6060600061120a83611544565b9050611218815160c0611678565b8160405160200161122a929190612307565b604051602081830303815290604052915050919050565b6000807a184f03e93ff9f4daa797ed6e38ed64bf6a1f010000000000000000831061128a577a184f03e93ff9f4daa797ed6e38ed64bf6a1f010000000000000000830492506040015b6d04ee2d6d415b85acef810000000083106112b6576d04ee2d6d415b85acef8100000000830492506020015b662386f26fc1000083106112d457662386f26fc10000830492506010015b6305f5e10083106112ec576305f5e100830492506008015b612710831061130057612710830492506004015b60648310611312576064830492506002015b600a831061021b5760010192915050565b600054610100900460ff166113ba576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e6700000000000000000000000000000000000000000060648201526084016102e3565b60018055565b600054610100900460ff16611457576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e6700000000000000000000000000000000000000000060648201526084016102e3565b6107d533610ab2565b606061021b61146e83611860565b6114af565b604051606082811b7fffffffffffffffffffffffffffffffffffffffff0000000000000000000000001660208301529061021b90603401610fad565b606080825160011480156114dd57506080836000815181106114d3576114d36122a3565b016020015160f81c105b156114e957508161021b565b6114f583516080611678565b83604051602001611507929190612307565b604051602081830303815290604052905092915050565b606061021b61146e83611948565b606061021b61146e8367ffffffffffffffff16611948565b6060815160000361156357505060408051600081526020810190915290565b6000805b83518110156115a857838181518110611582576115826122a3565b602002602001015151826115969190612290565b91506115a181612336565b9050611567565b60008267ffffffffffffffff8111156115c3576115c3611b1e565b6040519080825280601f01601f1916602001820160405280156115ed576020820181803683370190505b50600092509050602081015b855183101561166f576000868481518110611616576116166122a3565b60200260200101519050600060208201905061163483828451611aa3565b878581518110611646576116466122a3565b6020026020010151518361165a9190612290565b925050508261166890612336565b92506115f9565b50949350505050565b60608060388410156116f757604080516001808252818301909252906020820181803683370190505090506116ad838561236e565b60f81b816000815181106116c3576116c36122a3565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a905350610218565b600060015b6117068187612387565b156117295761171482612336565b91506117226101008261239b565b90506116fc565b611734826001612290565b67ffffffffffffffff81111561174c5761174c611b1e565b6040519080825280601f01601f191660200182016040528015611776576020820181803683370190505b509250611783858361236e565b61178e90603761236e565b60f81b836000815181106117a4576117a46122a3565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a905350600190505b8181116109e9576101006117ec82846123b2565b6117f8906101006124e5565b6118029088612387565b61180c91906124f1565b60f81b838281518110611821576118216122a3565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a90535061185981612336565b90506117d8565b606060008260405160200161187791815260200190565b604080518083037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe001815260208084528383019092529250600091829160208201818036833701905050905060005b815181101561166f5783836118da81612336565b9450815181106118ec576118ec6122a3565b602001015160f81c60f81b828281518110611909576119096122a3565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a90535061194181612336565b90506118c6565b606060008260405160200161195f91815260200190565b604051602081830303815290604052905060005b60208110156119cc5781818151811061198e5761198e6122a3565b01602001517fff00000000000000000000000000000000000000000000000000000000000000166000036119cc576119c581612336565b9050611973565b60006119d98260206123b2565b67ffffffffffffffff8111156119f1576119f1611b1e565b6040519080825280601f01601f191660200182016040528015611a1b576020820181803683370190505b50905060005b815181101561166f578383611a3581612336565b945081518110611a4757611a476122a3565b602001015160f81c60f81b828281518110611a6457611a646122a3565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a905350611a9c81612336565b9050611a21565b8282825b60208110611adf5781518352611abe602084612290565b9250611acb602083612290565b9150611ad86020826123b2565b9050611aa7565b905182516020929092036101000a7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0180199091169116179052505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6040805190810167ffffffffffffffff81118282101715611b7057611b70611b1e565b60405290565b604051610220810167ffffffffffffffff81118282101715611b7057611b70611b1e565b600082601f830112611bab57600080fd5b813567ffffffffffffffff80821115611bc657611bc6611b1e565b604051601f83017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f01168101908282118183101715611c0c57611c0c611b1e565b81604052838152866020858801011115611c2557600080fd5b836020870160208301376000602085830101528094505050505092915050565b801515811461088b57600080fd5b60008060408385031215611c6657600080fd5b823567ffffffffffffffff811115611c7d57600080fd5b611c8985828601611b9a565b9250506020830135611c9a81611c45565b809150509250929050565b73ffffffffffffffffffffffffffffffffffffffff8116811461088b57600080fd5b8035611cd281611ca5565b919050565b600060208284031215611ce957600080fd5b813561021881611ca5565b600080600060608486031215611d0957600080fd5b83359250602084013567ffffffffffffffff811115611d2757600080fd5b611d3386828701611b9a565b9250506040840135611d4481611c45565b809150509250925092565b60008060408385031215611d6257600080fd5b8235611d6d81611ca5565b946020939093013593505050565b600080600080600060808688031215611d9357600080fd5b853594506020860135611da581611ca5565b935060408601359250606086013567ffffffffffffffff80821115611dc957600080fd5b818801915088601f830112611ddd57600080fd5b813581811115611dec57600080fd5b896020828501011115611dfe57600080fd5b9699959850939650602001949392505050565b600060208284031215611e2357600080fd5b5035919050565b600082601f830112611e3b57600080fd5b60405161010080820182811067ffffffffffffffff82111715611e6057611e60611b1e565b60405283018185821115611e7357600080fd5b845b82811015611e8d578035825260209182019101611e75565b509195945050505050565b80356fffffffffffffffffffffffffffffffff81168114611cd257600080fd5b803567ffffffffffffffff81168114611cd257600080fd5b600060208284031215611ee257600080fd5b813567ffffffffffffffff80821115611efa57600080fd5b9083019060408286031215611f0e57600080fd5b611f16611b4d565b823582811115611f2557600080fd5b83016103008188031215611f3857600080fd5b611f40611b76565b8135815260208201356020820152611f5a60408301611cc7565b6040820152606082013560608201526080820135608082015260a082013560a0820152611f8a8860c08401611e2a565b60c08201526101c08083013560e08301526101e0611fa9818501611e98565b610100840152610200611fbd818601611eb8565b610120850152611fd06102208601611eb8565b610140850152611fe36102408601611eb8565b61016085015261026085013587811115611ffc57600080fd5b6120088c828801611b9a565b610180860152506102808501356101a08501526120286102a08601611eb8565b838501526102c0850135828501526102e085013581850152505050808352505060208301358281111561205a57600080fd5b61206687828601611b9a565b60208301525095945050505050565b60006020828403121561208757600080fd5b5051919050565b60005b838110156120a9578181015183820152602001612091565b50506000910152565b600081518084526120ca81602086016020860161208e565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b85815273ffffffffffffffffffffffffffffffffffffffff8516602082015283604082015282606082015260a06080820152600061213d60a08301846120b2565b979650505050505050565b60006020828403121561215a57600080fd5b815161021881611c45565b6000835161217781846020880161208e565b7f2e0000000000000000000000000000000000000000000000000000000000000090830190815283516121b181600184016020880161208e565b01600101949350505050565b60208152600061021860208301846120b2565b6000602082840312156121e257600080fd5b815161021881611ca5565b7f41523a7a65726f416464723a000000000000000000000000000000000000000081526000825161222581600c85016020870161208e565b91909101600c0192915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b8082018082111561021b5761021b612261565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b60008183825b60088110156122f75781518352602092830192909101906001016122d8565b5050506101008201905092915050565b6000835161231981846020880161208e565b83519083019061232d81836020880161208e565b01949350505050565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff820361236757612367612261565b5060010190565b60ff818116838216019081111561021b5761021b612261565b60008261239657612396612232565b500490565b808202811582820484141761021b5761021b612261565b8181038181111561021b5761021b612261565b600181815b8085111561241e57817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0482111561240457612404612261565b8085161561241157918102915b93841c93908002906123ca565b509250929050565b6000826124355750600161021b565b816124425750600061021b565b816001811461245857600281146124625761247e565b600191505061021b565b60ff84111561247357612473612261565b50506001821b61021b565b5060208310610133831016604e8410600b84101617156124a1575081810a61021b565b6124ab83836123c5565b807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff048211156124dd576124dd612261565b029392505050565b60006102188383612426565b60008261250057612500612232565b50069056fea26469706673582212209e7235233ea73cd822dc3fc71cb88aeed9bb6967b10cbcf6820dcc506b275d0164736f6c63430008120033", + "balance": "0x0" + }, + "0x0000777700000000000000000000000000000005": { + "contractName": "TestERC20", + "storage": { + "0x0000000000000000000000000000000000000000000000000000000000000003": "0x5072656465706c6f79455243323000000000000000000000000000000000001c", + "0x0000000000000000000000000000000000000000000000000000000000000004": "0x5052450000000000000000000000000000000000000000000000000000000006", + "0x0000000000000000000000000000000000000000000000000000000000000002": "0x00000000000000000000000000000000000000000000000000000000002ee000", + "0x0fbcff3234c0e4fa090508601e67e2155e18580b7c6ab4cb716e8ef2dca88184": "0x00000000000000000000000000000000000000000000000000000000000fa000", + "0x55385a0c2ad17c21b4fe396be9b1f10f500e7eebad11fcd1afe36c68ee5fa4cd": "0x00000000000000000000000000000000000000000000000000000000000fa000", + "0x478db7f3c43c550c1670aa0517a6d515b9e15f22ea28e4f99e8c5f8bcf58e406": "0x00000000000000000000000000000000000000000000000000000000000fa000" + }, + "code": "0x608060405234801561001057600080fd5b50600436106100c95760003560e01c80633950935111610081578063a457c2d71161005b578063a457c2d714610194578063a9059cbb146101a7578063dd62ed3e146101ba57600080fd5b8063395093511461014357806370a082311461015657806395d89b411461018c57600080fd5b806318160ddd116100b257806318160ddd1461010f57806323b872dd14610121578063313ce5671461013457600080fd5b806306fdde03146100ce578063095ea7b3146100ec575b600080fd5b6100d6610200565b6040516100e39190610908565b60405180910390f35b6100ff6100fa36600461099d565b610292565b60405190151581526020016100e3565b6002545b6040519081526020016100e3565b6100ff61012f3660046109c7565b6102ac565b604051601281526020016100e3565b6100ff61015136600461099d565b6102d0565b610113610164366004610a03565b73ffffffffffffffffffffffffffffffffffffffff1660009081526020819052604090205490565b6100d661031c565b6100ff6101a236600461099d565b61032b565b6100ff6101b536600461099d565b610401565b6101136101c8366004610a25565b73ffffffffffffffffffffffffffffffffffffffff918216600090815260016020908152604080832093909416825291909152205490565b60606003805461020f90610a58565b80601f016020809104026020016040519081016040528092919081815260200182805461023b90610a58565b80156102885780601f1061025d57610100808354040283529160200191610288565b820191906000526020600020905b81548152906001019060200180831161026b57829003601f168201915b5050505050905090565b6000336102a081858561040f565b60019150505b92915050565b6000336102ba8582856105c2565b6102c5858585610699565b506001949350505050565b33600081815260016020908152604080832073ffffffffffffffffffffffffffffffffffffffff871684529091528120549091906102a09082908690610317908790610aab565b61040f565b60606004805461020f90610a58565b33600081815260016020908152604080832073ffffffffffffffffffffffffffffffffffffffff87168452909152812054909190838110156103f4576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602560248201527f45524332303a2064656372656173656420616c6c6f77616e63652062656c6f7760448201527f207a65726f00000000000000000000000000000000000000000000000000000060648201526084015b60405180910390fd5b6102c5828686840361040f565b6000336102a0818585610699565b73ffffffffffffffffffffffffffffffffffffffff83166104b1576040517f08c379a0000000000000000000000000000000000000000000000000000000008152602060048201526024808201527f45524332303a20617070726f76652066726f6d20746865207a65726f2061646460448201527f726573730000000000000000000000000000000000000000000000000000000060648201526084016103eb565b73ffffffffffffffffffffffffffffffffffffffff8216610554576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602260248201527f45524332303a20617070726f766520746f20746865207a65726f20616464726560448201527f737300000000000000000000000000000000000000000000000000000000000060648201526084016103eb565b73ffffffffffffffffffffffffffffffffffffffff83811660008181526001602090815260408083209487168084529482529182902085905590518481527f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925910160405180910390a3505050565b73ffffffffffffffffffffffffffffffffffffffff8381166000908152600160209081526040808320938616835292905220547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff81146106935781811015610686576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f45524332303a20696e73756666696369656e7420616c6c6f77616e636500000060448201526064016103eb565b610693848484840361040f565b50505050565b73ffffffffffffffffffffffffffffffffffffffff831661073c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602560248201527f45524332303a207472616e736665722066726f6d20746865207a65726f20616460448201527f647265737300000000000000000000000000000000000000000000000000000060648201526084016103eb565b73ffffffffffffffffffffffffffffffffffffffff82166107df576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602360248201527f45524332303a207472616e7366657220746f20746865207a65726f206164647260448201527f657373000000000000000000000000000000000000000000000000000000000060648201526084016103eb565b73ffffffffffffffffffffffffffffffffffffffff831660009081526020819052604090205481811015610895576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f45524332303a207472616e7366657220616d6f756e742065786365656473206260448201527f616c616e6365000000000000000000000000000000000000000000000000000060648201526084016103eb565b73ffffffffffffffffffffffffffffffffffffffff848116600081815260208181526040808320878703905593871680835291849020805487019055925185815290927fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef910160405180910390a3610693565b600060208083528351808285015260005b8181101561093557858101830151858201604001528201610919565b5060006040828601015260407fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f8301168501019250505092915050565b803573ffffffffffffffffffffffffffffffffffffffff8116811461099857600080fd5b919050565b600080604083850312156109b057600080fd5b6109b983610974565b946020939093013593505050565b6000806000606084860312156109dc57600080fd5b6109e584610974565b92506109f360208501610974565b9150604084013590509250925092565b600060208284031215610a1557600080fd5b610a1e82610974565b9392505050565b60008060408385031215610a3857600080fd5b610a4183610974565b9150610a4f60208401610974565b90509250929050565b600181811c90821680610a6c57607f821691505b602082108103610aa5577f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b50919050565b808201808211156102a6577f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fdfea264697066735822122066fafca01d431074160bbb4b6fc540b95eb31fa8c4479f896ac206b98463328464736f6c63430008120033", + "balance": "0x0" + } +}
diff --git ethereum/go-ethereum/core/taiko_genesis/eldfell.json taikoxyz/taiko-geth/core/taiko_genesis/eldfell.json new file mode 100644 index 0000000000000000000000000000000000000000..b5938af70e403455cd8a973271dd6b88fccb81a5 --- /dev/null +++ taikoxyz/taiko-geth/core/taiko_genesis/eldfell.json @@ -0,0 +1,164 @@ +{ + "0x19B4F9C381C7927FE33D853e48b560141A380C44": { + "balance": "0xfffffffffffffacbbb7ca13a7fffffff" + }, + "0x113cE23c9e0cc50F4D41d7cE6DA02dCAFf8BFF85": { + "balance": "0xfffffffffffffacbbb7ca13a7fffffff" + }, + "0x88f66d67C0e643A541822cc326708530a827EC8E": { + "balance": "0xfffffffffffffacbbb7ca13a7fffffff" + }, + "0x2E610A0D8E30D6df2877B9c3EC3daDb885364800": { + "balance": "0xfffffffffffffacbbb7ca13a7fffffff" + }, + "0xd56fbBb9C88938a61e9CA71339Abd5f84dF131Cf": { + "contractName": "LibTrieProof", + "storage": {}, + "code": "0x73000000000000000000000000000000000000000030146080604052600436106100355760003560e01c8063a54274621461003a575b600080fd5b61004d61004836600461173e565b610061565b604051901515815260200160405180910390f35b600080806100718486018661188e565b6040516bffffffffffffffffffffffff1960608c901b166020820152919350915060009081906100b490603401604051602081830303815290604052858d610184565b915091508161010a5760405162461bcd60e51b815260206004820152601960248201527f4c54503a696e76616c6964206163636f756e742070726f6f660000000000000060448201526064015b60405180910390fd5b6000610115826101ad565b9050600061013c8260028151811061012f5761012f6118f2565b60200260200101516101e6565b90506101738b60405160200161015491815260200190565b60405160208183030381529060405261016c8c6102e9565b87846102fc565b9d9c50505050505050505050505050565b60006060600061019386610316565b90506101a0818686610348565b9250925050935093915050565b6040805180820182526000808252602091820152815180830190925282518252808301908201526060906101e090610423565b92915050565b600060218260000151111561023d5760405162461bcd60e51b815260206004820152601a60248201527f496e76616c696420524c5020627974657333322076616c75652e0000000000006044820152606401610101565b600080600061024b8561060f565b91945092509050600081600181111561026657610266611908565b146102b35760405162461bcd60e51b815260206004820152601a60248201527f496e76616c696420524c5020627974657333322076616c75652e0000000000006044820152606401610101565b60008386602001516102c59190611934565b805190915060208410156102df5760208490036101000a90045b9695505050505050565b60606101e06102f783610959565b610a8d565b60008061030886610316565b90506102df81868686610afc565b6060818051906020012060405160200161033291815260200190565b6040516020818303038152906040529050919050565b60006060600061035785610b39565b90506000806000610369848a89610c32565b8151929550909350915015808061037d5750815b6103c95760405162461bcd60e51b815260206004820152601a60248201527f50726f76696465642070726f6f6620697320696e76616c69642e0000000000006044820152606401610101565b6000816103e55760405180602001604052806000815250610411565b610411866103f4600188611947565b81518110610404576104046118f2565b6020026020010151611052565b919b919a509098505050505050505050565b60606000806104318461060f565b9193509091506001905081600181111561044d5761044d611908565b1461049a5760405162461bcd60e51b815260206004820152601760248201527f496e76616c696420524c50206c6973742076616c75652e0000000000000000006044820152606401610101565b6040805160208082526104208201909252600091816020015b60408051808201909152600080825260208201528152602001906001900390816104b35790505090506000835b8651811015610604576020821061054c5760405162461bcd60e51b815260206004820152602a60248201527f50726f766964656420524c50206c6973742065786365656473206d6178206c6960448201526939ba103632b733ba341760b11b6064820152608401610101565b6000806105896040518060400160405280858c6000015161056d9190611947565b8152602001858c602001516105829190611934565b905261060f565b5091509150604051806040016040528083836105a59190611934565b8152602001848b602001516105ba9190611934565b8152508585815181106105cf576105cf6118f2565b60209081029190910101526105e5600185611934565b93506105f18183611934565b6105fb9084611934565b925050506104e0565b508152949350505050565b6000806000808460000151116106675760405162461bcd60e51b815260206004820152601860248201527f524c50206974656d2063616e6e6f74206265206e756c6c2e00000000000000006044820152606401610101565b6020840151805160001a607f811161068c576000600160009450945094505050610952565b60b781116107085760006106a1608083611947565b9050808760000151116106f65760405162461bcd60e51b815260206004820152601960248201527f496e76616c696420524c502073686f727420737472696e672e000000000000006044820152606401610101565b60019550935060009250610952915050565b60bf81116107f757600061071d60b783611947565b9050808760000151116107725760405162461bcd60e51b815260206004820152601f60248201527f496e76616c696420524c50206c6f6e6720737472696e67206c656e6774682e006044820152606401610101565b600183015160208290036101000a900461078c8183611934565b8851116107db5760405162461bcd60e51b815260206004820152601860248201527f496e76616c696420524c50206c6f6e6720737472696e672e00000000000000006044820152606401610101565b6107e6826001611934565b965094506000935061095292505050565b60f7811161087257600061080c60c083611947565b9050808760000151116108615760405162461bcd60e51b815260206004820152601760248201527f496e76616c696420524c502073686f7274206c6973742e0000000000000000006044820152606401610101565b600195509350849250610952915050565b600061087f60f783611947565b9050808760000151116108d45760405162461bcd60e51b815260206004820152601d60248201527f496e76616c696420524c50206c6f6e67206c697374206c656e6774682e0000006044820152606401610101565b600183015160208290036101000a90046108ee8183611934565b8851116109365760405162461bcd60e51b815260206004820152601660248201527524b73b30b634b210292628103637b733903634b9ba1760511b6044820152606401610101565b610941826001611934565b965094506001935061095292505050565b9193909250565b606060008260405160200161097091815260200190565b604051602081830303815290604052905060005b60208110156109c55781818151811061099f5761099f6118f2565b01602001516001600160f81b0319166000036109c5576109be8161195a565b9050610984565b60006109d2826020611947565b67ffffffffffffffff8111156109ea576109ea6117eb565b6040519080825280601f01601f191660200182016040528015610a14576020820181803683370190505b50905060005b8151811015610a84578383610a2e8161195a565b945081518110610a4057610a406118f2565b602001015160f81c60f81b828281518110610a5d57610a5d6118f2565b60200101906001600160f81b031916908160001a905350610a7d8161195a565b9050610a1a565b50949350505050565b60608082516001148015610abb5750608083600081518110610ab157610ab16118f2565b016020015160f81c105b15610ac75750816101e0565b610ad383516080611079565b83604051602001610ae59291906119a3565b604051602081830303815290604052905092915050565b6000806000610b0c878686610348565b91509150818015610b2e57508051602080830191909120875191880191909120145b979650505050505050565b60606000610b46836101ad565b90506000815167ffffffffffffffff811115610b6457610b646117eb565b604051908082528060200260200182016040528015610ba957816020015b6040805180820190915260608082526020820152815260200190600190039081610b825790505b50905060005b8251811015610c2a576000610bdc848381518110610bcf57610bcf6118f2565b6020026020010151611223565b90506040518060400160405280610bf2836101ad565b815260200182815250838381518110610c0d57610c0d6118f2565b60200260200101819052505080610c239061195a565b9050610baf565b509392505050565b600060606000806000610c44876112b3565b90506000869050600080610c6b604051806040016040528060608152602001606081525090565b60005b8c5181101561102a578c8181518110610c8957610c896118f2565b602002602001015191508284610c9f9190611934565b9350610cac600188611934565b965083600003610d09578482602001518051906020012014610d045760405162461bcd60e51b8152602060048201526011602482015270092dcecc2d8d2c840e4dedee840d0c2e6d607b1b6044820152606401610101565b610dcb565b602082602001515110610d70578482602001518051906020012014610d045760405162461bcd60e51b815260206004820152601b60248201527f496e76616c6964206c6172676520696e7465726e616c206861736800000000006044820152606401610101565b84610d7e83602001516113ec565b14610dcb5760405162461bcd60e51b815260206004820152601a60248201527f496e76616c696420696e7465726e616c206e6f646520686173680000000000006044820152606401610101565b610dd7601060016119c0565b60ff1682600001515103610e45578551841461102a576000868581518110610e0157610e016118f2565b01602001518351805160f89290921c925060009183908110610e2557610e256118f2565b60200260200101519050610e3881611414565b965060019450505061101a565b81515160011901610fd2576000610e5b8361144a565b9050600081600081518110610e7257610e726118f2565b016020015160f81c90506000610e896002836119ef565b610e94906002611a11565b90506000610ea5848360ff1661146e565b90506000610eb38b8a61146e565b90506000610ec183836114a4565b905060ff851660021480610ed8575060ff85166003145b15610f1257808351148015610eed5750808251145b15610eff57610efc818b611934565b99505b50600160ff1b995061102a945050505050565b60ff85161580610f25575060ff85166001145b15610f7b5782518114610f455750600160ff1b995061102a945050505050565b610f6c8860000151600181518110610f5f57610f5f6118f2565b6020026020010151611414565b9a50975061101a945050505050565b60405162461bcd60e51b815260206004820152602660248201527f52656365697665642061206e6f6465207769746820616e20756e6b6e6f776e206044820152650e0e4caccd2f60d31b6064820152608401610101565b60405162461bcd60e51b815260206004820152601d60248201527f526563656976656420616e20756e706172736561626c65206e6f64652e0000006044820152606401610101565b6110238161195a565b9050610c6e565b50600160ff1b84148661103d878661146e565b909e909d50909b509950505050505050505050565b805180516060916101e09161106990600190611947565b81518110610bcf57610bcf6118f2565b60608060388410156110e057604080516001808252818301909252906020820181803683370190505090506110ae83856119c0565b60f81b816000815181106110c4576110c46118f2565b60200101906001600160f81b031916908160001a90535061121c565b600060015b6110ef8187611a2a565b15611112576110fd8261195a565b915061110b61010082611a3e565b90506110e5565b61111d826001611934565b67ffffffffffffffff811115611135576111356117eb565b6040519080825280601f01601f19166020018201604052801561115f576020820181803683370190505b50925061116c85836119c0565b6111779060376119c0565b60f81b8360008151811061118d5761118d6118f2565b60200101906001600160f81b031916908160001a905350600190505b818111611219576101006111bd8284611947565b6111c990610100611b39565b6111d39088611a2a565b6111dd9190611b45565b60f81b8382815181106111f2576111f26118f2565b60200101906001600160f81b031916908160001a9053506112128161195a565b90506111a9565b50505b9392505050565b606060008060006112338561060f565b91945092509050600081600181111561124e5761124e611908565b1461129b5760405162461bcd60e51b815260206004820152601860248201527f496e76616c696420524c502062797465732076616c75652e00000000000000006044820152606401610101565b6112aa8560200151848461151e565b95945050505050565b60606000825160026112c59190611a3e565b67ffffffffffffffff8111156112dd576112dd6117eb565b6040519080825280601f01601f191660200182016040528015611307576020820181803683370190505b50905060005b83518110156113e557600484828151811061132a5761132a6118f2565b01602001516001600160f81b031916901c82611347836002611a3e565b81518110611357576113576118f2565b60200101906001600160f81b031916908160001a9053506010848281518110611382576113826118f2565b0160200151611394919060f81c6119ef565b60f81b826113a3836002611a3e565b6113ae906001611934565b815181106113be576113be6118f2565b60200101906001600160f81b031916908160001a9053506113de8161195a565b905061130d565b5092915050565b600060208251101561140057506020015190565b818060200190518101906101e09190611b59565b600060606020836000015110156114355761142e836115c7565b9050611441565b61143e83611223565b90505b61121c816113ec565b60606101e06114698360000151600081518110610bcf57610bcf6118f2565b6112b3565b60608251821061148d57506040805160208101909152600081526101e0565b61121c838384865161149f9190611947565b6115d2565b6000805b8084511180156114b85750808351115b801561150957508281815181106114d1576114d16118f2565b602001015160f81c60f81b6001600160f81b0319168482815181106114f8576114f86118f2565b01602001516001600160f81b031916145b1561121c576115178161195a565b90506114a8565b606060008267ffffffffffffffff81111561153b5761153b6117eb565b6040519080825280601f01601f191660200182016040528015611565576020820181803683370190505b509050805160000361157857905061121c565b8484016020820160005b8581101561159a578281015182820152602001611582565b5060006001602087066020036101000a039050808251168119845116178252839450505050509392505050565b60606101e082611728565b6060816115e081601f611934565b101561161f5760405162461bcd60e51b815260206004820152600e60248201526d736c6963655f6f766572666c6f7760901b6044820152606401610101565b8261162a8382611934565b10156116695760405162461bcd60e51b815260206004820152600e60248201526d736c6963655f6f766572666c6f7760901b6044820152606401610101565b6116738284611934565b845110156116b75760405162461bcd60e51b8152602060048201526011602482015270736c6963655f6f75744f66426f756e647360781b6044820152606401610101565b6060821580156116d65760405191506000825260208201604052610a84565b6040519150601f8416801560200281840101858101878315602002848b0101015b8183101561170f5780518352602092830192016116f7565b5050858452601f01601f19166040525050949350505050565b60606101e082602001516000846000015161151e565b60008060008060008060a0878903121561175757600080fd5b8635955060208701356001600160a01b038116811461177557600080fd5b94506040870135935060608701359250608087013567ffffffffffffffff808211156117a057600080fd5b818901915089601f8301126117b457600080fd5b8135818111156117c357600080fd5b8a60208285010111156117d557600080fd5b6020830194508093505050509295509295509295565b634e487b7160e01b600052604160045260246000fd5b600082601f83011261181257600080fd5b813567ffffffffffffffff8082111561182d5761182d6117eb565b604051601f8301601f19908116603f01168101908282118183101715611855576118556117eb565b8160405283815286602085880101111561186e57600080fd5b836020870160208301376000602085830101528094505050505092915050565b600080604083850312156118a157600080fd5b823567ffffffffffffffff808211156118b957600080fd5b6118c586838701611801565b935060208501359150808211156118db57600080fd5b506118e885828601611801565b9150509250929050565b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052602160045260246000fd5b634e487b7160e01b600052601160045260246000fd5b808201808211156101e0576101e061191e565b818103818111156101e0576101e061191e565b60006001820161196c5761196c61191e565b5060010190565b6000815160005b81811015611994576020818501810151868301520161197a565b50600093019283525090919050565b60006119b86119b28386611973565b84611973565b949350505050565b60ff81811683821601908111156101e0576101e061191e565b634e487b7160e01b600052601260045260246000fd5b600060ff831680611a0257611a026119d9565b8060ff84160691505092915050565b60ff82811682821603908111156101e0576101e061191e565b600082611a3957611a396119d9565b500490565b80820281158282048414176101e0576101e061191e565b600181815b80851115611a90578160001904821115611a7657611a7661191e565b80851615611a8357918102915b93841c9390800290611a5a565b509250929050565b600082611aa7575060016101e0565b81611ab4575060006101e0565b8160018114611aca5760028114611ad457611af0565b60019150506101e0565b60ff841115611ae557611ae561191e565b50506001821b6101e0565b5060208310610133831016604e8410600b8410161715611b13575081810a6101e0565b611b1d8383611a55565b8060001904821115611b3157611b3161191e565b029392505050565b600061121c8383611a98565b600082611b5457611b546119d9565b500690565b600060208284031215611b6b57600080fd5b505191905056fea26469706673582212200ce0b855958491d449296239ab0a499d51105fc25c306cacdd66eed473ebcf4164736f6c63430008140033", + "balance": "0x0" + }, + "0x3D242344128D1db694d798CF0Ad3dC778Aa77347": { + "contractName": "LibBridgeRetry", + "storage": {}, + "code": "0x73000000000000000000000000000000000000000030146080604052600080fdfea26469706673582212209ad4b2c866dbe1263f15c72a9d9c6857d19b471dc0ffa8cba69fdd5d4cb102b864736f6c63430008140033", + "balance": "0x0" + }, + "0x9c7145F3B1EaB768364a9ff72318B9D7AeafB156": { + "contractName": "LibBridgeProcess", + "storage": {}, + "code": "0x73000000000000000000000000000000000000000030146080604052600080fdfea2646970667358221220580d1b027125bdf07c98c62cba13a64e78c2192e8c0f84c6cef28804c6341ae864736f6c63430008140033", + "balance": "0x0" + }, + "0x0000777700000000000000000000000000000006": { + "contractName": "ProxiedAddressManager", + "storage": {}, + "code": "0x608060405234801561001057600080fd5b50600436106100625760003560e01c8063656b06a414610067578063715018a6146100b75780638da5cb5b146100c1578063decd8e39146100d2578063e1c7392a146100e5578063f2fde38b146100ed575b600080fd5b61009b610075366004610466565b60009182526065602090815260408084209284529190529020546001600160a01b031690565b6040516001600160a01b03909116815260200160405180910390f35b6100bf610100565b005b6033546001600160a01b031661009b565b6100bf6100e03660046104a4565b610114565b6100bf6101d4565b6100bf6100fb3660046104d9565b6102ea565b610108610360565b61011260006103ba565b565b61011c610360565b6001600160a01b0381163b15801561013c57506001600160a01b03811633145b1561015a57604051633baa901360e21b815260040160405180910390fd5b600083815260656020908152604080832085845282529182902080546001600160a01b038581166001600160a01b0319831681179093558451928352169181018290529091849186917fe41a6e8584d6e19a0dfc5f9331be4ebe61b5f025d45da164c9ca6ee9b837cea9910160405180910390a350505050565b600054610100900460ff16158080156101f45750600054600160ff909116105b8061020e5750303b15801561020e575060005460ff166001145b6102765760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b60648201526084015b60405180910390fd5b6000805460ff191660011790558015610299576000805461ff0019166101001790555b6102a161040c565b80156102e7576000805461ff0019169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b50565b6102f2610360565b6001600160a01b0381166103575760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b606482015260840161026d565b6102e7816103ba565b6033546001600160a01b031633146101125760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015260640161026d565b603380546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b600054610100900460ff166104335760405162461bcd60e51b815260040161026d906104fb565b610112600054610100900460ff1661045d5760405162461bcd60e51b815260040161026d906104fb565b610112336103ba565b6000806040838503121561047957600080fd5b50508035926020909101359150565b80356001600160a01b038116811461049f57600080fd5b919050565b6000806000606084860312156104b957600080fd5b83359250602084013591506104d060408501610488565b90509250925092565b6000602082840312156104eb57600080fd5b6104f482610488565b9392505050565b6020808252602b908201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960408201526a6e697469616c697a696e6760a81b60608201526080019056fea2646970667358221220d1b8f83f17d2971223f345076e2c8b1982272c271a0ce36e6b3541cd15bd267964736f6c63430008140033", + "balance": "0x0" + }, + "0x1000777700000000000000000000000000000006": { + "contractName": "AddressManagerProxy", + "storage": { + "0x0000000000000000000000000000000000000000000000000000000000000000": "0x0000000000000000000000000000000000000000000000000000000000000001", + "0x0000000000000000000000000000000000000000000000000000000000000033": "0x00000000000000000000000019b4f9c381c7927fe33d853e48b560141a380c44", + "0xa2985d6ec808cf8e4351b74656a3169ef9f5ae53c52585f208ff047513b6b22f": "0x0000000000000000000000001000777700000000000000000000000000000001", + "0xab0df58d0c513f542551f7cf89c05da0610fe5e3092a4b838d7d8529d492ecf0": "0x0000000000000000000000001000777700000000000000000000000000000004", + "0x56e7eae2fe6d26fea53c92b4b72c70c097b4c6cb841f2560628bc18c65113ede": "0x0000000000000000000000001000777700000000000000000000000000000002", + "0x7b5ab0263db4edc4cd0bef661062356260cf371a7955689e8739ce5188c0e9fe": "0x0000000000000000000000001000777700000000000000000000000000000003", + "0x62856d7e6e6c45fe7cca6dc9dc0aff508e9e029ca538a20a7d2086827adddfda": "0x0000000000000000000000001000777700000000000000000000000000000007", + "0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103": "0x113cE23c9e0cc50F4D41d7cE6DA02dCAFf8BFF85", + "0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc": "0x0000777700000000000000000000000000000006" + }, + "code": "0x60806040526004361061004e5760003560e01c80633659cfe6146100655780634f1ef286146100855780635c60da1b146100985780638f283970146100c9578063f851a440146100e95761005d565b3661005d5761005b6100fe565b005b61005b6100fe565b34801561007157600080fd5b5061005b6100803660046106b3565b610118565b61005b6100933660046106ce565b610155565b3480156100a457600080fd5b506100ad6101bc565b6040516001600160a01b03909116815260200160405180910390f35b3480156100d557600080fd5b5061005b6100e43660046106b3565b6101ed565b3480156100f557600080fd5b506100ad61020d565b61010661022e565b6101166101116102c3565b6102cd565b565b6101206102f1565b6001600160a01b0316330361014d5761014a81604051806020016040528060008152506000610324565b50565b61014a6100fe565b61015d6102f1565b6001600160a01b031633036101b4576101af8383838080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525060019250610324915050565b505050565b6101af6100fe565b60006101c66102f1565b6001600160a01b031633036101e2576101dd6102c3565b905090565b6101ea6100fe565b90565b6101f56102f1565b6001600160a01b0316330361014d5761014a8161034f565b60006102176102f1565b6001600160a01b031633036101e2576101dd6102f1565b6102366102f1565b6001600160a01b031633036101165760405162461bcd60e51b815260206004820152604260248201527f5472616e73706172656e745570677261646561626c6550726f78793a2061646d60448201527f696e2063616e6e6f742066616c6c6261636b20746f2070726f78792074617267606482015261195d60f21b608482015260a4015b60405180910390fd5b60006101dd6103a3565b3660008037600080366000845af43d6000803e8080156102ec573d6000f35b3d6000fd5b60007fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035b546001600160a01b0316919050565b61032d836103cb565b60008251118061033a5750805b156101af57610349838361040b565b50505050565b7f7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f6103786102f1565b604080516001600160a01b03928316815291841660208301520160405180910390a161014a81610437565b60007f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc610315565b6103d4816104e0565b6040516001600160a01b038216907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b90600090a250565b606061043083836040518060600160405280602781526020016107c560279139610574565b9392505050565b6001600160a01b03811661049c5760405162461bcd60e51b815260206004820152602660248201527f455243313936373a206e65772061646d696e20697320746865207a65726f206160448201526564647265737360d01b60648201526084016102ba565b807fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035b80546001600160a01b0319166001600160a01b039290921691909117905550565b6001600160a01b0381163b61054d5760405162461bcd60e51b815260206004820152602d60248201527f455243313936373a206e657720696d706c656d656e746174696f6e206973206e60448201526c1bdd08184818dbdb9d1c9858dd609a1b60648201526084016102ba565b807f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc6104bf565b6060600080856001600160a01b0316856040516105919190610775565b600060405180830381855af49150503d80600081146105cc576040519150601f19603f3d011682016040523d82523d6000602084013e6105d1565b606091505b50915091506105e2868383876105ec565b9695505050505050565b6060831561065b578251600003610654576001600160a01b0385163b6106545760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e747261637400000060448201526064016102ba565b5081610665565b610665838361066d565b949350505050565b81511561067d5781518083602001fd5b8060405162461bcd60e51b81526004016102ba9190610791565b80356001600160a01b03811681146106ae57600080fd5b919050565b6000602082840312156106c557600080fd5b61043082610697565b6000806000604084860312156106e357600080fd5b6106ec84610697565b9250602084013567ffffffffffffffff8082111561070957600080fd5b818601915086601f83011261071d57600080fd5b81358181111561072c57600080fd5b87602082850101111561073e57600080fd5b6020830194508093505050509250925092565b60005b8381101561076c578181015183820152602001610754565b50506000910152565b60008251610787818460208701610751565b9190910192915050565b60208152600082518060208401526107b0816040850160208701610751565b601f01601f1916919091016040019291505056fe416464726573733a206c6f772d6c6576656c2064656c65676174652063616c6c206661696c6564a2646970667358221220caef1c2a647344b8936c2def885861b955c9b56ccb762c5243ac8ec49af2096f64736f6c63430008140033", + "balance": "0x0" + }, + "0x0000777700000000000000000000000000000001": { + "contractName": "ProxiedTaikoL2", + "storage": {}, + "code": "0x608060405234801561001057600080fd5b50600436106101375760003560e01c80639ee512f2116100b8578063c7b969081161007c578063c7b96908146102f3578063da69d3db1461030d578063dac5df7814610320578063ee82ac5e14610329578063f2fde38b1461033c578063f535bd561461034f57600080fd5b80639ee512f21461028e578063a86f9d9e146102a7578063b8914ce4146102ba578063bacb386d146102cd578063c20ebea5146102e057600080fd5b8063591aad8a116100ff578063591aad8a1461021d5780635c82e9c21461024f5780636c6563f614610262578063715018a6146102755780638da5cb5b1461027d57600080fd5b80630652b57a1461013c57806310da3738146101515780633ab76e9f1461018b5780634e755573146101b0578063539b8ade146101f2575b600080fd5b61014f61014a3660046116de565b610369565b005b6101787f92954368afd3caa1f3ce3ead0069c1af414054aefe1ef9aeacc1bf426222ce3881565b6040519081526020015b60405180910390f35b6097546001600160a01b03165b6040516001600160a01b039091168152602001610182565b6101b86103ec565b6040805182516001600160801b031681526020808401516001600160401b0316908201529181015163ffffffff1690820152606001610182565b60cd54610205906001600160401b031681565b6040516001600160401b039091168152602001610182565b61023061022b3660046116fb565b61044f565b6040805160ff9094168452602084019290925290820152606001610182565b61014f61025d366004611731565b61068a565b610198610270366004611782565b610a46565b61014f610a5d565b6065546001600160a01b0316610198565b61019871777735367b36bc9b61c50022d9d0700db4ec81565b6101986102b53660046117b7565b610a71565b6101786102c83660046117e3565b610a87565b6101786102db3660046117e3565b610ac3565b6101786102ee366004611810565b610afc565b60cd5461020590600160401b90046001600160401b031681565b61014f61031b366004611861565b610b20565b61017860cb5481565b6101786103373660046117e3565b610d8b565b61014f61034a3660046116de565b610dd8565b60cd5461020590600160801b90046001600160401b031681565b610371610e51565b6001600160a01b03811661039857604051634d084d8560e11b815260040160405180910390fd5b609780546001600160a01b0319166001600160a01b0383169081179091556040519081527f399ded90cb5ed8d89ef7e76ff4af65c373f06d3bf5d7eef55f4228e7b702a18b9060200160405180910390a150565b6040805160608101825260008082526020820181905291810191909152506040805160608101825260cc546001600160801b0381168252600160801b81046001600160401b03166020830152600160c01b900463ffffffff169181019190915290565b60008060008360ff1660011415801561046c57508360ff16600214155b1561048a5760405163bcd2d90d60e01b815260040160405180910390fd5b8360ff166001146104bb577fc6047f9441ed7d6d3045406e95c07cd85c778e4b8cef3ca7abac09b95c709ee56104dd565b7f79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f817985b915060008460ff16600114610512577fad77eceea844778cb4376153fc8f06f12f1695df4585bf75bfb17ec19ce90818610534565b7fb4a95509ce05fe8d45987859a067780d16a367c0e2cacf79cd301b93fb7179405b905060008560ff16600114610569577f71620584f61c57e688bbd3fd7a39a036e588d962c4c830f3dacbc15c917e02f261058b565b7f45b59254b0320fd853f3f38ac574999e91bd75fd5e6cab9c22c5e71fc6d276e45b82880192831001905060ff86166001036105c5576105be8282600170014551231950b75fc4402da1732fc9bebe19610eab565b9250610634565b61060d7f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a16106088484600170014551231950b75fc4402da1732fc9bebe19610eab565b610efa565b90925090506106318282600170014551231950b75fc4402da1732fc9bebe19610eab565b92505b7f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a0831115610681576106788370014551231950b75fc4402da1732fc9bebe196118bd565b92506001851894505b50509250925092565b600054610100900460ff16158080156106aa5750600054600160ff909116105b806106c45750303b1580156106c4575060005460ff166001145b61072c5760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b60648201526084015b60405180910390fd5b6000805460ff19166001179055801561074f576000805461ff0019166101001790555b600146111580610763575063ffffffff4610155b15610781576040516306cffa2760e01b815260040160405180910390fd5b60014311156107a357604051635a0f9e4160e11b815260040160405180910390fd5b6107b360408301602084016118d0565b63ffffffff16156109a2576107cb60208301836118eb565b6001600160401b031615806107f657506107eb60608301604084016118eb565b6001600160401b0316155b80610817575061080c60808301606084016118eb565b6001600160401b0316155b80610838575061082d60a08301608084016118eb565b6001600160401b0316155b1561085657604051639cc448b560e01b815260040160405180910390fd5b60008061089e61086c60608601604087016118eb565b61087960208701876118eb565b61088960808801606089016118eb565b61089960a0890160808a016118eb565b610f19565b91509150816001600160801b0316600014806108ca57506001600160401b036001600160801b03831610155b806108dc57506001600160801b038116155b156108fa57604051639cc448b560e01b815260040160405180910390fd5b60cc80546001600160401b038416600160801b026001600160c01b03199091166001600160801b0384161717905561093860408501602086016118d0565b60cc805463ffffffff92909216600160c01b0263ffffffff60c01b19909216919091179055600261096f60608601604087016118eb565b610979919061191c565b60cd60106101000a8154816001600160401b0302191690836001600160401b0316021790555050505b60cd805467ffffffffffffffff1916426001600160401b03161790556109c783611018565b6109d043611031565b5060cb5543156109fb5760006109e76001436118bd565b600081815260c96020526040902090409055505b8015610a41576000805461ff0019169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b505050565b6000610a538484846110c4565b90505b9392505050565b610a65610e51565b610a6f6000611178565b565b6000610a7e4684846110c4565b90505b92915050565b6000808215610a965782610aaa565b60cd54600160401b90046001600160401b03165b600090815260ca60205260409020600101549392505050565b6000808215610ad25782610ae6565b60cd54600160401b90046001600160401b03165b600090815260ca60205260409020549392505050565b6000610b17610b096103ec565b8563ffffffff1685856111ca565b50949350505050565b3371777735367b36bc9b61c50022d9d0700db4ec14610b5257604051636494e9f760e01b815260040160405180910390fd5b6000610b5f6001436118bd565b90508040600080610b6f84611031565b915091508160cb5414610ba35760cb54604051636340d9fb60e11b8152600481019190915260248101839052604401610723565b60cb819055600084815260c96020908152604080832086905560cd80546fffffffffffffffff00000000000000001916600160401b6001600160401b038c1690810291909117909155815180830183528c81528084018c815282865260ca8552948390209051815593516001949094019390935580518b81529182018a90527f7528bbd1cef0e5d13408706892a51ee8ef82bbf33d4ec0c37216f8beba71205b910160405180910390a2600080610c586103ec565b9050806040015163ffffffff16600014610cbd5760cd54610c8f908290610c88906001600160401b0316426118bd565b458a6111ca565b60cd80546001600160401b03909216600160801b0267ffffffffffffffff60801b1990921691909117905591505b814814610cf057604051634083acad60e01b81526001600160401b03808416600483015248166024820152604401610723565b60cd80546001600160401b0342811667ffffffffffffffff19909216821790925560408051438416815292851660208401524563ffffffff908116848301526060840192909252608083018890524460a08401524160c08401524690911660e0830152517ff5e89a4a67ffebdbc23df567479d3096c1dba4169c6bbf20ffc6b24d7f6e6e70918190036101000190a150505050505050505050565b6000438210610d9c57506000919050565b4382108015610db65750610db2610100436118bd565b8210155b15610dc057504090565b50600090815260c9602052604090205490565b919050565b610de0610e51565b6001600160a01b038116610e455760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b6064820152608401610723565b610e4e81611178565b50565b6065546001600160a01b03163314610a6f5760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610723565b600060405160408152602080820152602060408201528460608201528560808201528360a08201528260c082015260208160e08360056107d05a03fa610ef057600080fd5b5195945050505050565b6000806000198385098385029250828110838203039150509250929050565b600080856001600160401b0316600003610f3557610f35611942565b6000610f4260028861191c565b9050610f606001600160401b038816680755bf798b4a1bf1e4611958565b9250610f7f610f7a84886001600160401b03168489611276565b611335565b91506000610f8f84848489611276565b90506000610fa9858585610fa48b6002611972565b611276565b9050600082610fba8361271061199d565b610fc491906119b4565b9050806001600160401b0316876001600160401b03161461100b57604051631530943760e11b81526001600160401b03808916600483015282166024820152604401610723565b5050505094509492505050565b6110206113a2565b6110286113d1565b610e4e81611400565b60008061103c6116a9565b60005b60ff811080156110525750806001018510155b15611084576000198186030180408360ff83066101008110611076576110766119c8565b60200201525060010161103f565b5046611fe0820152612000812092508340816110a160ff876119de565b61010081106110b2576110b26119c8565b60200201526120009020919391925050565b60975460405163195ac1a960e21b815260048101859052602481018490526000916001600160a01b03169063656b06a490604401602060405180830381865afa158015611115573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061113991906119f2565b90508115801561115057506001600160a01b038116155b15610a5657604051631467050360e21b81526004810185905260248101849052604401610723565b606580546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b600080806202bf2063ffffffff8516116111e55760006111ec565b6202bf2084035b60cd5460408901519192506001600160401b03600160801b909104811663ffffffff8085169190910192811689029161123691839061122f908690839061144916565b039061145f565b935050505061125e86602001516001600160401b03168760000151838763ffffffff16611276565b91508160000361126d57600191505b94509492505050565b60006001600160801b0385161580159061129857506001600160801b03841615155b6112a4576112a4611942565b60006001600160401b038316156112bb57826112be565b60015b905060006112d5856001600160401b031688611474565b905060006112f56112e68488611a0f565b6001600160401b031689611474565b90506001600160801b0387166001600160401b03841661131584846118bd565b61131f91906119b4565b61132991906119b4565b98975050505050505050565b60006001600160801b0382111561139e5760405162461bcd60e51b815260206004820152602760248201527f53616665436173743a2076616c756520646f65736e27742066697420696e20316044820152663238206269747360c81b6064820152608401610723565b5090565b600054610100900460ff166113c95760405162461bcd60e51b815260040161072390611a36565b610a6f6114c6565b600054610100900460ff166113f85760405162461bcd60e51b815260040161072390611a36565b610a6f6114f3565b6001600160a01b03811661142757604051634d084d8560e11b815260040160405180910390fd5b609780546001600160a01b0319166001600160a01b0392909216919091179055565b60008183116114585781610a7e565b5090919050565b600081831161146e5782610a7e565b50919050565b60008061148a6001600160801b0384168561199d565b9050680755bf798b4a1bf1e481106114b55760405163576ff4f160e01b815260040160405180910390fd5b6114be81611523565b949350505050565b600054610100900460ff166114ed5760405162461bcd60e51b815260040161072390611a36565b60018055565b600054610100900460ff1661151a5760405162461bcd60e51b815260040161072390611a36565b610a6f33611178565b6000680248ce36a70cb26b3e19821361153e57506000919050565b680755bf798b4a1bf1e5821261156757604051631a93c68960e11b815260040160405180910390fd5b6503782dace9d9604e83901b059150600060606bb17217f7d1cf79abc9e3b39884821b6d2c06887d92262d378b9593af35346c09791803c2923d5d9721c3da80929091056001605f1b0190921d6bb17217f7d1cf79abc9e3b39881029095039081018102606090811d6d019dd9374d4315c8464a395fc09881016c1bff318b126baa436ea9aeaffd19840102821d93840193016d29c9ad45cc0beb0a2ff097a7bab40192909202821d6dcf3c27b2e487711b467e90f19320016c22fcd1cffa6fa000f6e27eeca082018202831d6d022f98fbc368092c79210d196fa0018202831d6d13aaae3ba38de06adc25ebfacc0901820290921d6d624dcbeb5e25df590e409325888a01026d360d7aeea093263ec6495851bd9760621b010574029d9dc38563c32e5c2f6dc192ee70ef65f9978af30260c3939093039290921c92915050565b604051806120000160405280610100906020820280368337509192915050565b6001600160a01b0381168114610e4e57600080fd5b6000602082840312156116f057600080fd5b8135610a56816116c9565b6000806040838503121561170e57600080fd5b82359150602083013560ff8116811461172657600080fd5b809150509250929050565b60008082840360c081121561174557600080fd5b8335611750816116c9565b925060a0601f198201121561176457600080fd5b506020830190509250929050565b80358015158114610dd357600080fd5b60008060006060848603121561179757600080fd5b83359250602084013591506117ae60408501611772565b90509250925092565b600080604083850312156117ca57600080fd5b823591506117da60208401611772565b90509250929050565b6000602082840312156117f557600080fd5b5035919050565b803563ffffffff81168114610dd357600080fd5b60008060006060848603121561182557600080fd5b61182e846117fc565b925061183c602085016117fc565b91506117ae604085016117fc565b80356001600160401b0381168114610dd357600080fd5b6000806000806080858703121561187757600080fd5b843593506020850135925061188e6040860161184a565b915061189c606086016117fc565b905092959194509250565b634e487b7160e01b600052601160045260246000fd5b81810381811115610a8157610a816118a7565b6000602082840312156118e257600080fd5b610a7e826117fc565b6000602082840312156118fd57600080fd5b610a7e8261184a565b634e487b7160e01b600052601260045260246000fd5b60006001600160401b038084168061193657611936611906565b92169190910492915050565b634e487b7160e01b600052600160045260246000fd5b60006001600160801b038084168061193657611936611906565b6001600160401b03818116838216028082169190828114611995576119956118a7565b505092915050565b8082028115828204841417610a8157610a816118a7565b6000826119c3576119c3611906565b500490565b634e487b7160e01b600052603260045260246000fd5b6000826119ed576119ed611906565b500690565b600060208284031215611a0457600080fd5b8151610a56816116c9565b6001600160401b03818116838216019080821115611a2f57611a2f6118a7565b5092915050565b6020808252602b908201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960408201526a6e697469616c697a696e6760a81b60608201526080019056fea2646970667358221220bd7f7091e6a697697091252fac98ba75d8b5eb2366b8463a9d05f995c921619164736f6c63430008140033", + "balance": "0x0" + }, + "0x1000777700000000000000000000000000000001": { + "contractName": "TaikoL2Proxy", + "storage": { + "0x00000000000000000000000000000000000000000000000000000000000000cb": "0xd02f27dfd81ca98ddc593afdc449ac14b6f636ece56d0f41f5aa383eaa73d02b", + "0x00000000000000000000000000000000000000000000000000000000000000cc": "0x0000000000bebc200000000058b8ef1c0000000485b9d2e799564d28c46075dd", + "0x00000000000000000000000000000000000000000000000000000000000000cd": "0x00000000000000000000000a9507f68000000000000000000000000064b16457", + "0x0000000000000000000000000000000000000000000000000000000000000097": "0x0000000000000000000000001000777700000000000000000000000000000006", + "0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103": "0x113cE23c9e0cc50F4D41d7cE6DA02dCAFf8BFF85", + "0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc": "0x0000777700000000000000000000000000000001" + }, + "code": "0x60806040526004361061004e5760003560e01c80633659cfe6146100655780634f1ef286146100855780635c60da1b146100985780638f283970146100c9578063f851a440146100e95761005d565b3661005d5761005b6100fe565b005b61005b6100fe565b34801561007157600080fd5b5061005b6100803660046106b3565b610118565b61005b6100933660046106ce565b610155565b3480156100a457600080fd5b506100ad6101bc565b6040516001600160a01b03909116815260200160405180910390f35b3480156100d557600080fd5b5061005b6100e43660046106b3565b6101ed565b3480156100f557600080fd5b506100ad61020d565b61010661022e565b6101166101116102c3565b6102cd565b565b6101206102f1565b6001600160a01b0316330361014d5761014a81604051806020016040528060008152506000610324565b50565b61014a6100fe565b61015d6102f1565b6001600160a01b031633036101b4576101af8383838080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525060019250610324915050565b505050565b6101af6100fe565b60006101c66102f1565b6001600160a01b031633036101e2576101dd6102c3565b905090565b6101ea6100fe565b90565b6101f56102f1565b6001600160a01b0316330361014d5761014a8161034f565b60006102176102f1565b6001600160a01b031633036101e2576101dd6102f1565b6102366102f1565b6001600160a01b031633036101165760405162461bcd60e51b815260206004820152604260248201527f5472616e73706172656e745570677261646561626c6550726f78793a2061646d60448201527f696e2063616e6e6f742066616c6c6261636b20746f2070726f78792074617267606482015261195d60f21b608482015260a4015b60405180910390fd5b60006101dd6103a3565b3660008037600080366000845af43d6000803e8080156102ec573d6000f35b3d6000fd5b60007fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035b546001600160a01b0316919050565b61032d836103cb565b60008251118061033a5750805b156101af57610349838361040b565b50505050565b7f7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f6103786102f1565b604080516001600160a01b03928316815291841660208301520160405180910390a161014a81610437565b60007f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc610315565b6103d4816104e0565b6040516001600160a01b038216907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b90600090a250565b606061043083836040518060600160405280602781526020016107c560279139610574565b9392505050565b6001600160a01b03811661049c5760405162461bcd60e51b815260206004820152602660248201527f455243313936373a206e65772061646d696e20697320746865207a65726f206160448201526564647265737360d01b60648201526084016102ba565b807fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035b80546001600160a01b0319166001600160a01b039290921691909117905550565b6001600160a01b0381163b61054d5760405162461bcd60e51b815260206004820152602d60248201527f455243313936373a206e657720696d706c656d656e746174696f6e206973206e60448201526c1bdd08184818dbdb9d1c9858dd609a1b60648201526084016102ba565b807f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc6104bf565b6060600080856001600160a01b0316856040516105919190610775565b600060405180830381855af49150503d80600081146105cc576040519150601f19603f3d011682016040523d82523d6000602084013e6105d1565b606091505b50915091506105e2868383876105ec565b9695505050505050565b6060831561065b578251600003610654576001600160a01b0385163b6106545760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e747261637400000060448201526064016102ba565b5081610665565b610665838361066d565b949350505050565b81511561067d5781518083602001fd5b8060405162461bcd60e51b81526004016102ba9190610791565b80356001600160a01b03811681146106ae57600080fd5b919050565b6000602082840312156106c557600080fd5b61043082610697565b6000806000604084860312156106e357600080fd5b6106ec84610697565b9250602084013567ffffffffffffffff8082111561070957600080fd5b818601915086601f83011261071d57600080fd5b81358181111561072c57600080fd5b87602082850101111561073e57600080fd5b6020830194508093505050509250925092565b60005b8381101561076c578181015183820152602001610754565b50506000910152565b60008251610787818460208701610751565b9190910192915050565b60208152600082518060208401526107b0816040850160208701610751565b601f01601f1916919091016040019291505056fe416464726573733a206c6f772d6c6576656c2064656c65676174652063616c6c206661696c6564a2646970667358221220caef1c2a647344b8936c2def885861b955c9b56ccb762c5243ac8ec49af2096f64736f6c63430008140033", + "balance": "0x0" + }, + "0x0000777700000000000000000000000000000004": { + "contractName": "ProxiedBridge", + "storage": {}, + "code": "0x60806040526004361061012e5760003560e01c8063715018a6116100ab578063bac443e21161006f578063bac443e21461041b578063ce70f39b1461043b578063d0496d6a1461045b578063f2fde38b146104ca578063f9803919146104ea578063fee99b221461050a57600080fd5b8063715018a6146103955780638da5cb5b146103aa57806396e17852146103c8578063a4444efd146103db578063a86f9d9e146103fb57600080fd5b8063540be6a3116100f2578063540be6a3146102e75780635817b0c3146103075780635d0bd98614610335578063606b5b74146103555780636c6563f61461037557600080fd5b80630652b57a1461020357806319ab453c14610223578063343b643c146102435780633ab76e9f146102885780635075a9d4146102ba57600080fd5b366101fe5761014c6a1d1bdad95b97dd985d5b1d60aa1b600161052a565b6001600160a01b0316336001600160a01b03161415801561019757506101816a195d1a195c97dd985d5b1d60aa1b600161052a565b6001600160a01b0316336001600160a01b031614155b80156101c757506101b1647461696b6f60d81b600161052a565b6001600160a01b0316336001600160a01b031614155b80156101de57506065546001600160a01b03163314155b156101fc576040516345dd044560e11b815260040160405180910390fd5b005b600080fd5b34801561020f57600080fd5b506101fc61021e366004612b75565b610540565b34801561022f57600080fd5b506101fc61023e366004612b75565b6105c3565b34801561024f57600080fd5b5061027361025e366004612b92565b600090815260cd602052604090205460ff1690565b60405190151581526020015b60405180910390f35b34801561029457600080fd5b506097546001600160a01b03165b6040516001600160a01b03909116815260200161027f565b3480156102c657600080fd5b506102da6102d5366004612b92565b6106db565b60405161027f9190612be3565b3480156102f357600080fd5b50610273610302366004612b92565b6106e6565b34801561031357600080fd5b50610327610322366004612c0a565b6106f2565b60405190815260200161027f565b34801561034157600080fd5b50610273610350366004612b92565b610705565b34801561036157600080fd5b50610327610370366004612b92565b610718565b34801561038157600080fd5b506102a2610390366004612c4c565b610723565b3480156103a157600080fd5b506101fc61073a565b3480156103b657600080fd5b506065546001600160a01b03166102a2565b6103276103d6366004612c0a565b61074e565b3480156103e757600080fd5b506102736103f6366004612ccd565b61077c565b34801561040757600080fd5b506102a2610416366004612d1f565b61052a565b34801561042757600080fd5b506101fc610436366004612d4f565b610794565b34801561044757600080fd5b50610273610456366004612ccd565b6107b8565b34801561046757600080fd5b50604080516060808201835260008083526020808401829052928401528251808201845260ca5480825260cb546001600160a01b0390811683860190815260cc54938701938452865192835251169381019390935251928201929092520161027f565b3480156104d657600080fd5b506101fc6104e5366004612b75565b6107c7565b3480156104f657600080fd5b506101fc610505366004612db7565b610840565b34801561051657600080fd5b506101fc610525366004612d4f565b61085e565b6000610537468484610874565b90505b92915050565b610548610928565b6001600160a01b03811661056f57604051634d084d8560e11b815260040160405180910390fd5b609780546001600160a01b0319166001600160a01b0383169081179091556040519081527f399ded90cb5ed8d89ef7e76ff4af65c373f06d3bf5d7eef55f4228e7b702a18b9060200160405180910390a150565b600054610100900460ff16158080156105e35750600054600160ff909116105b806105fd5750303b1580156105fd575060005460ff166001145b6106655760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b60648201526084015b60405180910390fd5b6000805460ff191660011790558015610688576000805461ff0019166101001790555b61069182610982565b80156106d7576000805461ff0019169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b5050565b600061053a8261099b565b600061053a30836109c6565b600061053a61070083612f0d565b610aa7565b60006107113083610ad7565b5092915050565b600061053a82610b60565b6000610730848484610874565b90505b9392505050565b610742610928565b61074c6000610b9b565b565b6000610758610bed565b61076c60c93061076785612f0d565b610c46565b905061077760018055565b919050565b600061078b3086868686610f27565b95945050505050565b61079c610bed565b6107aa60c93085858561108a565b6107b360018055565b505050565b600061078b308686868661137b565b6107cf610928565b6001600160a01b0381166108345760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b606482015260840161065c565b61083d81610b9b565b50565b610848610bed565b61085560c9308484611600565b6106d760018055565b610866610bed565b6107aa60c930858585611838565b60975460405163195ac1a960e21b815260048101859052602481018490526000916001600160a01b03169063656b06a490604401602060405180830381865afa1580156108c5573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108e9919061300e565b90508115801561090057506001600160a01b038116155b1561073357604051631467050360e21b8152600481018590526024810184905260440161065c565b6065546001600160a01b0316331461074c5760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015260640161065c565b61098a611d37565b610992611d66565b61083d81611d95565b6000806109a783610b60565b80549091508060038111156109be576109be612bab565b949350505050565b604051635437cecf60e11b81526000906001600160a01b0384169063a86f9d9e906109f590849060040161302b565b602060405180830381865afa158015610a12573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a36919061300e565b604051631933b5e360e11b8152306004820152602481018490526001600160a01b0391909116906332676bc690604401602060405180830381865afa158015610a83573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610537919061304d565b600081604051602001610aba91906130ba565b604051602081830303815290604052805190602001209050919050565b600080836001600160a01b0316636c6563f68460016040518363ffffffff1660e01b8152600401610b099291906131b4565b602060405180830381865afa158015610b26573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b4a919061300e565b6001600160a01b03811615159590945092505050565b60006040518060400160405280600e81526020016d4d4553534147455f53544154555360901b81525082604051602001610aba9291906131d3565b606580546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b600260015403610c3f5760405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c00604482015260640161065c565b6002600155565b60808101516000906001600160a01b0316610c74576040516301b1868360e71b815260040160405180910390fd5b600080610c85858560600151610ad7565b91509150811580610c995750468460600151145b15610cb75760405163e822b48d60e01b815260040160405180910390fd5b60a08401516001600160a01b03161580610ce65750806001600160a01b03168460a001516001600160a01b0316145b15610d045760405163b9ad6a0f60e01b815260040160405180910390fd5b60008461012001518561010001518660e00151610d21919061320b565b610d2b919061320b565b9050348114610d4d57604051632609a19760e21b815260040160405180910390fd5b604051635437cecf60e11b81526000906001600160a01b0388169063a86f9d9e90610d7d9060019060040161321e565b602060405180830381865afa158015610d9a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610dbe919061300e565b9050610dd36001600160a01b03821683611dde565b8754886000610de18361323d565b909155508652336020870152466040870152610dfc86610aa7565b604051635437cecf60e11b81529095506001600160a01b0388169063a86f9d9e90610e2c9060009060040161302b565b602060405180830381865afa158015610e49573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e6d919061300e565b6001600160a01b03166366ca2bc0866040518263ffffffff1660e01b8152600401610e9a91815260200190565b6020604051808303816000875af1158015610eb9573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610edd9190613256565b50847f47866f7dacd4a276245be6ed543cae03c9c17eb17e6980cee28e3dd168b7f9f387604051610f0e91906130ba565b60405180910390a2505050509392505050565b60018055565b600080866001600160a01b0316636c6563f68660006040518363ffffffff1660e01b8152600401610f599291906131b4565b602060405180830381865afa158015610f76573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f9a919061300e565b604051635437cecf60e11b81529091506001600160a01b0388169063a86f9d9e90610fca9060009060040161302b565b602060405180830381865afa158015610fe7573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061100b919061300e565b6001600160a01b0316635221f61386838988886040518663ffffffff1660e01b815260040161103e95949392919061326f565b602060405180830381865afa15801561105b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061107f919061304d565b979650505050505050565b600061109c60a0850160808601612b75565b6001600160a01b0316036110c3576040516301b1868360e71b815260040160405180910390fd5b468360400135146110e75760405163e822b48d60e01b815260040160405180910390fd5b60006110f561070085612f0d565b600081815260048801602052604090205490915060ff16151560010361112e5760405163afde133560e01b815260040160405180910390fd5b61113f85828660600135868661137b565b61115c5760405163498b0b1d60e01b815260040160405180910390fd5b60008181526004870160205260408120805460ff1916600117905561118a61010086013560e087013561320b565b9050801561131f57604051635437cecf60e11b81526000906001600160a01b0388169063a86f9d9e906111c29060019060040161321e565b602060405180830381865afa1580156111df573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611203919061300e565b90506001600160a01b03811615611298576001600160a01b03811663ba0bbd9561123360a0890160808a01612b75565b6040516001600160e01b031960e084901b1681526001600160a01b03909116600482015260248101859052604401600060405180830381600087803b15801561127b57600080fd5b505af115801561128f573d6000803e3d6000fd5b5050505061131d565b60006112aa60a0880160808901612b75565b6001600160a01b03168360405160006040518083038185875af1925050503d80600081146112f4576040519150601f19603f3d011682016040523d82523d6000602084013e6112f9565b606091505b505090508061131b5760405163f6664cf160e01b815260040160405180910390fd5b505b505b817fea00c741e39d1d9ab1c6703152d71f9da09a782ed4ae128414730dadbb9bd84761135160a0880160808901612b75565b604080516001600160a01b039092168252602082018590520160405180910390a250505050505050565b600046840361139d5760405163e822b48d60e01b815260040160405180910390fd5b60008590036113bf5760405163a6407c9360e01b815260040160405180910390fd5b60006113cd83850185613359565b604051635437cecf60e11b8152647461696b6f60d81b60048201526000602482018190529192506001600160a01b0389169063a86f9d9e90604401602060405180830381865afa158015611425573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611449919061300e565b8251610100015160405163bacb386d60e01b81526001600160801b0390911660048201526001600160a01b03919091169063bacb386d90602401602060405180830381865afa1580156114a0573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906114c49190613256565b90508015806114dd575081516114d990611e94565b8114155b156114ed5760009250505061078b565b815160600151604051633632b1fb60e11b815273d56fbBb9C88938a61e9CA71339Abd5f84dF131Cf9163a5427462916001600160a01b038c1690636c6563f69061153e908c906000906004016131b4565b602060405180830381865afa15801561155b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061157f919061300e565b6115888b610b60565b602087015160405160e086901b6001600160e01b03191681526115b3949392916003916004016134fd565b602060405180830381865af41580156115d0573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906115f4919061304d565b98975050505050505050565b610140820135158061160f5750805b156116555761162460a0830160808401612b75565b6001600160a01b0316336001600160a01b0316146116555760405163d7f4fc9f60e01b815260040160405180910390fd5b600061166361070084612f0d565b905060016116708261099b565b600381111561168157611681612bab565b1461169f57604051631f6646b560e01b815260040160405180910390fd5b604051635437cecf60e11b81526000906001600160a01b0386169063a86f9d9e906116cf9060019060040161321e565b602060405180830381865afa1580156116ec573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611710919061300e565b90506001600160a01b0381161561178057604051630d73bb3d60e41b815261010085013560048201526001600160a01b0382169063d73bb3d090602401600060405180830381600087803b15801561176757600080fd5b505af115801561177b573d6000803e3d6000fd5b505050505b61178c8685845a611eb9565b156117a15761179c826002612011565b611830565b8215611818576117b2826003612011565b6000806117c560e0870160c08801612b75565b6001600160a01b0316146117e8576117e360e0860160c08701612b75565b6117f8565b6117f860a0860160808701612b75565b90506118126001600160a01b038216610100870135611dde565b50611830565b6118306001600160a01b038216610100860135611dde565b505050505050565b61014083013515801561186c575061185660a0840160808501612b75565b6001600160a01b0316336001600160a01b031614155b1561188a5760405163398b635960e21b815260040160405180910390fd5b468360600135146118ae5760405163e822b48d60e01b815260040160405180910390fd5b60006118bc61070085612f0d565b905060006118c98261099b565b60038111156118da576118da612bab565b146118f857604051630cfafbf960e01b815260040160405180910390fd5b6000856001600160a01b0316636c6563f6866040013560006040518363ffffffff1660e01b815260040161192d9291906131b4565b602060405180830381865afa15801561194a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061196e919061300e565b604051635437cecf60e11b81529091506001600160a01b0387169063a86f9d9e9061199e9060009060040161302b565b602060405180830381865afa1580156119bb573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906119df919061300e565b6001600160a01b0316635221f6138660400135838588886040518663ffffffff1660e01b8152600401611a1695949392919061326f565b602060405180830381865afa158015611a33573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611a57919061304d565b611a74576040516314504c7360e31b815260040160405180910390fd5b6000610120860135611a8f61010088013560e089013561320b565b611a99919061320b565b90506000876001600160a01b031663a86f9d9e60016040518263ffffffff1660e01b8152600401611aca919061321e565b602060405180830381865afa158015611ae7573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611b0b919061300e565b90506001600160a01b03811615801590611b255750600082115b15611b8557604051630d73bb3d60e41b8152600481018390526001600160a01b0382169063d73bb3d090602401600060405180830381600087803b158015611b6c57600080fd5b505af1158015611b80573d6000803e3d6000fd5b505050505b611bac60e0880135611b9d60a08a0160808b01612b75565b6001600160a01b031690611dde565b60008030611bc060c08b0160a08c01612b75565b6001600160a01b03161480611bed57506000611be260c08b0160a08c01612b75565b6001600160a01b0316145b15611c02575060029050610100880135611c79565b6000611c1460a08b0160808c01612b75565b6001600160a01b0316336001600160a01b031614611c3757896101400135611c39565b5a5b90506000611c498d8c8a85611eb9565b90508015611c5a5760029350611c76565b60019350611c766001600160a01b0386166101008d0135611dde565b50505b611c838683612011565b600080611c9660e08c0160c08d01612b75565b6001600160a01b031614611cb957611cb460e08b0160c08c01612b75565b611cc9565b611cc960a08b0160808c01612b75565b90506001600160a01b0381163303611d07576000611cec836101208d013561320b565b9050611d016001600160a01b03831682611dde565b50611d29565b611d16336101208c0135611dde565b611d296001600160a01b03821683611dde565b505050505050505050505050565b600054610100900460ff16611d5e5760405162461bcd60e51b815260040161065c90613530565b61074c61208a565b600054610100900460ff16611d8d5760405162461bcd60e51b815260040161065c90613530565b61074c6120b1565b6001600160a01b038116611dbc57604051634d084d8560e11b815260040160405180910390fd5b609780546001600160a01b0319166001600160a01b0392909216919091179055565b801580611df257506001600160a01b038216155b15611dfb575050565b6000826001600160a01b03168260405160006040518083038185875af1925050503d8060008114611e48576040519150601f19603f3d011682016040523d82523d6000602084013e611e4d565b606091505b50509050806107b35760405162461bcd60e51b8152602060048201526013602482015272115512081d1c985b9cd9995c8819985a5b1959606a1b604482015260640161065c565b600080611eaa611ea58460006120e1565b612502565b80516020909101209392505050565b600081600003611edc57604051637f0e960960e11b815260040160405180910390fd5b6040518060600160405280848152602001856020016020810190611f009190612b75565b6001600160a01b039081168252604087810135602093840152835160018a0155918301516002890180546001600160a01b0319169190921617905501516003860155611f5260c0850160a08601612b75565b6001600160a01b031682610100860135611f7061016088018861357b565b604051611f7e9291906135c1565b600060405180830381858888f193505050503d8060008114611fbc576040519150601f19603f3d011682016040523d82523d6000602084013e611fc1565b606091505b505060408051606081018252600180825260208201819052600019919092018190528782018290556002880180546001600160a01b03191690921790915560039096019590955550929392505050565b80600381111561202357612023612bab565b61202c8361099b565b600381111561203d5761203d612bab565b146106d75761204c8282612546565b817f0af4d5247f6a4028d6699afb62871a76b398da1d1a626c8a9b90e0bd5f54c73c823360405161207e9291906135d1565b60405180910390a25050565b600054610100900460ff16610f215760405162461bcd60e51b815260040161065c90613530565b600054610100900460ff166120d85760405162461bcd60e51b815260040161065c90613530565b61074c33610b9b565b6102008201516060901561214c576120fa82601161320b565b6001600160401b0381111561211157612111612dfd565b60405190808252806020026020018201604052801561214457816020015b606081526020019060019003908161212f5790505b5090506121bb565b6101e083015115612162576120fa82601061320b565b61216d82600f61320b565b6001600160401b0381111561218457612184612dfd565b6040519080825280602002602001820160405280156121b757816020015b60608152602001906001900390816121a25790505b5090505b82516121c69061256f565b816000815181106121d9576121d96135f7565b60200260200101819052506121f1836020015161256f565b81600181518110612204576122046135f7565b602002602001018190525061221c8360400151612582565b8160028151811061222f5761222f6135f7565b6020026020010181905250612247836060015161256f565b8160038151811061225a5761225a6135f7565b6020026020010181905250612272836080015161256f565b81600481518110612285576122856135f7565b602002602001018190525061229d8360a0015161256f565b816005815181106122b0576122b06135f7565b60200260200101819052506122e78360c001516040516020016122d3919061360d565b6040516020818303038152906040526125ab565b816006815181106122fa576122fa6135f7565b60200260200101819052506123128360e0015161261a565b81600781518110612325576123256135f7565b60200260200101819052506123478361010001516001600160801b031661261a565b8160088151811061235a5761235a6135f7565b6020026020010181905250612373836101200151612628565b81600981518110612386576123866135f7565b602002602001018190525061239f836101400151612628565b81600a815181106123b2576123b26135f7565b60200260200101819052506123cb836101600151612628565b81600b815181106123de576123de6135f7565b60200260200101819052506123f78361018001516125ab565b81600c8151811061240a5761240a6135f7565b6020026020010181905250612423836101a0015161256f565b81600d81518110612436576124366135f7565b602002602001018190525061246d836101c001516040516020016122d3919060c09190911b6001600160c01b031916815260080190565b81600e81518110612480576124806135f7565b6020026020010181905250826101e001516000146124c5576124a6836101e0015161261a565b81600f815181106124b9576124b96135f7565b60200260200101819052505b6102008301511561053a576124de83610200015161256f565b816010815181106124f1576124f16135f7565b602002602001018190525092915050565b6060600061250f8361263f565b905061251d815160c0612774565b8160405160200161252f929190613642565b604051602081830303815290604052915050919050565b600061255183610b60565b9050600082600381111561256757612567612bab565b909155505050565b606061053a61257d8361291c565b6125ab565b604051606082811b6bffffffffffffffffffffffff191660208301529061053a906034016122d3565b606080825160011480156125d957506080836000815181106125cf576125cf6135f7565b016020015160f81c105b156125e557508161053a565b6125f183516080612774565b83604051602001612603929190613642565b604051602081830303815290604052905092915050565b606061053a61257d836129ce565b606061053a61257d836001600160401b03166129ce565b60608151600003612660576040805160008082526020820190925290610711565b6000805b83518110156126a55783818151811061267f5761267f6135f7565b60200260200101515182612693919061320b565b915061269e8161323d565b9050612664565b6000826001600160401b038111156126bf576126bf612dfd565b6040519080825280601f01601f1916602001820160405280156126e9576020820181803683370190505b50600092509050602081015b855183101561276b576000868481518110612712576127126135f7565b60200260200101519050600060208201905061273083828451612af8565b878581518110612742576127426135f7565b60200260200101515183612756919061320b565b92505050826127649061323d565b92506126f5565b50949350505050565b60608060388410156127db57604080516001808252818301909252906020820181803683370190505090506127a98385613671565b60f81b816000815181106127bf576127bf6135f7565b60200101906001600160f81b031916908160001a905350610537565b600060015b6127ea81876136a0565b1561280d576127f88261323d565b9150612806610100826136b4565b90506127e0565b61281882600161320b565b6001600160401b0381111561282f5761282f612dfd565b6040519080825280601f01601f191660200182016040528015612859576020820181803683370190505b5092506128668583613671565b612871906037613671565b60f81b83600081518110612887576128876135f7565b60200101906001600160f81b031916908160001a905350600190505b818111612913576101006128b782846136cb565b6128c3906101006137c2565b6128cd90886136a0565b6128d791906137ce565b60f81b8382815181106128ec576128ec6135f7565b60200101906001600160f81b031916908160001a90535061290c8161323d565b90506128a3565b50509392505050565b606060008260405160200161293391815260200190565b60408051808303601f1901815260208084528383019092529250600091829160208201818036833701905050905060005b815181101561276b5783836129788161323d565b94508151811061298a5761298a6135f7565b602001015160f81c60f81b8282815181106129a7576129a76135f7565b60200101906001600160f81b031916908160001a9053506129c78161323d565b9050612964565b60606000826040516020016129e591815260200190565b604051602081830303815290604052905060005b6020811015612a3a57818181518110612a1457612a146135f7565b01602001516001600160f81b031916600003612a3a57612a338161323d565b90506129f9565b6000612a478260206136cb565b6001600160401b03811115612a5e57612a5e612dfd565b6040519080825280601f01601f191660200182016040528015612a88576020820181803683370190505b50905060005b815181101561276b578383612aa28161323d565b945081518110612ab457612ab46135f7565b602001015160f81c60f81b828281518110612ad157612ad16135f7565b60200101906001600160f81b031916908160001a905350612af18161323d565b9050612a8e565b8282825b60208110612b345781518352612b1360208461320b565b9250612b2060208361320b565b9150612b2d6020826136cb565b9050612afc565b905182516020929092036101000a6000190180199091169116179052505050565b6001600160a01b038116811461083d57600080fd5b803561077781612b55565b600060208284031215612b8757600080fd5b813561053781612b55565b600060208284031215612ba457600080fd5b5035919050565b634e487b7160e01b600052602160045260246000fd5b60048110612bdf57634e487b7160e01b600052602160045260246000fd5b9052565b6020810161053a8284612bc1565b60006101a08284031215612c0457600080fd5b50919050565b600060208284031215612c1c57600080fd5b81356001600160401b03811115612c3257600080fd5b6109be84828501612bf1565b801515811461083d57600080fd5b600080600060608486031215612c6157600080fd5b83359250602084013591506040840135612c7a81612c3e565b809150509250925092565b60008083601f840112612c9757600080fd5b5081356001600160401b03811115612cae57600080fd5b602083019150836020828501011115612cc657600080fd5b9250929050565b60008060008060608587031215612ce357600080fd5b843593506020850135925060408501356001600160401b03811115612d0757600080fd5b612d1387828801612c85565b95989497509550505050565b60008060408385031215612d3257600080fd5b823591506020830135612d4481612c3e565b809150509250929050565b600080600060408486031215612d6457600080fd5b83356001600160401b0380821115612d7b57600080fd5b612d8787838801612bf1565b94506020860135915080821115612d9d57600080fd5b50612daa86828701612c85565b9497909650939450505050565b60008060408385031215612dca57600080fd5b82356001600160401b03811115612de057600080fd5b612dec85828601612bf1565b9250506020830135612d4481612c3e565b634e487b7160e01b600052604160045260246000fd5b6040516101a081016001600160401b0381118282101715612e3657612e36612dfd565b60405290565b604080519081016001600160401b0381118282101715612e3657612e36612dfd565b60405161022081016001600160401b0381118282101715612e3657612e36612dfd565b600082601f830112612e9257600080fd5b81356001600160401b0380821115612eac57612eac612dfd565b604051601f8301601f19908116603f01168101908282118183101715612ed457612ed4612dfd565b81604052838152866020858801011115612eed57600080fd5b836020870160208301376000602085830101528094505050505092915050565b60006101a08236031215612f2057600080fd5b612f28612e13565b82358152612f3860208401612b6a565b60208201526040830135604082015260608301356060820152612f5d60808401612b6a565b6080820152612f6e60a08401612b6a565b60a0820152612f7f60c08401612b6a565b60c082015260e08381013590820152610100808401359082015261012080840135908201526101408084013590820152610160808401356001600160401b0380821115612fcb57600080fd5b612fd736838801612e81565b83850152610180925082860135915080821115612ff357600080fd5b5061300036828701612e81565b918301919091525092915050565b60006020828403121561302057600080fd5b815161053781612b55565b6d7369676e616c5f7365727669636560901b8152901515602082015260400190565b60006020828403121561305f57600080fd5b815161053781612c3e565b60005b8381101561308557818101518382015260200161306d565b50506000910152565b600081518084526130a681602086016020860161306a565b601f01601f19169290920160200192915050565b6020815281516020820152600060208301516130e160408401826001600160a01b03169052565b506040830151606083015260608301516080830152608083015161311060a08401826001600160a01b03169052565b5060a08301516001600160a01b03811660c08401525060c08301516001600160a01b03811660e08401525060e0830151610100838101919091528301516101208084019190915283015161014080840191909152830151610160808401919091528301516101a061018080850182905261318e6101c086018461308e565b90860151858203601f1901838701529092506131aa838261308e565b9695505050505050565b9182526562726964676560d01b60208301521515604082015260600190565b600083516131e581846020880161306a565b9190910191825250602001919050565b634e487b7160e01b600052601160045260246000fd5b8082018082111561053a5761053a6131f5565b6a195d1a195c97dd985d5b1d60aa1b8152901515602082015260400190565b60006001820161324f5761324f6131f5565b5060010190565b60006020828403121561326857600080fd5b5051919050565b8581526001600160a01b0385166020820152604081018490526080606082018190528101829052818360a0830137600081830160a090810191909152601f909201601f19160101949350505050565b600082601f8301126132cf57600080fd5b6040516101008082018281106001600160401b03821117156132f3576132f3612dfd565b6040528301818582111561330657600080fd5b845b82811015613320578035825260209182019101613308565b509195945050505050565b80356001600160801b038116811461077757600080fd5b80356001600160401b038116811461077757600080fd5b60006020828403121561336b57600080fd5b81356001600160401b038082111561338257600080fd5b908301906040828603121561339657600080fd5b61339e612e3c565b8235828111156133ad57600080fd5b830161030081880312156133c057600080fd5b6133c8612e5e565b81358152602082013560208201526133e260408301612b6a565b6040820152606082013560608201526080820135608082015260a082013560a08201526134128860c084016132be565b60c08201526101c08083013560e08301526101e061343181850161332b565b610100840152610200613445818601613342565b6101208501526134586102208601613342565b61014085015261346b6102408601613342565b6101608501526102608501358781111561348457600080fd5b6134908c828801612e81565b610180860152506102808501356101a08501526134b06102a08601613342565b838501526102c0850135828501526102e08501358185015250505080835250506020830135828111156134e257600080fd5b6134ee87828601612e81565b60208301525095945050505050565b85815260018060a01b038516602082015283604082015282606082015260a06080820152600061107f60a083018461308e565b6020808252602b908201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960408201526a6e697469616c697a696e6760a81b606082015260800190565b6000808335601e1984360301811261359257600080fd5b8301803591506001600160401b038211156135ac57600080fd5b602001915036819003821315612cc657600080fd5b8183823760009101908152919050565b604081016135df8285612bc1565b6001600160a01b039290921660209190910152919050565b634e487b7160e01b600052603260045260246000fd5b60008183825b6008811015613632578151835260209283019290910190600101613613565b5050506101008201905092915050565b6000835161365481846020880161306a565b83519083019061366881836020880161306a565b01949350505050565b60ff818116838216019081111561053a5761053a6131f5565b634e487b7160e01b600052601260045260246000fd5b6000826136af576136af61368a565b500490565b808202811582820484141761053a5761053a6131f5565b8181038181111561053a5761053a6131f5565b600181815b808511156137195781600019048211156136ff576136ff6131f5565b8085161561370c57918102915b93841c93908002906136e3565b509250929050565b6000826137305750600161053a565b8161373d5750600061053a565b8160018114613753576002811461375d57613779565b600191505061053a565b60ff84111561376e5761376e6131f5565b50506001821b61053a565b5060208310610133831016604e8410600b841016171561379c575081810a61053a565b6137a683836136de565b80600019048211156137ba576137ba6131f5565b029392505050565b60006105378383613721565b6000826137dd576137dd61368a565b50069056fea2646970667358221220375c4de0362d3ed6e76edb571acb958d89d208d7216e0c416a7cdb4ee2dfeba764736f6c63430008140033", + "balance": "0x0" + }, + "0x1000777700000000000000000000000000000004": { + "contractName": "BridgeProxy", + "storage": { + "0x0000000000000000000000000000000000000000000000000000000000000000": "0x0000000000000000000000000000000000000000000000000000000000000001", + "0x0000000000000000000000000000000000000000000000000000000000000001": "0x0000000000000000000000000000000000000000000000000000000000000001", + "0x0000000000000000000000000000000000000000000000000000000000000065": "0x00000000000000000000000019b4f9c381c7927fe33d853e48b560141a380c44", + "0x0000000000000000000000000000000000000000000000000000000000000097": "0x0000000000000000000000001000777700000000000000000000000000000006", + "0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103": "0x113cE23c9e0cc50F4D41d7cE6DA02dCAFf8BFF85", + "0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc": "0x0000777700000000000000000000000000000004" + }, + "code": "0x60806040526004361061004e5760003560e01c80633659cfe6146100655780634f1ef286146100855780635c60da1b146100985780638f283970146100c9578063f851a440146100e95761005d565b3661005d5761005b6100fe565b005b61005b6100fe565b34801561007157600080fd5b5061005b6100803660046106b3565b610118565b61005b6100933660046106ce565b610155565b3480156100a457600080fd5b506100ad6101bc565b6040516001600160a01b03909116815260200160405180910390f35b3480156100d557600080fd5b5061005b6100e43660046106b3565b6101ed565b3480156100f557600080fd5b506100ad61020d565b61010661022e565b6101166101116102c3565b6102cd565b565b6101206102f1565b6001600160a01b0316330361014d5761014a81604051806020016040528060008152506000610324565b50565b61014a6100fe565b61015d6102f1565b6001600160a01b031633036101b4576101af8383838080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525060019250610324915050565b505050565b6101af6100fe565b60006101c66102f1565b6001600160a01b031633036101e2576101dd6102c3565b905090565b6101ea6100fe565b90565b6101f56102f1565b6001600160a01b0316330361014d5761014a8161034f565b60006102176102f1565b6001600160a01b031633036101e2576101dd6102f1565b6102366102f1565b6001600160a01b031633036101165760405162461bcd60e51b815260206004820152604260248201527f5472616e73706172656e745570677261646561626c6550726f78793a2061646d60448201527f696e2063616e6e6f742066616c6c6261636b20746f2070726f78792074617267606482015261195d60f21b608482015260a4015b60405180910390fd5b60006101dd6103a3565b3660008037600080366000845af43d6000803e8080156102ec573d6000f35b3d6000fd5b60007fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035b546001600160a01b0316919050565b61032d836103cb565b60008251118061033a5750805b156101af57610349838361040b565b50505050565b7f7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f6103786102f1565b604080516001600160a01b03928316815291841660208301520160405180910390a161014a81610437565b60007f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc610315565b6103d4816104e0565b6040516001600160a01b038216907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b90600090a250565b606061043083836040518060600160405280602781526020016107c560279139610574565b9392505050565b6001600160a01b03811661049c5760405162461bcd60e51b815260206004820152602660248201527f455243313936373a206e65772061646d696e20697320746865207a65726f206160448201526564647265737360d01b60648201526084016102ba565b807fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035b80546001600160a01b0319166001600160a01b039290921691909117905550565b6001600160a01b0381163b61054d5760405162461bcd60e51b815260206004820152602d60248201527f455243313936373a206e657720696d706c656d656e746174696f6e206973206e60448201526c1bdd08184818dbdb9d1c9858dd609a1b60648201526084016102ba565b807f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc6104bf565b6060600080856001600160a01b0316856040516105919190610775565b600060405180830381855af49150503d80600081146105cc576040519150601f19603f3d011682016040523d82523d6000602084013e6105d1565b606091505b50915091506105e2868383876105ec565b9695505050505050565b6060831561065b578251600003610654576001600160a01b0385163b6106545760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e747261637400000060448201526064016102ba565b5081610665565b610665838361066d565b949350505050565b81511561067d5781518083602001fd5b8060405162461bcd60e51b81526004016102ba9190610791565b80356001600160a01b03811681146106ae57600080fd5b919050565b6000602082840312156106c557600080fd5b61043082610697565b6000806000604084860312156106e357600080fd5b6106ec84610697565b9250602084013567ffffffffffffffff8082111561070957600080fd5b818601915086601f83011261071d57600080fd5b81358181111561072c57600080fd5b87602082850101111561073e57600080fd5b6020830194508093505050509250925092565b60005b8381101561076c578181015183820152602001610754565b50506000910152565b60008251610787818460208701610751565b9190910192915050565b60208152600082518060208401526107b0816040850160208701610751565b601f01601f1916919091016040019291505056fe416464726573733a206c6f772d6c6576656c2064656c65676174652063616c6c206661696c6564a2646970667358221220caef1c2a647344b8936c2def885861b955c9b56ccb762c5243ac8ec49af2096f64736f6c63430008140033", + "balance": "0x0" + }, + "0x0000777700000000000000000000000000000002": { + "contractName": "ProxiedTokenVault", + "storage": {}, + "code": "0x6080604052600436106100e85760003560e01c8063780b64f01161008a578063a86f9d9e11610059578063a86f9d9e146102ca578063c287e578146102ea578063ee1490b21461032a578063f2fde38b1461033d57600080fd5b8063780b64f0146101fc5780638da5cb5b1461025b5780639754149b146102795780639aa8605c1461029957600080fd5b80633ab76e9f116100c65780633ab76e9f1461014f57806367090ccf146101865780636c6563f6146101c7578063715018a6146101e757600080fd5b80630652b57a146100ed5780630c6fab821461010f57806319ab453c1461012f575b600080fd5b3480156100f957600080fd5b5061010d610108366004611fa4565b61035d565b005b34801561011b57600080fd5b5061010d61012a366004611fc1565b6103e0565b34801561013b57600080fd5b5061010d61014a366004611fa4565b61068f565b34801561015b57600080fd5b506097546001600160a01b03165b6040516001600160a01b0390911681526020015b60405180910390f35b34801561019257600080fd5b506101696101a1366004612030565b60cb6020908152600092835260408084209091529082529020546001600160a01b031681565b3480156101d357600080fd5b506101696101e236600461206e565b6107a7565b3480156101f357600080fd5b5061010d6107be565b34801561020857600080fd5b5061023c6102173660046120a7565b60cc60205260009081526040902080546001909101546001600160a01b039091169082565b604080516001600160a01b03909316835260208301919091520161017d565b34801561026757600080fd5b506065546001600160a01b0316610169565b34801561028557600080fd5b5061010d6102943660046120c0565b6107d2565b3480156102a557600080fd5b506102b96102b4366004611fa4565b610b54565b60405161017d9594939291906121b0565b3480156102d657600080fd5b506101696102e5366004612201565b610ca5565b3480156102f657600080fd5b5061031a610305366004611fa4565b60c96020526000908152604090205460ff1681565b604051901515815260200161017d565b61010d610338366004612295565b610cbb565b34801561034957600080fd5b5061010d610358366004611fa4565b611574565b6103656115ed565b6001600160a01b03811661038c57604051634d084d8560e11b815260040160405180910390fd5b609780546001600160a01b0319166001600160a01b0383169081179091556040519081527f399ded90cb5ed8d89ef7e76ff4af65c373f06d3bf5d7eef55f4228e7b702a18b9060200160405180910390a150565b6103e8611647565b6562726964676560d01b6103fd816001610ca5565b6001600160a01b0316336001600160a01b03161461042e57604051630d85cccf60e11b815260040160405180910390fd5b6000336001600160a01b031663d0496d6a6040518163ffffffff1660e01b8152600401606060405180830381865afa15801561046e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906104929190612374565b90506104b281604001516a1d1bdad95b97dd985d5b1d60aa1b60006107a7565b6001600160a01b031681602001516001600160a01b0316146104e7576040516320258b8760e21b815260040160405180910390fd5b6000468735036105b4576105016040880160208901611fa4565b905061051c6a3a30b4b5b7afba37b5b2b760a91b6001610ca5565b6001600160a01b0316816001600160a01b03160361059b576040516340c10f1960e01b81526001600160a01b038681166004830152602482018690528216906340c10f1990604401600060405180830381600087803b15801561057e57600080fd5b505af1158015610592573d6000803e3d6000fd5b50505050610624565b6105af6001600160a01b03821686866116a0565b610624565b6105bd87611703565b6040516340c10f1960e01b81526001600160a01b03878116600483015260248201879052919250908216906340c10f1990604401600060405180830381600087803b15801561060b57600080fd5b505af115801561061f573d6000803e3d6000fd5b505050505b815160408084015181519081526001600160a01b0384811660208301529181018790528188169291891691907fe5da926519fc972010fe65b35c1e3339e6dc72b35ffaec203999c2a2a2593eac9060600160405180910390a450505061068960018055565b50505050565b600054610100900460ff16158080156106af5750600054600160ff909116105b806106c95750303b1580156106c9575060005460ff166001145b6107315760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b60648201526084015b60405180910390fd5b6000805460ff191660011790558015610754576000805461ff0019166101001790555b61075d82611762565b80156107a3576000805461ff0019169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b5050565b60006107b484848461177b565b90505b9392505050565b6107c66115ed565b6107d0600061182f565b565b6107da611647565b60006107ec60a0850160808601611fa4565b6001600160a01b031603610813576040516372b41cdf60e01b815260040160405180910390fd5b46836040013514610837576040516348bc100560e01b815260040160405180910390fd5b600061084d6562726964676560d01b6000610ca5565b90506000816001600160a01b0316635817b0c3866040518263ffffffff1660e01b815260040161087d919061244c565b602060405180830381865afa15801561089a573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108be919061256a565b600081815260cc6020526040902080546001909101549192506001600160a01b031690816108ff57604051637c6addb760e01b815260040160405180910390fd5b60405163ce70f39b60e01b81526001600160a01b0385169063ce70f39b9061093590869060608c0135908b908b90600401612583565b602060405180830381865afa158015610952573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061097691906125ad565b610993576040516308ba49e560e31b815260040160405180910390fd5b6040805180820182526000808252602080830182815287835260cc909152929020905181546001600160a01b0319166001600160a01b0390911617815590516001909101558015610adb576001600160a01b038216600090815260c9602052604090205460ff1680610a2e5750610a196a3a30b4b5b7afba37b5b2b760a91b6001610ca5565b6001600160a01b0316826001600160a01b0316145b15610ab7576001600160a01b0382166340c10f19610a5260a08a0160808b01611fa4565b6040516001600160e01b031960e084901b1681526001600160a01b03909116600482015260248101849052604401600060405180830381600087803b158015610a9a57600080fd5b505af1158015610aae573d6000803e3d6000fd5b50505050610adb565b610adb610aca60a0890160808a01611fa4565b6001600160a01b03841690836116a0565b610aeb60a0880160808901611fa4565b6001600160a01b0316837fc5d9f7cd7998e24ecf12ad69eca9339764e2cb13788d5d9616f502601b219af68484604051610b3a9291906001600160a01b03929092168252602082015260400190565b60405180910390a350505050610b4f60018055565b505050565b60ca6020526000908152604090208054600182015460028301805492936001600160a01b03831693600160a01b90930460ff1692909190610b94906125ca565b80601f0160208091040260200160405190810160405280929190818152602001828054610bc0906125ca565b8015610c0d5780601f10610be257610100808354040283529160200191610c0d565b820191906000526020600020905b815481529060010190602001808311610bf057829003601f168201915b505050505090806003018054610c22906125ca565b80601f0160208091040260200160405190810160405280929190818152602001828054610c4e906125ca565b8015610c9b5780601f10610c7057610100808354040283529160200191610c9b565b820191906000526020600020905b815481529060010190602001808311610c7e57829003601f168201915b5050505050905085565b6000610cb246848461177b565b90505b92915050565b610cc3611647565b6001600160a01b0387161580610d035750610cee886a1d1bdad95b97dd985d5b1d60aa1b60006107a7565b6001600160a01b0316876001600160a01b0316145b15610d2157604051634694641b60e01b815260040160405180910390fd5b6001600160a01b038616610d4857604051637c6addb760e01b815260040160405180910390fd5b84600003610d685760405162af849960e11b815260040160405180910390fd5b6040805160a08101825260008082526020820181905291810191909152606080820181905260808201526001600160a01b038716600090815260c9602052604081205460ff1615610faf576001600160a01b03888116600090815260ca6020908152604091829020825160a08101845281548152600182015494851692810192909252600160a01b90930460ff1691810191909152600282018054919291606084019190610e15906125ca565b80601f0160208091040260200160405190810160405280929190818152602001828054610e41906125ca565b8015610e8e5780601f10610e6357610100808354040283529160200191610e8e565b820191906000526020600020905b815481529060010190602001808311610e7157829003601f168201915b50505050508152602001600382018054610ea7906125ca565b80601f0160208091040260200160405190810160405280929190818152602001828054610ed3906125ca565b8015610f205780601f10610ef557610100808354040283529160200191610f20565b820191906000526020600020905b815481529060010190602001808311610f0357829003601f168201915b5050509190925250505060208101519092506001600160a01b0316610f4757610f47612604565b604051632770a7eb60e21b8152336004820152602481018890526001600160a01b03891690639dc29fac90604401600060405180830381600087803b158015610f8f57600080fd5b505af1158015610fa3573d6000803e3d6000fd5b505050508690506112a8565b60008890506040518060a001604052804681526020018a6001600160a01b03168152602001826001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa158015611012573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110369190612629565b60ff168152602001826001600160a01b03166395d89b416040518163ffffffff1660e01b8152600401600060405180830381865afa15801561107c573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526110a49190810190612646565b8152602001826001600160a01b03166306fdde036040518163ffffffff1660e01b8152600401600060405180830381865afa1580156110e7573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405261110f9190810190612646565b9052925061112c6a3a30b4b5b7afba37b5b2b760a91b6001610ca5565b6001600160a01b0316896001600160a01b0316036111ac57604051632770a7eb60e21b8152336004820152602481018990526001600160a01b038a1690639dc29fac90604401600060405180830381600087803b15801561118c57600080fd5b505af11580156111a0573d6000803e3d6000fd5b505050508791506112a6565b6040516370a0823160e01b81523060048201526000906001600160a01b038316906370a0823190602401602060405180830381865afa1580156111f3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611217919061256a565b905061122e6001600160a01b03831633308c611881565b6040516370a0823160e01b815230600482015281906001600160a01b038416906370a0823190602401602060405180830381865afa158015611274573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611298919061256a565b6112a291906126bd565b9250505b505b611337604051806101a001604052806000815260200160006001600160a01b03168152602001600081526020016000815260200160006001600160a01b0316815260200160006001600160a01b0316815260200160006001600160a01b031681526020016000815260200160008152602001600081526020016000815260200160608152602001606081525090565b606081018b905233608082015261135e8b6a1d1bdad95b97dd985d5b1d60aa1b60006107a7565b6001600160a01b031660a08201526080810151604051630637d5c160e11b91611390918691908e9087906024016126de565b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b031990931692909217909152610160820152610140810187905261012081018690526113e286346126bd565b60e08201526001600160a01b03851660c0820152610180810184905260006114136562726964676560d01b82610ca5565b6001600160a01b03166396e1785234846040518363ffffffff1660e01b815260040161143f9190612776565b60206040518083038185885af115801561145d573d6000803e3d6000fd5b50505050506040513d601f19601f82011682018060405250810190611482919061256a565b905060405180604001604052808b6001600160a01b031681526020018481525060cc600083815260200190815260200160002060008201518160000160006101000a8154816001600160a01b0302191690836001600160a01b03160217905550602082015181600101559050508a6001600160a01b031682608001516001600160a01b0316827f325cab7553038374e17f39bb45e2a2c90f66c6a52798cb5f95c20d94c11c95e28f8e88604051611555939291909283526001600160a01b03919091166020830152604082015260600190565b60405180910390a45050505061156a60018055565b5050505050505050565b61157c6115ed565b6001600160a01b0381166115e15760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b6064820152608401610728565b6115ea8161182f565b50565b6065546001600160a01b031633146107d05760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610728565b6002600154036116995760405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c006044820152606401610728565b6002600155565b6040516001600160a01b038316602482015260448101829052610b4f90849063a9059cbb60e01b906064015b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b0319909316929092179091526118b9565b8035600090815260cb6020908152604080832083929091839161172a918701908701611fa4565b6001600160a01b03908116825260208201929092526040016000205416905080610cb5576117578361198b565b6107b7565b60018055565b61176a611be6565b611772611c15565b6115ea81611c44565b60975460405163195ac1a960e21b815260048101859052602481018490526000916001600160a01b03169063656b06a490604401602060405180830381865afa1580156117cc573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117f09190612866565b90508115801561180757506001600160a01b038116155b156107b757604051631467050360e21b81526004810185905260248101849052604401610728565b606580546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b6040516001600160a01b03808516602483015283166044820152606481018290526106899085906323b872dd60e01b906084016116cc565b600061190e826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b0316611c8d9092919063ffffffff16565b805190915015610b4f578080602001905181019061192c91906125ad565b610b4f5760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6044820152691bdd081cdd58d8d9595960b21b6064820152608401610728565b6000611a048183356119a36040860160208701611fa4565b6040516119c692916001600160a01b031690602001918252602082015260400190565b60405160208183030381529060405280519060200120604051806020016119ec90611f72565b601f1982820381018352601f90910116604052611c9c565b6097549091506001600160a01b0380831691636c0db62b9116611a2d6040860160208701611fa4565b8535611a3f6060880160408901612883565b611a4c60608901896128a0565b611a5960808b018b6128a0565b6040518963ffffffff1660e01b8152600401611a7c9897969594939291906128e7565b600060405180830381600087803b158015611a9657600080fd5b505af1158015611aaa573d6000803e3d6000fd5b5050506001600160a01b038216600090815260c960209081526040808320805460ff1916600117905560ca9091529020839150611ae78282612a55565b50508135600090815260cb60209081526040808320849390929091611b1191908701908701611fa4565b6001600160a01b03166001600160a01b0316815260200190815260200160002060006101000a8154816001600160a01b0302191690836001600160a01b03160217905550806001600160a01b0316826020016020810190611b729190611fa4565b6001600160a01b031683357f9e465b29e576a3e01584e31d607353f21b80c055e813af907c0a495f6cf4f7bc611bab60608701876128a0565b611bb860808901896128a0565b611bc860608b0160408c01612883565b604051611bd9959493929190612adc565b60405180910390a4919050565b600054610100900460ff16611c0d5760405162461bcd60e51b815260040161072890612b19565b6107d0611da0565b600054610100900460ff16611c3c5760405162461bcd60e51b815260040161072890612b19565b6107d0611dc7565b6001600160a01b038116611c6b57604051634d084d8560e11b815260040160405180910390fd5b609780546001600160a01b0319166001600160a01b0392909216919091179055565b60606107b48484600085611df7565b600083471015611cee5760405162461bcd60e51b815260206004820152601d60248201527f437265617465323a20696e73756666696369656e742062616c616e63650000006044820152606401610728565b8151600003611d3f5760405162461bcd60e51b815260206004820181905260248201527f437265617465323a2062797465636f6465206c656e677468206973207a65726f6044820152606401610728565b8282516020840186f590506001600160a01b0381166107b75760405162461bcd60e51b815260206004820152601960248201527f437265617465323a204661696c6564206f6e206465706c6f79000000000000006044820152606401610728565b600054610100900460ff1661175c5760405162461bcd60e51b815260040161072890612b19565b600054610100900460ff16611dee5760405162461bcd60e51b815260040161072890612b19565b6107d03361182f565b606082471015611e585760405162461bcd60e51b815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f6044820152651c8818d85b1b60d21b6064820152608401610728565b600080866001600160a01b03168587604051611e749190612b64565b60006040518083038185875af1925050503d8060008114611eb1576040519150601f19603f3d011682016040523d82523d6000602084013e611eb6565b606091505b5091509150611ec787838387611ed4565b925050505b949350505050565b60608315611f43578251600003611f3c576001600160a01b0385163b611f3c5760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610728565b5081611ecc565b611ecc8383815115611f585781518083602001fd5b8060405162461bcd60e51b81526004016107289190612b80565b61199080612b9483390190565b6001600160a01b03811681146115ea57600080fd5b8035611f9f81611f7f565b919050565b600060208284031215611fb657600080fd5b81356107b781611f7f565b60008060008060808587031215611fd757600080fd5b843567ffffffffffffffff811115611fee57600080fd5b850160a0818803121561200057600080fd5b9350602085013561201081611f7f565b9250604085013561202081611f7f565b9396929550929360600135925050565b6000806040838503121561204357600080fd5b82359150602083013561205581611f7f565b809150509250929050565b80151581146115ea57600080fd5b60008060006060848603121561208357600080fd5b8335925060208401359150604084013561209c81612060565b809150509250925092565b6000602082840312156120b957600080fd5b5035919050565b6000806000604084860312156120d557600080fd5b833567ffffffffffffffff808211156120ed57600080fd5b908501906101a0828803121561210257600080fd5b9093506020850135908082111561211857600080fd5b818601915086601f83011261212c57600080fd5b81358181111561213b57600080fd5b87602082850101111561214d57600080fd5b6020830194508093505050509250925092565b60005b8381101561217b578181015183820152602001612163565b50506000910152565b6000815180845261219c816020860160208601612160565b601f01601f19169290920160200192915050565b8581526001600160a01b038516602082015260ff8416604082015260a0606082018190526000906121e390830185612184565b82810360808401526121f58185612184565b98975050505050505050565b6000806040838503121561221457600080fd5b82359150602083013561205581612060565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f1916810167ffffffffffffffff8111828210171561226557612265612226565b604052919050565b600067ffffffffffffffff82111561228757612287612226565b50601f01601f191660200190565b600080600080600080600080610100898b0312156122b257600080fd5b8835975060208901356122c481611f7f565b965060408901356122d481611f7f565b9550606089013594506080890135935060a0890135925060c08901356122f981611f7f565b915060e089013567ffffffffffffffff81111561231557600080fd5b8901601f81018b1361232657600080fd5b80356123396123348261226d565b61223c565b8181528c602083850101111561234e57600080fd5b816020840160208301376000602083830101528093505050509295985092959890939650565b60006060828403121561238657600080fd5b6040516060810181811067ffffffffffffffff821117156123a9576123a9612226565b6040528251815260208301516123be81611f7f565b60208201526040928301519281019290925250919050565b6000808335601e198436030181126123ed57600080fd5b830160208101925035905067ffffffffffffffff81111561240d57600080fd5b80360382131561241c57600080fd5b9250929050565b81835281816020850137506000828201602090810191909152601f909101601f19169091010190565b6020815281356020820152600061246560208401611f94565b6001600160a01b038116604084015250604083013560608301526060830135608083015261249560808401611f94565b6001600160a01b03811660a0840152506124b160a08401611f94565b6001600160a01b03811660c0840152506124cd60c08401611f94565b6001600160a01b03811660e08401525061010060e084013581840152610120818501358185015261014091508085013582850152506101608185013581850152612519818601866123d6565b925090506101a061018081818701526125376101c087018585612423565b9350612545818801886123d6565b878603601f1901848901529350905061255f848483612423565b979650505050505050565b60006020828403121561257c57600080fd5b5051919050565b8481528360208201526060604082015260006125a3606083018486612423565b9695505050505050565b6000602082840312156125bf57600080fd5b81516107b781612060565b600181811c908216806125de57607f821691505b6020821081036125fe57634e487b7160e01b600052602260045260246000fd5b50919050565b634e487b7160e01b600052600160045260246000fd5b60ff811681146115ea57600080fd5b60006020828403121561263b57600080fd5b81516107b78161261a565b60006020828403121561265857600080fd5b815167ffffffffffffffff81111561266f57600080fd5b8201601f8101841361268057600080fd5b805161268e6123348261226d565b8181528560208385010111156126a357600080fd5b6126b4826020830160208601612160565b95945050505050565b81810381811115610cb557634e487b7160e01b600052601160045260246000fd5b60808152845160808201526000602086015160018060a01b0380821660a085015260ff60408901511660c08501526060880151915060a060e0850152612728610120850183612184565b91506080880151607f19858403016101008601526127468382612184565b9188166020860152506001600160a01b038616604085015291506127679050565b82606083015295945050505050565b60208152815160208201526000602083015161279d60408401826001600160a01b03169052565b50604083015160608301526060830151608083015260808301516127cc60a08401826001600160a01b03169052565b5060a08301516001600160a01b03811660c08401525060c08301516001600160a01b03811660e08401525060e0830151610100838101919091528301516101208084019190915283015161014080840191909152830151610160808401919091528301516101a061018080850182905261284a6101c0860184612184565b90860151858203601f1901838701529092506125a38382612184565b60006020828403121561287857600080fd5b81516107b781611f7f565b60006020828403121561289557600080fd5b81356107b78161261a565b6000808335601e198436030181126128b757600080fd5b83018035915067ffffffffffffffff8211156128d257600080fd5b60200191503681900382131561241c57600080fd5b6001600160a01b038981168252881660208201526040810187905260ff8616606082015260c0608082018190526000906129249083018688612423565b82810360a0840152612937818587612423565b9b9a5050505050505050505050565b601f821115610b4f57600081815260208120601f850160051c8101602086101561296d5750805b601f850160051c820191505b8181101561298c57828155600101612979565b505050505050565b67ffffffffffffffff8311156129ac576129ac612226565b6129c0836129ba83546125ca565b83612946565b6000601f8411600181146129f457600085156129dc5750838201355b600019600387901b1c1916600186901b178355612a4e565b600083815260209020601f19861690835b82811015612a255786850135825560209485019460019092019101612a05565b5086821015612a425760001960f88860031b161c19848701351681555b505060018560011b0183555b5050505050565b81358155600181016020830135612a6b81611f7f565b81546040850135612a7b8161261a565b60ff60a01b60a09190911b166001600160a01b03929092166001600160a81b03199190911617179055612ab160608301836128a0565b612abf818360028601612994565b5050612ace60808301836128a0565b610689818360038601612994565b606081526000612af0606083018789612423565b8281036020840152612b03818688612423565b91505060ff831660408301529695505050505050565b6020808252602b908201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960408201526a6e697469616c697a696e6760a81b606082015260800190565b60008251612b76818460208701612160565b9190910192915050565b602081526000610cb2602083018461218456fe608060405234801561001057600080fd5b50611970806100206000396000f3fe608060405234801561001057600080fd5b50600436106101585760003560e01c80636c6563f6116100c35780639dc29fac1161007c5780639dc29fac146102fa578063a457c2d71461030d578063a86f9d9e14610320578063a9059cbb14610333578063dd62ed3e14610346578063f2fde38b1461035957600080fd5b80636c6563f61461028a57806370a082311461029d578063715018a6146102c65780637cf8ed0d146102ce5780638da5cb5b146102e157806395d89b41146102f257600080fd5b8063313ce56711610115578063313ce5671461020e57806339509351146102235780633ab76e9f1461023657806340c10f191461025b57806349d126051461026e5780636c0db62b1461027757600080fd5b80630652b57a1461015d57806306fdde0314610172578063095ea7b31461019057806318160ddd146101b357806323b872dd146101c557806326afaadd146101d8575b600080fd5b61017061016b36600461144e565b61036c565b005b61017a6103ef565b604051610187919061148f565b60405180910390f35b6101a361019e3660046114c2565b610429565b6040519015158152602001610187565b60cb545b604051908152602001610187565b6101a36101d33660046114ee565b610443565b6101ef60fb5460fc546001600160a01b0390911691565b604080516001600160a01b039093168352602083019190915201610187565b60fd5460405160ff9091168152602001610187565b6101a36102313660046114c2565b610483565b6097546001600160a01b03165b6040516001600160a01b039091168152602001610187565b6101706102693660046114c2565b6104a5565b6101b760fc5481565b6101706102853660046115d2565b6105ae565b610243610298366004611691565b610754565b6101b76102ab36600461144e565b6001600160a01b0316600090815260c9602052604090205490565b610170610761565b60fb54610243906001600160a01b031681565b6065546001600160a01b0316610243565b61017a610775565b6101706103083660046114c2565b610807565b6101a361031b3660046114c2565b610901565b61024361032e3660046116c6565b610987565b6101a36103413660046114c2565b610994565b6101b76103543660046116f2565b6109c9565b61017061036736600461144e565b6109f4565b610374610a6d565b6001600160a01b03811661039b57604051634d084d8560e11b815260040160405180910390fd5b609780546001600160a01b0319166001600160a01b0383169081179091556040519081527f399ded90cb5ed8d89ef7e76ff4af65c373f06d3bf5d7eef55f4228e7b702a18b9060200160405180910390a150565b60606103f9610ac7565b61040460fc54610ad6565b60405160200161041592919061172b565b604051602081830303815290604052905090565b600033610437818585610b69565b60019150505b92915050565b6000306001600160a01b0384160361046e576040516319a6f37760e21b815260040160405180910390fd5b610479848484610c8e565b90505b9392505050565b60003361043781858561049683836109c9565b6104a09190611769565b610b69565b647461696b6f60d81b6a1c1c9bdd995c97dc1bdbdb60aa1b6a1d1bdad95b97dd985d5b1d60aa1b6104d7836001610987565b6001600160a01b0316336001600160a01b03161415801561051457506104fe826001610987565b6001600160a01b0316336001600160a01b031614155b801561053c5750610526816001610987565b6001600160a01b0316336001600160a01b031614155b1561055a57604051630d85cccf60e11b815260040160405180910390fd5b6105648585610ca7565b846001600160a01b03167f0f6798a560793a54c3bcfe86a93cde1e73087d944c0ea20544137d41213968858560405161059f91815260200190565b60405180910390a25050505050565b600054610100900460ff16158080156105ce5750600054600160ff909116105b806105e85750303b1580156105e8575060005460ff166001145b6106505760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b60648201526084015b60405180910390fd5b6000805460ff191660011790558015610673576000805461ff0019166101001790555b6001600160a01b0386161580610687575084155b8061069157504685145b8061069b57508251155b806106a557508151155b156106c3576040516301e25ab360e71b815260040160405180910390fd5b6106cc87610d69565b6106d68284610d82565b60fb80546001600160a01b0319166001600160a01b03881617905560fc85905560fd805460ff191660ff8616179055801561074b576000805461ff0019169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b50505050505050565b6000610479848484610db3565b610769610a6d565b6107736000610e67565b565b606060cd80546107849061178a565b80601f01602080910402602001604051908101604052809291908181526020018280546107b09061178a565b80156107fd5780601f106107d2576101008083540402835291602001916107fd565b820191906000526020600020905b8154815290600101906020018083116107e057829003601f168201915b5050505050905090565b647461696b6f60d81b6a1c1c9bdd995c97dc1bdbdb60aa1b6a1d1bdad95b97dd985d5b1d60aa1b610839836001610987565b6001600160a01b0316336001600160a01b0316141580156108765750610860826001610987565b6001600160a01b0316336001600160a01b031614155b801561089e5750610888816001610987565b6001600160a01b0316336001600160a01b031614155b156108bc57604051630d85cccf60e11b815260040160405180910390fd5b6108c68585610eb9565b846001600160a01b03167fcc16f5dbb4873280815c1ee09dbd06736cffcc184412cf7a71a0fdb75d397ca58560405161059f91815260200190565b6000338161090f82866109c9565b90508381101561096f5760405162461bcd60e51b815260206004820152602560248201527f45524332303a2064656372656173656420616c6c6f77616e63652062656c6f77604482015264207a65726f60d81b6064820152608401610647565b61097c8286868403610b69565b506001949350505050565b600061047c468484610db3565b6000306001600160a01b038416036109bf576040516319a6f37760e21b815260040160405180910390fd5b61047c8383610fea565b6001600160a01b03918216600090815260ca6020908152604080832093909416825291909152205490565b6109fc610a6d565b6001600160a01b038116610a615760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b6064820152608401610647565b610a6a81610e67565b50565b6065546001600160a01b031633146107735760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610647565b606060cc80546107849061178a565b60606000610ae383610ff8565b600101905060008167ffffffffffffffff811115610b0357610b0361152f565b6040519080825280601f01601f191660200182016040528015610b2d576020820181803683370190505b5090508181016020015b600019016f181899199a1a9b1b9c1cb0b131b232b360811b600a86061a8153600a8504945084610b3757509392505050565b6001600160a01b038316610bcb5760405162461bcd60e51b8152602060048201526024808201527f45524332303a20617070726f76652066726f6d20746865207a65726f206164646044820152637265737360e01b6064820152608401610647565b6001600160a01b038216610c2c5760405162461bcd60e51b815260206004820152602260248201527f45524332303a20617070726f766520746f20746865207a65726f206164647265604482015261737360f01b6064820152608401610647565b6001600160a01b03838116600081815260ca602090815260408083209487168084529482529182902085905590518481527f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92591015b60405180910390a3505050565b600033610c9c8582856110d0565b61097c85858561114a565b6001600160a01b038216610cfd5760405162461bcd60e51b815260206004820152601f60248201527f45524332303a206d696e7420746f20746865207a65726f2061646472657373006044820152606401610647565b8060cb6000828254610d0f9190611769565b90915550506001600160a01b038216600081815260c960209081526040808320805486019055518481527fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef910160405180910390a35b5050565b610d716112f5565b610d79611324565b610a6a81611353565b600054610100900460ff16610da95760405162461bcd60e51b8152600401610647906117c4565b610d65828261139c565b60975460405163195ac1a960e21b815260048101859052602481018490526000916001600160a01b03169063656b06a490604401602060405180830381865afa158015610e04573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e28919061180f565b905081158015610e3f57506001600160a01b038116155b1561047c57604051631467050360e21b81526004810185905260248101849052604401610647565b606580546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b6001600160a01b038216610f195760405162461bcd60e51b815260206004820152602160248201527f45524332303a206275726e2066726f6d20746865207a65726f206164647265736044820152607360f81b6064820152608401610647565b6001600160a01b038216600090815260c9602052604090205481811015610f8d5760405162461bcd60e51b815260206004820152602260248201527f45524332303a206275726e20616d6f756e7420657863656564732062616c616e604482015261636560f01b6064820152608401610647565b6001600160a01b038316600081815260c960209081526040808320868603905560cb80548790039055518581529192917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9101610c81565b505050565b60003361043781858561114a565b60008072184f03e93ff9f4daa797ed6e38ed64bf6a1f0160401b83106110375772184f03e93ff9f4daa797ed6e38ed64bf6a1f0160401b830492506040015b6d04ee2d6d415b85acef81000000008310611063576d04ee2d6d415b85acef8100000000830492506020015b662386f26fc10000831061108157662386f26fc10000830492506010015b6305f5e1008310611099576305f5e100830492506008015b61271083106110ad57612710830492506004015b606483106110bf576064830492506002015b600a831061043d5760010192915050565b60006110dc84846109c9565b9050600019811461114457818110156111375760405162461bcd60e51b815260206004820152601d60248201527f45524332303a20696e73756666696369656e7420616c6c6f77616e63650000006044820152606401610647565b6111448484848403610b69565b50505050565b6001600160a01b0383166111ae5760405162461bcd60e51b815260206004820152602560248201527f45524332303a207472616e736665722066726f6d20746865207a65726f206164604482015264647265737360d81b6064820152608401610647565b6001600160a01b0382166112105760405162461bcd60e51b815260206004820152602360248201527f45524332303a207472616e7366657220746f20746865207a65726f206164647260448201526265737360e81b6064820152608401610647565b6001600160a01b038316600090815260c96020526040902054818110156112885760405162461bcd60e51b815260206004820152602660248201527f45524332303a207472616e7366657220616d6f756e7420657863656564732062604482015265616c616e636560d01b6064820152608401610647565b6001600160a01b03808516600081815260c9602052604080822086860390559286168082529083902080548601905591517fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef906112e89086815260200190565b60405180910390a3611144565b600054610100900460ff1661131c5760405162461bcd60e51b8152600401610647906117c4565b6107736113dc565b600054610100900460ff1661134b5760405162461bcd60e51b8152600401610647906117c4565b610773611409565b6001600160a01b03811661137a57604051634d084d8560e11b815260040160405180910390fd5b609780546001600160a01b0319166001600160a01b0392909216919091179055565b600054610100900460ff166113c35760405162461bcd60e51b8152600401610647906117c4565b60cc6113cf838261187a565b5060cd610fe5828261187a565b600054610100900460ff166114035760405162461bcd60e51b8152600401610647906117c4565b60018055565b600054610100900460ff166114305760405162461bcd60e51b8152600401610647906117c4565b61077333610e67565b6001600160a01b0381168114610a6a57600080fd5b60006020828403121561146057600080fd5b813561047c81611439565b60005b8381101561148657818101518382015260200161146e565b50506000910152565b60208152600082518060208401526114ae81604085016020870161146b565b601f01601f19169190910160400192915050565b600080604083850312156114d557600080fd5b82356114e081611439565b946020939093013593505050565b60008060006060848603121561150357600080fd5b833561150e81611439565b9250602084013561151e81611439565b929592945050506040919091013590565b634e487b7160e01b600052604160045260246000fd5b600082601f83011261155657600080fd5b813567ffffffffffffffff808211156115715761157161152f565b604051601f8301601f19908116603f011681019082821181831017156115995761159961152f565b816040528381528660208588010111156115b257600080fd5b836020870160208301376000602085830101528094505050505092915050565b60008060008060008060c087890312156115eb57600080fd5b86356115f681611439565b9550602087013561160681611439565b945060408701359350606087013560ff8116811461162357600080fd5b9250608087013567ffffffffffffffff8082111561164057600080fd5b61164c8a838b01611545565b935060a089013591508082111561166257600080fd5b5061166f89828a01611545565b9150509295509295509295565b8035801515811461168c57600080fd5b919050565b6000806000606084860312156116a657600080fd5b83359250602084013591506116bd6040850161167c565b90509250925092565b600080604083850312156116d957600080fd5b823591506116e96020840161167c565b90509250929050565b6000806040838503121561170557600080fd5b823561171081611439565b9150602083013561172081611439565b809150509250929050565b6000835161173d81846020880161146b565b6241c55b60e71b908301908152835161175d81600484016020880161146b565b01600401949350505050565b8082018082111561043d57634e487b7160e01b600052601160045260246000fd5b600181811c9082168061179e57607f821691505b6020821081036117be57634e487b7160e01b600052602260045260246000fd5b50919050565b6020808252602b908201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960408201526a6e697469616c697a696e6760a81b606082015260800190565b60006020828403121561182157600080fd5b815161047c81611439565b601f821115610fe557600081815260208120601f850160051c810160208610156118535750805b601f850160051c820191505b818110156118725782815560010161185f565b505050505050565b815167ffffffffffffffff8111156118945761189461152f565b6118a8816118a2845461178a565b8461182c565b602080601f8311600181146118dd57600084156118c55750858301515b600019600386901b1c1916600185901b178555611872565b600085815260208120601f198616915b8281101561190c578886015182559484019460019091019084016118ed565b508582101561192a5787850151600019600388901b60f8161c191681555b5050505050600190811b0190555056fea2646970667358221220b40c6ab2d2ac6f02bd81640104801f3a38058209c3426b02583ae83cd4f9626164736f6c63430008140033a264697066735822122051da8881de7c8127cafb93733e67495f9cf4eb99b2d5f043b163acb59a7c9c5c64736f6c63430008140033", + "balance": "0x0" + }, + "0x1000777700000000000000000000000000000002": { + "contractName": "TokenVaultProxy", + "storage": { + "0x0000000000000000000000000000000000000000000000000000000000000000": "0x0000000000000000000000000000000000000000000000000000000000000001", + "0x0000000000000000000000000000000000000000000000000000000000000001": "0x0000000000000000000000000000000000000000000000000000000000000001", + "0x0000000000000000000000000000000000000000000000000000000000000065": "0x00000000000000000000000019b4f9c381c7927fe33d853e48b560141a380c44", + "0x0000000000000000000000000000000000000000000000000000000000000097": "0x0000000000000000000000001000777700000000000000000000000000000006", + "0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103": "0x113cE23c9e0cc50F4D41d7cE6DA02dCAFf8BFF85", + "0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc": "0x0000777700000000000000000000000000000002" + }, + "code": "0x60806040526004361061004e5760003560e01c80633659cfe6146100655780634f1ef286146100855780635c60da1b146100985780638f283970146100c9578063f851a440146100e95761005d565b3661005d5761005b6100fe565b005b61005b6100fe565b34801561007157600080fd5b5061005b6100803660046106b3565b610118565b61005b6100933660046106ce565b610155565b3480156100a457600080fd5b506100ad6101bc565b6040516001600160a01b03909116815260200160405180910390f35b3480156100d557600080fd5b5061005b6100e43660046106b3565b6101ed565b3480156100f557600080fd5b506100ad61020d565b61010661022e565b6101166101116102c3565b6102cd565b565b6101206102f1565b6001600160a01b0316330361014d5761014a81604051806020016040528060008152506000610324565b50565b61014a6100fe565b61015d6102f1565b6001600160a01b031633036101b4576101af8383838080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525060019250610324915050565b505050565b6101af6100fe565b60006101c66102f1565b6001600160a01b031633036101e2576101dd6102c3565b905090565b6101ea6100fe565b90565b6101f56102f1565b6001600160a01b0316330361014d5761014a8161034f565b60006102176102f1565b6001600160a01b031633036101e2576101dd6102f1565b6102366102f1565b6001600160a01b031633036101165760405162461bcd60e51b815260206004820152604260248201527f5472616e73706172656e745570677261646561626c6550726f78793a2061646d60448201527f696e2063616e6e6f742066616c6c6261636b20746f2070726f78792074617267606482015261195d60f21b608482015260a4015b60405180910390fd5b60006101dd6103a3565b3660008037600080366000845af43d6000803e8080156102ec573d6000f35b3d6000fd5b60007fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035b546001600160a01b0316919050565b61032d836103cb565b60008251118061033a5750805b156101af57610349838361040b565b50505050565b7f7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f6103786102f1565b604080516001600160a01b03928316815291841660208301520160405180910390a161014a81610437565b60007f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc610315565b6103d4816104e0565b6040516001600160a01b038216907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b90600090a250565b606061043083836040518060600160405280602781526020016107c560279139610574565b9392505050565b6001600160a01b03811661049c5760405162461bcd60e51b815260206004820152602660248201527f455243313936373a206e65772061646d696e20697320746865207a65726f206160448201526564647265737360d01b60648201526084016102ba565b807fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035b80546001600160a01b0319166001600160a01b039290921691909117905550565b6001600160a01b0381163b61054d5760405162461bcd60e51b815260206004820152602d60248201527f455243313936373a206e657720696d706c656d656e746174696f6e206973206e60448201526c1bdd08184818dbdb9d1c9858dd609a1b60648201526084016102ba565b807f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc6104bf565b6060600080856001600160a01b0316856040516105919190610775565b600060405180830381855af49150503d80600081146105cc576040519150601f19603f3d011682016040523d82523d6000602084013e6105d1565b606091505b50915091506105e2868383876105ec565b9695505050505050565b6060831561065b578251600003610654576001600160a01b0385163b6106545760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e747261637400000060448201526064016102ba565b5081610665565b610665838361066d565b949350505050565b81511561067d5781518083602001fd5b8060405162461bcd60e51b81526004016102ba9190610791565b80356001600160a01b03811681146106ae57600080fd5b919050565b6000602082840312156106c557600080fd5b61043082610697565b6000806000604084860312156106e357600080fd5b6106ec84610697565b9250602084013567ffffffffffffffff8082111561070957600080fd5b818601915086601f83011261071d57600080fd5b81358181111561072c57600080fd5b87602082850101111561073e57600080fd5b6020830194508093505050509250925092565b60005b8381101561076c578181015183820152602001610754565b50506000910152565b60008251610787818460208701610751565b9190910192915050565b60208152600082518060208401526107b0816040850160208701610751565b601f01601f1916919091016040019291505056fe416464726573733a206c6f772d6c6576656c2064656c65676174652063616c6c206661696c6564a2646970667358221220caef1c2a647344b8936c2def885861b955c9b56ccb762c5243ac8ec49af2096f64736f6c63430008140033", + "balance": "0x0" + }, + "0x0000777700000000000000000000000000000003": { + "contractName": "ProxiedEtherVault", + "storage": {}, + "code": "0x6080604052600436106100ab5760003560e01c80638da5cb5b116100645780638da5cb5b146101c0578063a86f9d9e146101de578063ba0bbd95146101fe578063d73bb3d01461021e578063f2fde38b1461023e578063fe9fbb801461025e57600080fd5b80630652b57a146100f457806319ab453c146101145780632d1fb389146101345780633ab76e9f146101545780636c6563f61461018b578063715018a6146101ab57600080fd5b366100ef5747158015906100cf575033600090815260c9602052604090205460ff16155b156100ed57604051634fa3f24560e01b815260040160405180910390fd5b005b600080fd5b34801561010057600080fd5b506100ed61010f366004610a90565b6102a7565b34801561012057600080fd5b506100ed61012f366004610a90565b61032a565b34801561014057600080fd5b506100ed61014f366004610ac2565b610442565b34801561016057600080fd5b506097546001600160a01b03165b6040516001600160a01b0390911681526020015b60405180910390f35b34801561019757600080fd5b5061016e6101a6366004610af7565b6104fb565b3480156101b757600080fd5b506100ed610512565b3480156101cc57600080fd5b506065546001600160a01b031661016e565b3480156101ea57600080fd5b5061016e6101f9366004610b2c565b610526565b34801561020a57600080fd5b506100ed610219366004610b4f565b610533565b34801561022a57600080fd5b506100ed610239366004610b7b565b6105f1565b34801561024a57600080fd5b506100ed610259366004610a90565b610674565b34801561026a57600080fd5b50610297610279366004610a90565b6001600160a01b0316600090815260c9602052604090205460ff1690565b6040519015158152602001610182565b6102af6106ea565b6001600160a01b0381166102d657604051634d084d8560e11b815260040160405180910390fd5b609780546001600160a01b0319166001600160a01b0383169081179091556040519081527f399ded90cb5ed8d89ef7e76ff4af65c373f06d3bf5d7eef55f4228e7b702a18b9060200160405180910390a150565b600054610100900460ff161580801561034a5750600054600160ff909116105b806103645750303b158015610364575060005460ff166001145b6103cc5760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b60648201526084015b60405180910390fd5b6000805460ff1916600117905580156103ef576000805461ff0019166101001790555b6103f882610744565b801561043e576000805461ff0019169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b5050565b61044a6106ea565b6001600160a01b038216158061047e57506001600160a01b038216600090815260c9602052604090205460ff161515811515145b1561049c57604051631bebdfa760e21b815260040160405180910390fd5b6001600160a01b038216600081815260c96020908152604091829020805460ff191685151590811790915591519182527f4c0079b9bcd37cd5d29a13938effd97c881798cbc6bd52a3026a29d94b27d1bf910160405180910390a25050565b600061050884848461075d565b90505b9392505050565b61051a6106ea565b6105246000610811565b565b600061050b46848461075d565b33600090815260c9602052604090205460ff1661056357604051634fa3f24560e01b815260040160405180910390fd5b61056b610863565b6001600160a01b0382166105925760405163687563df60e01b815260040160405180910390fd5b6105a56001600160a01b038316826108bc565b816001600160a01b03167f7b9f77d35803cd201eac9c4ed739bc1fcd3f1be6ab8877d925d1e55517b6fd6e826040516105e091815260200190565b60405180910390a261043e60018055565b33600090815260c9602052604090205460ff1661062157604051634fa3f24560e01b815260040160405180910390fd5b610629610863565b61063333826108bc565b60405181815233907f7b9f77d35803cd201eac9c4ed739bc1fcd3f1be6ab8877d925d1e55517b6fd6e9060200160405180910390a261067160018055565b50565b61067c6106ea565b6001600160a01b0381166106e15760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b60648201526084016103c3565b61067181610811565b6065546001600160a01b031633146105245760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657260448201526064016103c3565b61074c61097d565b6107546109ac565b610671816109db565b60975460405163195ac1a960e21b815260048101859052602481018490526000916001600160a01b03169063656b06a490604401602060405180830381865afa1580156107ae573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906107d29190610b94565b9050811580156107e957506001600160a01b038116155b1561050b57604051631467050360e21b815260048101859052602481018490526044016103c3565b606580546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b6002600154036108b55760405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c0060448201526064016103c3565b6002600155565b8015806108d057506001600160a01b038216155b156108d9575050565b6000826001600160a01b03168260405160006040518083038185875af1925050503d8060008114610926576040519150601f19603f3d011682016040523d82523d6000602084013e61092b565b606091505b50509050806109725760405162461bcd60e51b8152602060048201526013602482015272115512081d1c985b9cd9995c8819985a5b1959606a1b60448201526064016103c3565b505050565b60018055565b600054610100900460ff166109a45760405162461bcd60e51b81526004016103c390610bb1565b610524610a24565b600054610100900460ff166109d35760405162461bcd60e51b81526004016103c390610bb1565b610524610a4b565b6001600160a01b038116610a0257604051634d084d8560e11b815260040160405180910390fd5b609780546001600160a01b0319166001600160a01b0392909216919091179055565b600054610100900460ff166109775760405162461bcd60e51b81526004016103c390610bb1565b600054610100900460ff16610a725760405162461bcd60e51b81526004016103c390610bb1565b61052433610811565b6001600160a01b038116811461067157600080fd5b600060208284031215610aa257600080fd5b813561050b81610a7b565b80358015158114610abd57600080fd5b919050565b60008060408385031215610ad557600080fd5b8235610ae081610a7b565b9150610aee60208401610aad565b90509250929050565b600080600060608486031215610b0c57600080fd5b8335925060208401359150610b2360408501610aad565b90509250925092565b60008060408385031215610b3f57600080fd5b82359150610aee60208401610aad565b60008060408385031215610b6257600080fd5b8235610b6d81610a7b565b946020939093013593505050565b600060208284031215610b8d57600080fd5b5035919050565b600060208284031215610ba657600080fd5b815161050b81610a7b565b6020808252602b908201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960408201526a6e697469616c697a696e6760a81b60608201526080019056fea2646970667358221220d1f620816e429aef5462d90b937779e4a09a43cf61a7434dba633ff2bfa8098364736f6c63430008140033", + "balance": "0x0" + }, + "0x1000777700000000000000000000000000000003": { + "contractName": "EtherVaultProxy", + "storage": { + "0x0000000000000000000000000000000000000000000000000000000000000000": "0x0000000000000000000000000000000000000000000000000000000000000001", + "0x0000000000000000000000000000000000000000000000000000000000000001": "0x0000000000000000000000000000000000000000000000000000000000000001", + "0x0000000000000000000000000000000000000000000000000000000000000065": "0x00000000000000000000000019b4f9c381c7927fe33d853e48b560141a380c44", + "0x0000000000000000000000000000000000000000000000000000000000000097": "0x0000000000000000000000001000777700000000000000000000000000000006", + "0xa738d3397c1eb96f671d7e4bd29cabbfa1a9c9ebc0db4142aee17809c43ab720": "0x0000000000000000000000000000000000000000000000000000000000000001", + "0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103": "0x113cE23c9e0cc50F4D41d7cE6DA02dCAFf8BFF85", + "0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc": "0x0000777700000000000000000000000000000003" + }, + "code": "0x60806040526004361061004e5760003560e01c80633659cfe6146100655780634f1ef286146100855780635c60da1b146100985780638f283970146100c9578063f851a440146100e95761005d565b3661005d5761005b6100fe565b005b61005b6100fe565b34801561007157600080fd5b5061005b6100803660046106b3565b610118565b61005b6100933660046106ce565b610155565b3480156100a457600080fd5b506100ad6101bc565b6040516001600160a01b03909116815260200160405180910390f35b3480156100d557600080fd5b5061005b6100e43660046106b3565b6101ed565b3480156100f557600080fd5b506100ad61020d565b61010661022e565b6101166101116102c3565b6102cd565b565b6101206102f1565b6001600160a01b0316330361014d5761014a81604051806020016040528060008152506000610324565b50565b61014a6100fe565b61015d6102f1565b6001600160a01b031633036101b4576101af8383838080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525060019250610324915050565b505050565b6101af6100fe565b60006101c66102f1565b6001600160a01b031633036101e2576101dd6102c3565b905090565b6101ea6100fe565b90565b6101f56102f1565b6001600160a01b0316330361014d5761014a8161034f565b60006102176102f1565b6001600160a01b031633036101e2576101dd6102f1565b6102366102f1565b6001600160a01b031633036101165760405162461bcd60e51b815260206004820152604260248201527f5472616e73706172656e745570677261646561626c6550726f78793a2061646d60448201527f696e2063616e6e6f742066616c6c6261636b20746f2070726f78792074617267606482015261195d60f21b608482015260a4015b60405180910390fd5b60006101dd6103a3565b3660008037600080366000845af43d6000803e8080156102ec573d6000f35b3d6000fd5b60007fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035b546001600160a01b0316919050565b61032d836103cb565b60008251118061033a5750805b156101af57610349838361040b565b50505050565b7f7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f6103786102f1565b604080516001600160a01b03928316815291841660208301520160405180910390a161014a81610437565b60007f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc610315565b6103d4816104e0565b6040516001600160a01b038216907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b90600090a250565b606061043083836040518060600160405280602781526020016107c560279139610574565b9392505050565b6001600160a01b03811661049c5760405162461bcd60e51b815260206004820152602660248201527f455243313936373a206e65772061646d696e20697320746865207a65726f206160448201526564647265737360d01b60648201526084016102ba565b807fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035b80546001600160a01b0319166001600160a01b039290921691909117905550565b6001600160a01b0381163b61054d5760405162461bcd60e51b815260206004820152602d60248201527f455243313936373a206e657720696d706c656d656e746174696f6e206973206e60448201526c1bdd08184818dbdb9d1c9858dd609a1b60648201526084016102ba565b807f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc6104bf565b6060600080856001600160a01b0316856040516105919190610775565b600060405180830381855af49150503d80600081146105cc576040519150601f19603f3d011682016040523d82523d6000602084013e6105d1565b606091505b50915091506105e2868383876105ec565b9695505050505050565b6060831561065b578251600003610654576001600160a01b0385163b6106545760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e747261637400000060448201526064016102ba565b5081610665565b610665838361066d565b949350505050565b81511561067d5781518083602001fd5b8060405162461bcd60e51b81526004016102ba9190610791565b80356001600160a01b03811681146106ae57600080fd5b919050565b6000602082840312156106c557600080fd5b61043082610697565b6000806000604084860312156106e357600080fd5b6106ec84610697565b9250602084013567ffffffffffffffff8082111561070957600080fd5b818601915086601f83011261071d57600080fd5b81358181111561072c57600080fd5b87602082850101111561073e57600080fd5b6020830194508093505050509250925092565b60005b8381101561076c578181015183820152602001610754565b50506000910152565b60008251610787818460208701610751565b9190910192915050565b60208152600082518060208401526107b0816040850160208701610751565b601f01601f1916919091016040019291505056fe416464726573733a206c6f772d6c6576656c2064656c65676174652063616c6c206661696c6564a2646970667358221220caef1c2a647344b8936c2def885861b955c9b56ccb762c5243ac8ec49af2096f64736f6c63430008140033", + "balance": "0xffffffffffffff21f494c589bfffffff" + }, + "0x0000777700000000000000000000000000000007": { + "contractName": "ProxiedSignalService", + "storage": {}, + "code": "0x608060405234801561001057600080fd5b50600436106100b45760003560e01c80636c6563f6116100715780636c6563f614610162578063715018a6146101755780638da5cb5b1461017d578063a86f9d9e1461018e578063f2fde38b146101a1578063f8f3f844146101b457600080fd5b80630652b57a146100b957806319ab453c146100ce57806332676bc6146100e15780633ab76e9f146101095780635221f6131461012e57806366ca2bc014610141575b600080fd5b6100cc6100c7366004611a18565b6101e0565b005b6100cc6100dc366004611a18565b610263565b6100f46100ef366004611a35565b61037b565b60405190151581526020015b60405180910390f35b6097546001600160a01b03165b6040516001600160a01b039091168152602001610100565b6100f461013c366004611a61565b6103ed565b61015461014f366004611af7565b61055d565b604051908152602001610100565b610116610170366004611b25565b6105a2565b6100cc6105b9565b6065546001600160a01b0316610116565b61011661019c366004611b5a565b6105cd565b6100cc6101af366004611a18565b6105da565b6101546101c2366004611a35565b6040805192835260208301919091526034600c830120918101905290565b6101e8610653565b6001600160a01b03811661020f57604051634d084d8560e11b815260040160405180910390fd5b609780546001600160a01b0319166001600160a01b0383169081179091556040519081527f399ded90cb5ed8d89ef7e76ff4af65c373f06d3bf5d7eef55f4228e7b702a18b9060200160405180910390a150565b600054610100900460ff16158080156102835750600054600160ff909116105b8061029d5750303b15801561029d575060005460ff166001145b6103055760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b60648201526084015b60405180910390fd5b6000805460ff191660011790558015610328576000805461ff0019166101001790555b610331826106ad565b8015610377576000805461ff0019169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b5050565b60006001600160a01b0383166103a4576040516354cdfc8d60e11b815260040160405180910390fd5b60008290036103c65760405163014f1da760e21b815260040160405180910390fd5b5060408051838152602081018390526034600c820120908201909152546001145b92915050565b600046860361040f5760405163e822b48d60e01b815260040160405180910390fd5b6001600160a01b038516610436576040516354cdfc8d60e11b815260040160405180910390fd5b60008490036104585760405163014f1da760e21b815260040160405180910390fd5b600061046683850185611bf6565b9050600061047d647461696b6f60d81b60006105cd565b8251604051632e24533960e21b81526001600160a01b03929092169163b8914ce4916104af9160040190815260200190565b602060405180830381865afa1580156104cc573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906104f09190611cbd565b60408051898152602081018990526034600c820120818301909252606081019190915290915061055190608001604051602081830303815290604052604051806040016040528060018152602001600160f81b8152508460200151846106c6565b98975050505050505050565b600081810361057f5760405163014f1da760e21b815260040160405180910390fd5b506040805133815260208101929092526034600c83012091810190526001815590565b60006105af8484846106ea565b90505b9392505050565b6105c1610653565b6105cb600061079e565b565b60006105b24684846106ea565b6105e2610653565b6001600160a01b0381166106475760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b60648201526084016102fc565b6106508161079e565b50565b6065546001600160a01b031633146105cb5760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657260448201526064016102fc565b6106b56107f0565b6106bd61081f565b6106508161084e565b6000806106d286610897565b90506106e0818686866108c9565b9695505050505050565b60975460405163195ac1a960e21b815260048101859052602481018490526000916001600160a01b03169063656b06a490604401602060405180830381865afa15801561073b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061075f9190611cd6565b90508115801561077657506001600160a01b038116155b156105b257604051631467050360e21b815260048101859052602481018490526044016102fc565b606580546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b600054610100900460ff166108175760405162461bcd60e51b81526004016102fc90611cf3565b6105cb610906565b600054610100900460ff166108465760405162461bcd60e51b81526004016102fc90611cf3565b6105cb610933565b6001600160a01b03811661087557604051634d084d8560e11b815260040160405180910390fd5b609780546001600160a01b0319166001600160a01b0392909216919091179055565b606081805190602001206040516020016108b391815260200190565b6040516020818303038152906040529050919050565b60008060006108d9878686610963565b915091508180156108fb57508051602080830191909120875191880191909120145b979650505050505050565b600054610100900460ff1661092d5760405162461bcd60e51b81526004016102fc90611cf3565b60018055565b600054610100900460ff1661095a5760405162461bcd60e51b81526004016102fc90611cf3565b6105cb3361079e565b60006060600061097285610a3e565b90506000806000610984848a89610b37565b815192955090935091501580806109985750815b6109e45760405162461bcd60e51b815260206004820152601a60248201527f50726f76696465642070726f6f6620697320696e76616c69642e00000000000060448201526064016102fc565b600081610a005760405180602001604052806000815250610a2c565b610a2c86610a0f600188611d54565b81518110610a1f57610a1f611d67565b6020026020010151610f57565b919b919a509098505050505050505050565b60606000610a4b83610f7e565b90506000815167ffffffffffffffff811115610a6957610a69611b86565b604051908082528060200260200182016040528015610aae57816020015b6040805180820190915260608082526020820152815260200190600190039081610a875790505b50905060005b8251811015610b2f576000610ae1848381518110610ad457610ad4611d67565b6020026020010151610fb1565b90506040518060400160405280610af783610f7e565b815260200182815250838381518110610b1257610b12611d67565b60200260200101819052505080610b2890611d7d565b9050610ab4565b509392505050565b600060606000806000610b4987611041565b90506000869050600080610b70604051806040016040528060608152602001606081525090565b60005b8c51811015610f2f578c8181518110610b8e57610b8e611d67565b602002602001015191508284610ba49190611d96565b9350610bb1600188611d96565b965083600003610c0e578482602001518051906020012014610c095760405162461bcd60e51b8152602060048201526011602482015270092dcecc2d8d2c840e4dedee840d0c2e6d607b1b60448201526064016102fc565b610cd0565b602082602001515110610c75578482602001518051906020012014610c095760405162461bcd60e51b815260206004820152601b60248201527f496e76616c6964206c6172676520696e7465726e616c2068617368000000000060448201526064016102fc565b84610c83836020015161117a565b14610cd05760405162461bcd60e51b815260206004820152601a60248201527f496e76616c696420696e7465726e616c206e6f6465206861736800000000000060448201526064016102fc565b610cdc60106001611da9565b60ff1682600001515103610d4a5785518414610f2f576000868581518110610d0657610d06611d67565b01602001518351805160f89290921c925060009183908110610d2a57610d2a611d67565b60200260200101519050610d3d816111a2565b9650600194505050610f1f565b81515160011901610ed7576000610d60836111d8565b9050600081600081518110610d7757610d77611d67565b016020015160f81c90506000610d8e600283611dc2565b610d99906002611df2565b90506000610daa848360ff166111fc565b90506000610db88b8a6111fc565b90506000610dc68383611232565b905060ff851660021480610ddd575060ff85166003145b15610e1757808351148015610df25750808251145b15610e0457610e01818b611d96565b99505b50600160ff1b9950610f2f945050505050565b60ff85161580610e2a575060ff85166001145b15610e805782518114610e4a5750600160ff1b9950610f2f945050505050565b610e718860000151600181518110610e6457610e64611d67565b60200260200101516111a2565b9a509750610f1f945050505050565b60405162461bcd60e51b815260206004820152602660248201527f52656365697665642061206e6f6465207769746820616e20756e6b6e6f776e206044820152650e0e4caccd2f60d31b60648201526084016102fc565b60405162461bcd60e51b815260206004820152601d60248201527f526563656976656420616e20756e706172736561626c65206e6f64652e00000060448201526064016102fc565b610f2881611d7d565b9050610b73565b50600160ff1b841486610f4287866111fc565b909e909d50909b509950505050505050505050565b805180516060916103e791610f6e90600190611d54565b81518110610ad457610ad4611d67565b6040805180820182526000808252602091820152815180830190925282518252808301908201526060906103e7906112ac565b60606000806000610fc185611498565b919450925090506000816001811115610fdc57610fdc611e0b565b146110295760405162461bcd60e51b815260206004820152601860248201527f496e76616c696420524c502062797465732076616c75652e000000000000000060448201526064016102fc565b611038856020015184846117e2565b95945050505050565b60606000825160026110539190611e21565b67ffffffffffffffff81111561106b5761106b611b86565b6040519080825280601f01601f191660200182016040528015611095576020820181803683370190505b50905060005b83518110156111735760048482815181106110b8576110b8611d67565b01602001516001600160f81b031916901c826110d5836002611e21565b815181106110e5576110e5611d67565b60200101906001600160f81b031916908160001a905350601084828151811061111057611110611d67565b0160200151611122919060f81c611dc2565b60f81b82611131836002611e21565b61113c906001611d96565b8151811061114c5761114c611d67565b60200101906001600160f81b031916908160001a90535061116c81611d7d565b905061109b565b5092915050565b600060208251101561118e57506020015190565b818060200190518101906103e79190611cbd565b600060606020836000015110156111c3576111bc8361188b565b90506111cf565b6111cc83610fb1565b90505b6105b28161117a565b60606103e76111f78360000151600081518110610ad457610ad4611d67565b611041565b60608251821061121b57506040805160208101909152600081526103e7565b6105b2838384865161122d9190611d54565b611896565b6000805b8084511180156112465750808351115b8015611297575082818151811061125f5761125f611d67565b602001015160f81c60f81b6001600160f81b03191684828151811061128657611286611d67565b01602001516001600160f81b031916145b156105b2576112a581611d7d565b9050611236565b60606000806112ba84611498565b919350909150600190508160018111156112d6576112d6611e0b565b146113235760405162461bcd60e51b815260206004820152601760248201527f496e76616c696420524c50206c6973742076616c75652e00000000000000000060448201526064016102fc565b6040805160208082526104208201909252600091816020015b604080518082019091526000808252602082015281526020019060019003908161133c5790505090506000835b865181101561148d57602082106113d55760405162461bcd60e51b815260206004820152602a60248201527f50726f766964656420524c50206c6973742065786365656473206d6178206c6960448201526939ba103632b733ba341760b11b60648201526084016102fc565b6000806114126040518060400160405280858c600001516113f69190611d54565b8152602001858c6020015161140b9190611d96565b9052611498565b50915091506040518060400160405280838361142e9190611d96565b8152602001848b602001516114439190611d96565b81525085858151811061145857611458611d67565b602090810291909101015261146e600185611d96565b935061147a8183611d96565b6114849084611d96565b92505050611369565b508152949350505050565b6000806000808460000151116114f05760405162461bcd60e51b815260206004820152601860248201527f524c50206974656d2063616e6e6f74206265206e756c6c2e000000000000000060448201526064016102fc565b6020840151805160001a607f81116115155760006001600094509450945050506117db565b60b7811161159157600061152a608083611d54565b90508087600001511161157f5760405162461bcd60e51b815260206004820152601960248201527f496e76616c696420524c502073686f727420737472696e672e0000000000000060448201526064016102fc565b600195509350600092506117db915050565b60bf81116116805760006115a660b783611d54565b9050808760000151116115fb5760405162461bcd60e51b815260206004820152601f60248201527f496e76616c696420524c50206c6f6e6720737472696e67206c656e6774682e0060448201526064016102fc565b600183015160208290036101000a90046116158183611d96565b8851116116645760405162461bcd60e51b815260206004820152601860248201527f496e76616c696420524c50206c6f6e6720737472696e672e000000000000000060448201526064016102fc565b61166f826001611d96565b96509450600093506117db92505050565b60f781116116fb57600061169560c083611d54565b9050808760000151116116ea5760405162461bcd60e51b815260206004820152601760248201527f496e76616c696420524c502073686f7274206c6973742e00000000000000000060448201526064016102fc565b6001955093508492506117db915050565b600061170860f783611d54565b90508087600001511161175d5760405162461bcd60e51b815260206004820152601d60248201527f496e76616c696420524c50206c6f6e67206c697374206c656e6774682e00000060448201526064016102fc565b600183015160208290036101000a90046117778183611d96565b8851116117bf5760405162461bcd60e51b815260206004820152601660248201527524b73b30b634b210292628103637b733903634b9ba1760511b60448201526064016102fc565b6117ca826001611d96565b96509450600193506117db92505050565b9193909250565b606060008267ffffffffffffffff8111156117ff576117ff611b86565b6040519080825280601f01601f191660200182016040528015611829576020820181803683370190505b509050805160000361183c5790506105b2565b8484016020820160005b8581101561185e578281015182820152602001611846565b5060006001602087066020036101000a039050808251168119845116178252839450505050509392505050565b60606103e7826119ed565b6060816118a481601f611d96565b10156118e35760405162461bcd60e51b815260206004820152600e60248201526d736c6963655f6f766572666c6f7760901b60448201526064016102fc565b826118ee8382611d96565b101561192d5760405162461bcd60e51b815260206004820152600e60248201526d736c6963655f6f766572666c6f7760901b60448201526064016102fc565b6119378284611d96565b8451101561197b5760405162461bcd60e51b8152602060048201526011602482015270736c6963655f6f75744f66426f756e647360781b60448201526064016102fc565b60608215801561199a57604051915060008252602082016040526119e4565b6040519150601f8416801560200281840101858101878315602002848b0101015b818310156119d35780518352602092830192016119bb565b5050858452601f01601f1916604052505b50949350505050565b60606103e78260200151600084600001516117e2565b6001600160a01b038116811461065057600080fd5b600060208284031215611a2a57600080fd5b81356105b281611a03565b60008060408385031215611a4857600080fd5b8235611a5381611a03565b946020939093013593505050565b600080600080600060808688031215611a7957600080fd5b853594506020860135611a8b81611a03565b935060408601359250606086013567ffffffffffffffff80821115611aaf57600080fd5b818801915088601f830112611ac357600080fd5b813581811115611ad257600080fd5b896020828501011115611ae457600080fd5b9699959850939650602001949392505050565b600060208284031215611b0957600080fd5b5035919050565b80358015158114611b2057600080fd5b919050565b600080600060608486031215611b3a57600080fd5b8335925060208401359150611b5160408501611b10565b90509250925092565b60008060408385031215611b6d57600080fd5b82359150611b7d60208401611b10565b90509250929050565b634e487b7160e01b600052604160045260246000fd5b6040805190810167ffffffffffffffff81118282101715611bbf57611bbf611b86565b60405290565b604051601f8201601f1916810167ffffffffffffffff81118282101715611bee57611bee611b86565b604052919050565b60006020808385031215611c0957600080fd5b823567ffffffffffffffff80821115611c2157600080fd5b9084019060408287031215611c3557600080fd5b611c3d611b9c565b823581528383013582811115611c5257600080fd5b80840193505086601f840112611c6757600080fd5b823582811115611c7957611c79611b86565b611c8b601f8201601f19168601611bc5565b92508083528785828601011115611ca157600080fd5b8085850186850137600090830185015292830152509392505050565b600060208284031215611ccf57600080fd5b5051919050565b600060208284031215611ce857600080fd5b81516105b281611a03565b6020808252602b908201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960408201526a6e697469616c697a696e6760a81b606082015260800190565b634e487b7160e01b600052601160045260246000fd5b818103818111156103e7576103e7611d3e565b634e487b7160e01b600052603260045260246000fd5b600060018201611d8f57611d8f611d3e565b5060010190565b808201808211156103e7576103e7611d3e565b60ff81811683821601908111156103e7576103e7611d3e565b600060ff831680611de357634e487b7160e01b600052601260045260246000fd5b8060ff84160691505092915050565b60ff82811682821603908111156103e7576103e7611d3e565b634e487b7160e01b600052602160045260246000fd5b80820281158282048414176103e7576103e7611d3e56fea2646970667358221220727b3b71bb6428f2b0ff827ceeabefd08ed4c1ffd6ad882c5d137fbe8f96be8064736f6c63430008140033", + "balance": "0x0" + }, + "0x1000777700000000000000000000000000000007": { + "contractName": "SignalServiceProxy", + "storage": { + "0x0000000000000000000000000000000000000000000000000000000000000000": "0x0000000000000000000000000000000000000000000000000000000000000001", + "0x0000000000000000000000000000000000000000000000000000000000000001": "0x0000000000000000000000000000000000000000000000000000000000000001", + "0x0000000000000000000000000000000000000000000000000000000000000065": "0x00000000000000000000000019b4f9c381c7927fe33d853e48b560141a380c44", + "0x0000000000000000000000000000000000000000000000000000000000000097": "0x0000000000000000000000001000777700000000000000000000000000000006", + "0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103": "0x113cE23c9e0cc50F4D41d7cE6DA02dCAFf8BFF85", + "0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc": "0x0000777700000000000000000000000000000007" + }, + "code": "0x60806040526004361061004e5760003560e01c80633659cfe6146100655780634f1ef286146100855780635c60da1b146100985780638f283970146100c9578063f851a440146100e95761005d565b3661005d5761005b6100fe565b005b61005b6100fe565b34801561007157600080fd5b5061005b6100803660046106b3565b610118565b61005b6100933660046106ce565b610155565b3480156100a457600080fd5b506100ad6101bc565b6040516001600160a01b03909116815260200160405180910390f35b3480156100d557600080fd5b5061005b6100e43660046106b3565b6101ed565b3480156100f557600080fd5b506100ad61020d565b61010661022e565b6101166101116102c3565b6102cd565b565b6101206102f1565b6001600160a01b0316330361014d5761014a81604051806020016040528060008152506000610324565b50565b61014a6100fe565b61015d6102f1565b6001600160a01b031633036101b4576101af8383838080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525060019250610324915050565b505050565b6101af6100fe565b60006101c66102f1565b6001600160a01b031633036101e2576101dd6102c3565b905090565b6101ea6100fe565b90565b6101f56102f1565b6001600160a01b0316330361014d5761014a8161034f565b60006102176102f1565b6001600160a01b031633036101e2576101dd6102f1565b6102366102f1565b6001600160a01b031633036101165760405162461bcd60e51b815260206004820152604260248201527f5472616e73706172656e745570677261646561626c6550726f78793a2061646d60448201527f696e2063616e6e6f742066616c6c6261636b20746f2070726f78792074617267606482015261195d60f21b608482015260a4015b60405180910390fd5b60006101dd6103a3565b3660008037600080366000845af43d6000803e8080156102ec573d6000f35b3d6000fd5b60007fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035b546001600160a01b0316919050565b61032d836103cb565b60008251118061033a5750805b156101af57610349838361040b565b50505050565b7f7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f6103786102f1565b604080516001600160a01b03928316815291841660208301520160405180910390a161014a81610437565b60007f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc610315565b6103d4816104e0565b6040516001600160a01b038216907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b90600090a250565b606061043083836040518060600160405280602781526020016107c560279139610574565b9392505050565b6001600160a01b03811661049c5760405162461bcd60e51b815260206004820152602660248201527f455243313936373a206e65772061646d696e20697320746865207a65726f206160448201526564647265737360d01b60648201526084016102ba565b807fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035b80546001600160a01b0319166001600160a01b039290921691909117905550565b6001600160a01b0381163b61054d5760405162461bcd60e51b815260206004820152602d60248201527f455243313936373a206e657720696d706c656d656e746174696f6e206973206e60448201526c1bdd08184818dbdb9d1c9858dd609a1b60648201526084016102ba565b807f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc6104bf565b6060600080856001600160a01b0316856040516105919190610775565b600060405180830381855af49150503d80600081146105cc576040519150601f19603f3d011682016040523d82523d6000602084013e6105d1565b606091505b50915091506105e2868383876105ec565b9695505050505050565b6060831561065b578251600003610654576001600160a01b0385163b6106545760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e747261637400000060448201526064016102ba565b5081610665565b610665838361066d565b949350505050565b81511561067d5781518083602001fd5b8060405162461bcd60e51b81526004016102ba9190610791565b80356001600160a01b03811681146106ae57600080fd5b919050565b6000602082840312156106c557600080fd5b61043082610697565b6000806000604084860312156106e357600080fd5b6106ec84610697565b9250602084013567ffffffffffffffff8082111561070957600080fd5b818601915086601f83011261071d57600080fd5b81358181111561072c57600080fd5b87602082850101111561073e57600080fd5b6020830194508093505050509250925092565b60005b8381101561076c578181015183820152602001610754565b50506000910152565b60008251610787818460208701610751565b9190910192915050565b60208152600082518060208401526107b0816040850160208701610751565b601f01601f1916919091016040019291505056fe416464726573733a206c6f772d6c6576656c2064656c65676174652063616c6c206661696c6564a2646970667358221220caef1c2a647344b8936c2def885861b955c9b56ccb762c5243ac8ec49af2096f64736f6c63430008140033", + "balance": "0x0" + }, + "0x0000777700000000000000000000000000000005": { + "contractName": "RegularERC20", + "storage": { + "0x0000000000000000000000000000000000000000000000000000000000000003": "0x526567756c617245524332300000000000000000000000000000000000000018", + "0x0000000000000000000000000000000000000000000000000000000000000004": "0x52474c0000000000000000000000000000000000000000000000000000000006", + "0x0000000000000000000000000000000000000000000000000000000000000002": "0x00000000000000000000000000000000000000000000000000000000003e8000", + "0xc4fd933fc30203af5f8bd19ad30e064c96642a369b9fc4288ea95569541f4034": "0x00000000000000000000000000000000000000000000000000000000000fa000", + "0x967c153683def525608ec6efe0cac3319a9c97a6d4164fb43765c79311abffdc": "0x00000000000000000000000000000000000000000000000000000000000fa000", + "0x5de52a798624bd714aafa39067b28145e3708f46d26ac1d8a415c99cb44977ab": "0x00000000000000000000000000000000000000000000000000000000000fa000", + "0x29f6d6ec0904737d43c119104bcf9427181549a0e10faeefa218e436001011fd": "0x00000000000000000000000000000000000000000000000000000000000fa000" + }, + "code": "0x608060405234801561001057600080fd5b50600436106100a95760003560e01c80633950935111610071578063395093511461012357806370a082311461013657806395d89b411461015f578063a457c2d714610167578063a9059cbb1461017a578063dd62ed3e1461018d57600080fd5b806306fdde03146100ae578063095ea7b3146100cc57806318160ddd146100ef57806323b872dd14610101578063313ce56714610114575b600080fd5b6100b66101a0565b6040516100c3919061069c565b60405180910390f35b6100df6100da366004610706565b610232565b60405190151581526020016100c3565b6002545b6040519081526020016100c3565b6100df61010f366004610730565b61024c565b604051601281526020016100c3565b6100df610131366004610706565b610270565b6100f361014436600461076c565b6001600160a01b031660009081526020819052604090205490565b6100b6610292565b6100df610175366004610706565b6102a1565b6100df610188366004610706565b610321565b6100f361019b36600461078e565b61032f565b6060600380546101af906107c1565b80601f01602080910402602001604051908101604052809291908181526020018280546101db906107c1565b80156102285780601f106101fd57610100808354040283529160200191610228565b820191906000526020600020905b81548152906001019060200180831161020b57829003601f168201915b5050505050905090565b60003361024081858561035a565b60019150505b92915050565b60003361025a85828561047e565b6102658585856104f8565b506001949350505050565b600033610240818585610283838361032f565b61028d91906107fb565b61035a565b6060600480546101af906107c1565b600033816102af828661032f565b9050838110156103145760405162461bcd60e51b815260206004820152602560248201527f45524332303a2064656372656173656420616c6c6f77616e63652062656c6f77604482015264207a65726f60d81b60648201526084015b60405180910390fd5b610265828686840361035a565b6000336102408185856104f8565b6001600160a01b03918216600090815260016020908152604080832093909416825291909152205490565b6001600160a01b0383166103bc5760405162461bcd60e51b8152602060048201526024808201527f45524332303a20617070726f76652066726f6d20746865207a65726f206164646044820152637265737360e01b606482015260840161030b565b6001600160a01b03821661041d5760405162461bcd60e51b815260206004820152602260248201527f45524332303a20617070726f766520746f20746865207a65726f206164647265604482015261737360f01b606482015260840161030b565b6001600160a01b0383811660008181526001602090815260408083209487168084529482529182902085905590518481527f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925910160405180910390a3505050565b600061048a848461032f565b905060001981146104f257818110156104e55760405162461bcd60e51b815260206004820152601d60248201527f45524332303a20696e73756666696369656e7420616c6c6f77616e6365000000604482015260640161030b565b6104f2848484840361035a565b50505050565b6001600160a01b03831661055c5760405162461bcd60e51b815260206004820152602560248201527f45524332303a207472616e736665722066726f6d20746865207a65726f206164604482015264647265737360d81b606482015260840161030b565b6001600160a01b0382166105be5760405162461bcd60e51b815260206004820152602360248201527f45524332303a207472616e7366657220746f20746865207a65726f206164647260448201526265737360e81b606482015260840161030b565b6001600160a01b038316600090815260208190526040902054818110156106365760405162461bcd60e51b815260206004820152602660248201527f45524332303a207472616e7366657220616d6f756e7420657863656564732062604482015265616c616e636560d01b606482015260840161030b565b6001600160a01b03848116600081815260208181526040808320878703905593871680835291849020805487019055925185815290927fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef910160405180910390a36104f2565b600060208083528351808285015260005b818110156106c9578581018301518582016040015282016106ad565b506000604082860101526040601f19601f8301168501019250505092915050565b80356001600160a01b038116811461070157600080fd5b919050565b6000806040838503121561071957600080fd5b610722836106ea565b946020939093013593505050565b60008060006060848603121561074557600080fd5b61074e846106ea565b925061075c602085016106ea565b9150604084013590509250925092565b60006020828403121561077e57600080fd5b610787826106ea565b9392505050565b600080604083850312156107a157600080fd5b6107aa836106ea565b91506107b8602084016106ea565b90509250929050565b600181811c908216806107d557607f821691505b6020821081036107f557634e487b7160e01b600052602260045260246000fd5b50919050565b8082018082111561024657634e487b7160e01b600052601160045260246000fdfea26469706673582212200c6a590d0220261e9ad2a153910ca40f21f69a425e5af92fee3a769ffc07753764736f6c63430008140033", + "balance": "0x0" + } +}
diff --git ethereum/go-ethereum/core/taiko_genesis/grimsvotn.json taikoxyz/taiko-geth/core/taiko_genesis/grimsvotn.json new file mode 100644 index 0000000000000000000000000000000000000000..b9932a22f1e7129e1a440f3b03188014a36f4998 --- /dev/null +++ taikoxyz/taiko-geth/core/taiko_genesis/grimsvotn.json @@ -0,0 +1,164 @@ +{ + "0x19B4F9C381C7927FE33D853e48b560141A380C44": { + "balance": "0xfffffffffffffacbbb7ca13a7fffffff" + }, + "0x113cE23c9e0cc50F4D41d7cE6DA02dCAFf8BFF85": { + "balance": "0xfffffffffffffacbbb7ca13a7fffffff" + }, + "0x09d4121CD4123F039390c7f5e99b15BED5e07222": { + "balance": "0xfffffffffffffacbbb7ca13a7fffffff" + }, + "0x9E5da4B6D25Ee5A68aa8c29B6B87C82f7F463893": { + "balance": "0xfffffffffffffacbbb7ca13a7fffffff" + }, + "0x5075901Fdd1d57Ca754472cb94967f564bA7dc6E": { + "contractName": "LibTrieProof", + "storage": {}, + "code": "0x73000000000000000000000000000000000000000030146080604052600436106100355760003560e01c8063a54274621461003a575b600080fd5b61004d61004836600461173e565b610061565b604051901515815260200160405180910390f35b600080806100718486018661188e565b6040516bffffffffffffffffffffffff1960608c901b166020820152919350915060009081906100b490603401604051602081830303815290604052858d610184565b915091508161010a5760405162461bcd60e51b815260206004820152601960248201527f4c54503a696e76616c6964206163636f756e742070726f6f660000000000000060448201526064015b60405180910390fd5b6000610115826101ad565b9050600061013c8260028151811061012f5761012f6118f2565b60200260200101516101e6565b90506101738b60405160200161015491815260200190565b60405160208183030381529060405261016c8c6102e9565b87846102fc565b9d9c50505050505050505050505050565b60006060600061019386610316565b90506101a0818686610348565b9250925050935093915050565b6040805180820182526000808252602091820152815180830190925282518252808301908201526060906101e090610423565b92915050565b600060218260000151111561023d5760405162461bcd60e51b815260206004820152601a60248201527f496e76616c696420524c5020627974657333322076616c75652e0000000000006044820152606401610101565b600080600061024b8561060f565b91945092509050600081600181111561026657610266611908565b146102b35760405162461bcd60e51b815260206004820152601a60248201527f496e76616c696420524c5020627974657333322076616c75652e0000000000006044820152606401610101565b60008386602001516102c59190611934565b805190915060208410156102df5760208490036101000a90045b9695505050505050565b60606101e06102f783610959565b610a8d565b60008061030886610316565b90506102df81868686610afc565b6060818051906020012060405160200161033291815260200190565b6040516020818303038152906040529050919050565b60006060600061035785610b39565b90506000806000610369848a89610c32565b8151929550909350915015808061037d5750815b6103c95760405162461bcd60e51b815260206004820152601a60248201527f50726f76696465642070726f6f6620697320696e76616c69642e0000000000006044820152606401610101565b6000816103e55760405180602001604052806000815250610411565b610411866103f4600188611947565b81518110610404576104046118f2565b6020026020010151611052565b919b919a509098505050505050505050565b60606000806104318461060f565b9193509091506001905081600181111561044d5761044d611908565b1461049a5760405162461bcd60e51b815260206004820152601760248201527f496e76616c696420524c50206c6973742076616c75652e0000000000000000006044820152606401610101565b6040805160208082526104208201909252600091816020015b60408051808201909152600080825260208201528152602001906001900390816104b35790505090506000835b8651811015610604576020821061054c5760405162461bcd60e51b815260206004820152602a60248201527f50726f766964656420524c50206c6973742065786365656473206d6178206c6960448201526939ba103632b733ba341760b11b6064820152608401610101565b6000806105896040518060400160405280858c6000015161056d9190611947565b8152602001858c602001516105829190611934565b905261060f565b5091509150604051806040016040528083836105a59190611934565b8152602001848b602001516105ba9190611934565b8152508585815181106105cf576105cf6118f2565b60209081029190910101526105e5600185611934565b93506105f18183611934565b6105fb9084611934565b925050506104e0565b508152949350505050565b6000806000808460000151116106675760405162461bcd60e51b815260206004820152601860248201527f524c50206974656d2063616e6e6f74206265206e756c6c2e00000000000000006044820152606401610101565b6020840151805160001a607f811161068c576000600160009450945094505050610952565b60b781116107085760006106a1608083611947565b9050808760000151116106f65760405162461bcd60e51b815260206004820152601960248201527f496e76616c696420524c502073686f727420737472696e672e000000000000006044820152606401610101565b60019550935060009250610952915050565b60bf81116107f757600061071d60b783611947565b9050808760000151116107725760405162461bcd60e51b815260206004820152601f60248201527f496e76616c696420524c50206c6f6e6720737472696e67206c656e6774682e006044820152606401610101565b600183015160208290036101000a900461078c8183611934565b8851116107db5760405162461bcd60e51b815260206004820152601860248201527f496e76616c696420524c50206c6f6e6720737472696e672e00000000000000006044820152606401610101565b6107e6826001611934565b965094506000935061095292505050565b60f7811161087257600061080c60c083611947565b9050808760000151116108615760405162461bcd60e51b815260206004820152601760248201527f496e76616c696420524c502073686f7274206c6973742e0000000000000000006044820152606401610101565b600195509350849250610952915050565b600061087f60f783611947565b9050808760000151116108d45760405162461bcd60e51b815260206004820152601d60248201527f496e76616c696420524c50206c6f6e67206c697374206c656e6774682e0000006044820152606401610101565b600183015160208290036101000a90046108ee8183611934565b8851116109365760405162461bcd60e51b815260206004820152601660248201527524b73b30b634b210292628103637b733903634b9ba1760511b6044820152606401610101565b610941826001611934565b965094506001935061095292505050565b9193909250565b606060008260405160200161097091815260200190565b604051602081830303815290604052905060005b60208110156109c55781818151811061099f5761099f6118f2565b01602001516001600160f81b0319166000036109c5576109be8161195a565b9050610984565b60006109d2826020611947565b67ffffffffffffffff8111156109ea576109ea6117eb565b6040519080825280601f01601f191660200182016040528015610a14576020820181803683370190505b50905060005b8151811015610a84578383610a2e8161195a565b945081518110610a4057610a406118f2565b602001015160f81c60f81b828281518110610a5d57610a5d6118f2565b60200101906001600160f81b031916908160001a905350610a7d8161195a565b9050610a1a565b50949350505050565b60608082516001148015610abb5750608083600081518110610ab157610ab16118f2565b016020015160f81c105b15610ac75750816101e0565b610ad383516080611079565b83604051602001610ae59291906119a3565b604051602081830303815290604052905092915050565b6000806000610b0c878686610348565b91509150818015610b2e57508051602080830191909120875191880191909120145b979650505050505050565b60606000610b46836101ad565b90506000815167ffffffffffffffff811115610b6457610b646117eb565b604051908082528060200260200182016040528015610ba957816020015b6040805180820190915260608082526020820152815260200190600190039081610b825790505b50905060005b8251811015610c2a576000610bdc848381518110610bcf57610bcf6118f2565b6020026020010151611223565b90506040518060400160405280610bf2836101ad565b815260200182815250838381518110610c0d57610c0d6118f2565b60200260200101819052505080610c239061195a565b9050610baf565b509392505050565b600060606000806000610c44876112b3565b90506000869050600080610c6b604051806040016040528060608152602001606081525090565b60005b8c5181101561102a578c8181518110610c8957610c896118f2565b602002602001015191508284610c9f9190611934565b9350610cac600188611934565b965083600003610d09578482602001518051906020012014610d045760405162461bcd60e51b8152602060048201526011602482015270092dcecc2d8d2c840e4dedee840d0c2e6d607b1b6044820152606401610101565b610dcb565b602082602001515110610d70578482602001518051906020012014610d045760405162461bcd60e51b815260206004820152601b60248201527f496e76616c6964206c6172676520696e7465726e616c206861736800000000006044820152606401610101565b84610d7e83602001516113ec565b14610dcb5760405162461bcd60e51b815260206004820152601a60248201527f496e76616c696420696e7465726e616c206e6f646520686173680000000000006044820152606401610101565b610dd7601060016119c0565b60ff1682600001515103610e45578551841461102a576000868581518110610e0157610e016118f2565b01602001518351805160f89290921c925060009183908110610e2557610e256118f2565b60200260200101519050610e3881611414565b965060019450505061101a565b81515160011901610fd2576000610e5b8361144a565b9050600081600081518110610e7257610e726118f2565b016020015160f81c90506000610e896002836119ef565b610e94906002611a11565b90506000610ea5848360ff1661146e565b90506000610eb38b8a61146e565b90506000610ec183836114a4565b905060ff851660021480610ed8575060ff85166003145b15610f1257808351148015610eed5750808251145b15610eff57610efc818b611934565b99505b50600160ff1b995061102a945050505050565b60ff85161580610f25575060ff85166001145b15610f7b5782518114610f455750600160ff1b995061102a945050505050565b610f6c8860000151600181518110610f5f57610f5f6118f2565b6020026020010151611414565b9a50975061101a945050505050565b60405162461bcd60e51b815260206004820152602660248201527f52656365697665642061206e6f6465207769746820616e20756e6b6e6f776e206044820152650e0e4caccd2f60d31b6064820152608401610101565b60405162461bcd60e51b815260206004820152601d60248201527f526563656976656420616e20756e706172736561626c65206e6f64652e0000006044820152606401610101565b6110238161195a565b9050610c6e565b50600160ff1b84148661103d878661146e565b909e909d50909b509950505050505050505050565b805180516060916101e09161106990600190611947565b81518110610bcf57610bcf6118f2565b60608060388410156110e057604080516001808252818301909252906020820181803683370190505090506110ae83856119c0565b60f81b816000815181106110c4576110c46118f2565b60200101906001600160f81b031916908160001a90535061121c565b600060015b6110ef8187611a2a565b15611112576110fd8261195a565b915061110b61010082611a3e565b90506110e5565b61111d826001611934565b67ffffffffffffffff811115611135576111356117eb565b6040519080825280601f01601f19166020018201604052801561115f576020820181803683370190505b50925061116c85836119c0565b6111779060376119c0565b60f81b8360008151811061118d5761118d6118f2565b60200101906001600160f81b031916908160001a905350600190505b818111611219576101006111bd8284611947565b6111c990610100611b39565b6111d39088611a2a565b6111dd9190611b45565b60f81b8382815181106111f2576111f26118f2565b60200101906001600160f81b031916908160001a9053506112128161195a565b90506111a9565b50505b9392505050565b606060008060006112338561060f565b91945092509050600081600181111561124e5761124e611908565b1461129b5760405162461bcd60e51b815260206004820152601860248201527f496e76616c696420524c502062797465732076616c75652e00000000000000006044820152606401610101565b6112aa8560200151848461151e565b95945050505050565b60606000825160026112c59190611a3e565b67ffffffffffffffff8111156112dd576112dd6117eb565b6040519080825280601f01601f191660200182016040528015611307576020820181803683370190505b50905060005b83518110156113e557600484828151811061132a5761132a6118f2565b01602001516001600160f81b031916901c82611347836002611a3e565b81518110611357576113576118f2565b60200101906001600160f81b031916908160001a9053506010848281518110611382576113826118f2565b0160200151611394919060f81c6119ef565b60f81b826113a3836002611a3e565b6113ae906001611934565b815181106113be576113be6118f2565b60200101906001600160f81b031916908160001a9053506113de8161195a565b905061130d565b5092915050565b600060208251101561140057506020015190565b818060200190518101906101e09190611b59565b600060606020836000015110156114355761142e836115c7565b9050611441565b61143e83611223565b90505b61121c816113ec565b60606101e06114698360000151600081518110610bcf57610bcf6118f2565b6112b3565b60608251821061148d57506040805160208101909152600081526101e0565b61121c838384865161149f9190611947565b6115d2565b6000805b8084511180156114b85750808351115b801561150957508281815181106114d1576114d16118f2565b602001015160f81c60f81b6001600160f81b0319168482815181106114f8576114f86118f2565b01602001516001600160f81b031916145b1561121c576115178161195a565b90506114a8565b606060008267ffffffffffffffff81111561153b5761153b6117eb565b6040519080825280601f01601f191660200182016040528015611565576020820181803683370190505b509050805160000361157857905061121c565b8484016020820160005b8581101561159a578281015182820152602001611582565b5060006001602087066020036101000a039050808251168119845116178252839450505050509392505050565b60606101e082611728565b6060816115e081601f611934565b101561161f5760405162461bcd60e51b815260206004820152600e60248201526d736c6963655f6f766572666c6f7760901b6044820152606401610101565b8261162a8382611934565b10156116695760405162461bcd60e51b815260206004820152600e60248201526d736c6963655f6f766572666c6f7760901b6044820152606401610101565b6116738284611934565b845110156116b75760405162461bcd60e51b8152602060048201526011602482015270736c6963655f6f75744f66426f756e647360781b6044820152606401610101565b6060821580156116d65760405191506000825260208201604052610a84565b6040519150601f8416801560200281840101858101878315602002848b0101015b8183101561170f5780518352602092830192016116f7565b5050858452601f01601f19166040525050949350505050565b60606101e082602001516000846000015161151e565b60008060008060008060a0878903121561175757600080fd5b8635955060208701356001600160a01b038116811461177557600080fd5b94506040870135935060608701359250608087013567ffffffffffffffff808211156117a057600080fd5b818901915089601f8301126117b457600080fd5b8135818111156117c357600080fd5b8a60208285010111156117d557600080fd5b6020830194508093505050509295509295509295565b634e487b7160e01b600052604160045260246000fd5b600082601f83011261181257600080fd5b813567ffffffffffffffff8082111561182d5761182d6117eb565b604051601f8301601f19908116603f01168101908282118183101715611855576118556117eb565b8160405283815286602085880101111561186e57600080fd5b836020870160208301376000602085830101528094505050505092915050565b600080604083850312156118a157600080fd5b823567ffffffffffffffff808211156118b957600080fd5b6118c586838701611801565b935060208501359150808211156118db57600080fd5b506118e885828601611801565b9150509250929050565b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052602160045260246000fd5b634e487b7160e01b600052601160045260246000fd5b808201808211156101e0576101e061191e565b818103818111156101e0576101e061191e565b60006001820161196c5761196c61191e565b5060010190565b6000815160005b81811015611994576020818501810151868301520161197a565b50600093019283525090919050565b60006119b86119b28386611973565b84611973565b949350505050565b60ff81811683821601908111156101e0576101e061191e565b634e487b7160e01b600052601260045260246000fd5b600060ff831680611a0257611a026119d9565b8060ff84160691505092915050565b60ff82811682821603908111156101e0576101e061191e565b600082611a3957611a396119d9565b500490565b80820281158282048414176101e0576101e061191e565b600181815b80851115611a90578160001904821115611a7657611a7661191e565b80851615611a8357918102915b93841c9390800290611a5a565b509250929050565b600082611aa7575060016101e0565b81611ab4575060006101e0565b8160018114611aca5760028114611ad457611af0565b60019150506101e0565b60ff841115611ae557611ae561191e565b50506001821b6101e0565b5060208310610133831016604e8410600b8410161715611b13575081810a6101e0565b611b1d8383611a55565b8060001904821115611b3157611b3161191e565b029392505050565b600061121c8383611a98565b600082611b5457611b546119d9565b500690565b600060208284031215611b6b57600080fd5b505191905056fea264697066735822122067ddb2e3690f84d93d1a412860f6a463049c890e3ec168676bae8e8dc7ae3f3764736f6c63430008120033", + "balance": "0x0" + }, + "0x032847A8Cdd4487f83705f8D702743b60029AFDD": { + "contractName": "LibBridgeRetry", + "storage": {}, + "code": "0x73000000000000000000000000000000000000000030146080604052600080fdfea2646970667358221220beb5d00868487ae13b8103480d5057ef120c70dcf0a0b13d4d29fb292e8aad5764736f6c63430008120033", + "balance": "0x0" + }, + "0x3e55D64323AD7E3287aa283475903D3fb3cA5098": { + "contractName": "LibBridgeProcess", + "storage": {}, + "code": "0x73000000000000000000000000000000000000000030146080604052600080fdfea2646970667358221220d80093ff59f040f5928ff201a3c212fa752b2ff8e0aea20a97ac0325ba978abb64736f6c63430008120033", + "balance": "0x0" + }, + "0x0000777700000000000000000000000000000006": { + "contractName": "ProxiedAddressManager", + "storage": {}, + "code": "0x608060405234801561001057600080fd5b50600436106100625760003560e01c8063656b06a414610067578063715018a6146100b75780638da5cb5b146100c1578063decd8e39146100d2578063e1c7392a146100e5578063f2fde38b146100ed575b600080fd5b61009b610075366004610466565b60009182526065602090815260408084209284529190529020546001600160a01b031690565b6040516001600160a01b03909116815260200160405180910390f35b6100bf610100565b005b6033546001600160a01b031661009b565b6100bf6100e03660046104a4565b610114565b6100bf6101d4565b6100bf6100fb3660046104d9565b6102ea565b610108610360565b61011260006103ba565b565b61011c610360565b6001600160a01b0381163b15801561013c57506001600160a01b03811633145b1561015a57604051633baa901360e21b815260040160405180910390fd5b600083815260656020908152604080832085845282529182902080546001600160a01b038581166001600160a01b0319831681179093558451928352169181018290529091849186917fe41a6e8584d6e19a0dfc5f9331be4ebe61b5f025d45da164c9ca6ee9b837cea9910160405180910390a350505050565b600054610100900460ff16158080156101f45750600054600160ff909116105b8061020e5750303b15801561020e575060005460ff166001145b6102765760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b60648201526084015b60405180910390fd5b6000805460ff191660011790558015610299576000805461ff0019166101001790555b6102a161040c565b80156102e7576000805461ff0019169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b50565b6102f2610360565b6001600160a01b0381166103575760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b606482015260840161026d565b6102e7816103ba565b6033546001600160a01b031633146101125760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015260640161026d565b603380546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b600054610100900460ff166104335760405162461bcd60e51b815260040161026d906104fb565b610112600054610100900460ff1661045d5760405162461bcd60e51b815260040161026d906104fb565b610112336103ba565b6000806040838503121561047957600080fd5b50508035926020909101359150565b80356001600160a01b038116811461049f57600080fd5b919050565b6000806000606084860312156104b957600080fd5b83359250602084013591506104d060408501610488565b90509250925092565b6000602082840312156104eb57600080fd5b6104f482610488565b9392505050565b6020808252602b908201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960408201526a6e697469616c697a696e6760a81b60608201526080019056fea2646970667358221220c5f7d4557009ba7141b3cd005aecb51648d30e5868346d5747a6722064e5e73664736f6c63430008120033", + "balance": "0x0" + }, + "0x1000777700000000000000000000000000000006": { + "contractName": "AddressManagerProxy", + "storage": { + "0x0000000000000000000000000000000000000000000000000000000000000000": "0x0000000000000000000000000000000000000000000000000000000000000001", + "0x0000000000000000000000000000000000000000000000000000000000000033": "0x00000000000000000000000019b4f9c381c7927fe33d853e48b560141a380c44", + "0xfeaa72fcc59acba6371da88141d071c9993f23312f54395296e3d9e5d39f0056": "0x0000000000000000000000001000777700000000000000000000000000000001", + "0x92fbb82d3d87ec735ae0893053f892b13be008dae0d966d083fc63772a95a170": "0x0000000000000000000000001000777700000000000000000000000000000004", + "0x2d89f514e5eeed612cd92d7cbfb188ecb4896b21769ef98030d34bcdb4c94bd9": "0x0000000000000000000000001000777700000000000000000000000000000002", + "0xc783d6d711f5c3d107daed8026e2089323b4661d3f4f92208071f4addcb75352": "0x0000000000000000000000001000777700000000000000000000000000000003", + "0xe4e56c450eba5c80504ff288920951a9da92b61b66c227cf06a8edb6e2edb548": "0x0000000000000000000000001000777700000000000000000000000000000007", + "0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103": "0x113cE23c9e0cc50F4D41d7cE6DA02dCAFf8BFF85", + "0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc": "0x0000777700000000000000000000000000000006" + }, + "code": "0x60806040526004361061004e5760003560e01c80633659cfe6146100655780634f1ef286146100855780635c60da1b146100985780638f283970146100c9578063f851a440146100e95761005d565b3661005d5761005b6100fe565b005b61005b6100fe565b34801561007157600080fd5b5061005b6100803660046106c2565b610118565b61005b6100933660046106dd565b610155565b3480156100a457600080fd5b506100ad6101bc565b6040516001600160a01b03909116815260200160405180910390f35b3480156100d557600080fd5b5061005b6100e43660046106c2565b6101ed565b3480156100f557600080fd5b506100ad61020d565b610106610269565b6101166101116102fe565b610308565b565b61012061032c565b6001600160a01b0316330361014d5761014a8160405180602001604052806000815250600061035f565b50565b61014a6100fe565b61015d61032c565b6001600160a01b031633036101b4576101af8383838080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152506001925061035f915050565b505050565b6101af6100fe565b60006101c661032c565b6001600160a01b031633036101e2576101dd6102fe565b905090565b6101ea6100fe565b90565b6101f561032c565b6001600160a01b0316330361014d5761014a8161038a565b600061021761032c565b6001600160a01b031633036101e2576101dd61032c565b606061025383836040518060600160405280602781526020016107d4602791396103de565b9392505050565b6001600160a01b03163b151590565b61027161032c565b6001600160a01b031633036101165760405162461bcd60e51b815260206004820152604260248201527f5472616e73706172656e745570677261646561626c6550726f78793a2061646d60448201527f696e2063616e6e6f742066616c6c6261636b20746f2070726f78792074617267606482015261195d60f21b608482015260a4015b60405180910390fd5b60006101dd610456565b3660008037600080366000845af43d6000803e808015610327573d6000f35b3d6000fd5b60007fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035b546001600160a01b0316919050565b6103688361047e565b6000825111806103755750805b156101af57610384838361022e565b50505050565b7f7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f6103b361032c565b604080516001600160a01b03928316815291841660208301520160405180910390a161014a816104be565b6060600080856001600160a01b0316856040516103fb9190610784565b600060405180830381855af49150503d8060008114610436576040519150601f19603f3d011682016040523d82523d6000602084013e61043b565b606091505b509150915061044c86838387610567565b9695505050505050565b60007f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc610350565b610487816105e8565b6040516001600160a01b038216907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b90600090a250565b6001600160a01b0381166105235760405162461bcd60e51b815260206004820152602660248201527f455243313936373a206e65772061646d696e20697320746865207a65726f206160448201526564647265737360d01b60648201526084016102f5565b807fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035b80546001600160a01b0319166001600160a01b039290921691909117905550565b606083156105d65782516000036105cf576001600160a01b0385163b6105cf5760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e747261637400000060448201526064016102f5565b50816105e0565b6105e0838361067c565b949350505050565b6001600160a01b0381163b6106555760405162461bcd60e51b815260206004820152602d60248201527f455243313936373a206e657720696d706c656d656e746174696f6e206973206e60448201526c1bdd08184818dbdb9d1c9858dd609a1b60648201526084016102f5565b807f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc610546565b81511561068c5781518083602001fd5b8060405162461bcd60e51b81526004016102f591906107a0565b80356001600160a01b03811681146106bd57600080fd5b919050565b6000602082840312156106d457600080fd5b610253826106a6565b6000806000604084860312156106f257600080fd5b6106fb846106a6565b9250602084013567ffffffffffffffff8082111561071857600080fd5b818601915086601f83011261072c57600080fd5b81358181111561073b57600080fd5b87602082850101111561074d57600080fd5b6020830194508093505050509250925092565b60005b8381101561077b578181015183820152602001610763565b50506000910152565b60008251610796818460208701610760565b9190910192915050565b60208152600082518060208401526107bf816040850160208701610760565b601f01601f1916919091016040019291505056fe416464726573733a206c6f772d6c6576656c2064656c65676174652063616c6c206661696c6564a2646970667358221220f44b4bd0f73d4a6c872717d3b99f5935a2080af0980894ed447890241a743cdb64736f6c63430008120033", + "balance": "0x0" + }, + "0x0000777700000000000000000000000000000001": { + "contractName": "ProxiedTaikoL2", + "storage": {}, + "code": "0x608060405234801561001057600080fd5b50600436106101375760003560e01c80638f3ca30d116100b8578063c7b969081161007c578063c7b96908146102f5578063dac5df781461030f578063e1848cb014610318578063ee82ac5e1461032b578063f2fde38b1461033e578063f535bd561461035157600080fd5b80638f3ca30d146102905780639ee512f2146102a3578063a86f9d9e146102bc578063b8914ce4146102cf578063bacb386d146102e257600080fd5b8063539b8ade116100ff578063539b8ade14610207578063591aad8a146102325780636c6563f614610264578063715018a6146102775780638da5cb5b1461027f57600080fd5b80630652b57a1461013c57806310da3738146101515780633ab76e9f1461018b5780633d384a4b146101b05780634e755573146101c3575b600080fd5b61014f61014a3660046116d2565b61036b565b005b6101787f92954368afd3caa1f3ce3ead0069c1af414054aefe1ef9aeacc1bf426222ce3881565b6040519081526020015b60405180910390f35b6097546001600160a01b03165b6040516001600160a01b039091168152602001610182565b61014f6101be366004611706565b6103ee565b6101cb61065e565b6040805182516001600160801b031681526020808401516001600160401b03908116918301919091529282015190921690820152606001610182565b60cd5461021a906001600160401b031681565b6040516001600160401b039091168152602001610182565b61024561024036600461174c565b6106be565b6040805160ff9094168452602084019290925290820152606001610182565b610198610272366004611792565b6108f9565b61014f610910565b6065546001600160a01b0316610198565b61014f61029e3660046117c7565b610924565b61019871777735367b36bc9b61c50022d9d0700db4ec81565b6101986102ca366004611808565b610ce0565b6101786102dd366004611834565b610cf6565b6101786102f0366004611834565b610d32565b60cd5461021a90600160401b90046001600160401b031681565b61017860cb5481565b61017861032636600461184d565b610d6b565b610178610339366004611834565b610d8f565b61014f61034c3660046116d2565b610ddc565b60cd5461021a90600160801b90046001600160401b031681565b610373610e55565b6001600160a01b03811661039a57604051634d084d8560e11b815260040160405180910390fd5b609780546001600160a01b0319166001600160a01b0383169081179091556040519081527f399ded90cb5ed8d89ef7e76ff4af65c373f06d3bf5d7eef55f4228e7b702a18b9060200160405180910390a150565b3371777735367b36bc9b61c50022d9d0700db4ec1461042057604051636494e9f760e01b815260040160405180910390fd5b600061042d6001436118a8565b9050804060008061043d84610eaf565b915091508160cb54146104765760cb54604051636340d9fb60e11b81526004810191909152602481018390526044015b60405180910390fd5b60cb819055600084815260c96020908152604080832086905560cd80546fffffffffffffffff00000000000000001916600160401b6001600160401b038c1690810291909117909155815180830183528c81528084018c815282865260ca8552948390209051815593516001949094019390935580518b81529182018a90527f7528bbd1cef0e5d13408706892a51ee8ef82bbf33d4ec0c37216f8beba71205b910160405180910390a260008061052b61065e565b905080604001516001600160401b03166000146105935760cd5461056590829061055e906001600160401b0316426118a8565b458a610f42565b60cd80546001600160401b03909216600160801b0267ffffffffffffffff60801b1990921691909117905591505b8148146105c657604051634083acad60e01b81526001600160401b0380841660048301524816602482015260440161046d565b60cd805467ffffffffffffffff1916426001600160401b03908116918217909255604080514384168152858416602082015245909316908301526060820152608081018690524460a08201524160c082015263ffffffff461660e08201527f4dcb01f99c4a2c27a16ab38d00ec92434f8231be81fa62e058f260d3c7156029906101000160405180910390a150505050505050505050565b6040805160608101825260008082526020820181905291810191909152506040805160608101825260cc546001600160801b03811682526001600160401b03600160801b820481166020840152600160c01b909104169181019190915290565b60008060008360ff166001141580156106db57508360ff16600214155b156106f95760405163bcd2d90d60e01b815260040160405180910390fd5b8360ff1660011461072a577fc6047f9441ed7d6d3045406e95c07cd85c778e4b8cef3ca7abac09b95c709ee561074c565b7f79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f817985b915060008460ff16600114610781577fad77eceea844778cb4376153fc8f06f12f1695df4585bf75bfb17ec19ce908186107a3565b7fb4a95509ce05fe8d45987859a067780d16a367c0e2cacf79cd301b93fb7179405b905060008560ff166001146107d8577f71620584f61c57e688bbd3fd7a39a036e588d962c4c830f3dacbc15c917e02f26107fa565b7f45b59254b0320fd853f3f38ac574999e91bd75fd5e6cab9c22c5e71fc6d276e45b82880192831001905060ff86166001036108345761082d8282600170014551231950b75fc4402da1732fc9bebe19610fde565b92506108a3565b61087c7f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a16108778484600170014551231950b75fc4402da1732fc9bebe19610fde565b61102d565b90925090506108a08282600170014551231950b75fc4402da1732fc9bebe19610fde565b92505b7f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a08311156108f0576108e78370014551231950b75fc4402da1732fc9bebe196118a8565b92506001851894505b50509250925092565b600061090684848461104c565b90505b9392505050565b610918610e55565b6109226000611100565b565b600054610100900460ff16158080156109445750600054600160ff909116105b8061095e5750303b15801561095e575060005460ff166001145b6109c15760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b606482015260840161046d565b6000805460ff1916600117905580156109e4576000805461ff0019166101001790555b6001461115806109f8575063ffffffff4610155b15610a16576040516306cffa2760e01b815260040160405180910390fd5b6001431115610a3857604051635a0f9e4160e11b815260040160405180910390fd5b610a4860408301602084016118bb565b6001600160401b031615610c3c57610a6360208301836118bb565b6001600160401b03161580610a8e5750610a8360608301604084016118bb565b6001600160401b0316155b80610aaf5750610aa460808301606084016118bb565b6001600160401b0316155b80610ad05750610ac560a08301608084016118bb565b6001600160401b0316155b15610aee57604051639cc448b560e01b815260040160405180910390fd5b600080610b36610b0460608601604087016118bb565b610b1160208701876118bb565b610b2160808801606089016118bb565b610b3160a0890160808a016118bb565b611152565b91509150816001600160801b031660001480610b6257506001600160401b036001600160801b03831610155b80610b7457506001600160801b038116155b15610b9257604051639cc448b560e01b815260040160405180910390fd5b60cc80546001600160401b038416600160801b026001600160c01b03199091166001600160801b03841617179055610bd060408501602086016118bb565b60cc80546001600160401b0392909216600160c01b026001600160c01b039092169190911790556002610c0960608601604087016118bb565b610c1391906118ec565b60cd60106101000a8154816001600160401b0302191690836001600160401b0316021790555050505b60cd805467ffffffffffffffff1916426001600160401b0316179055610c6183611251565b610c6a43610eaf565b5060cb554315610c95576000610c816001436118a8565b600081815260c96020526040902090409055505b8015610cdb576000805461ff0019169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b505050565b6000610ced46848461104c565b90505b92915050565b6000808215610d055782610d19565b60cd54600160401b90046001600160401b03165b600090815260ca60205260409020600101549392505050565b6000808215610d415782610d55565b60cd54600160401b90046001600160401b03165b600090815260ca60205260409020549392505050565b6000610d86610d7861065e565b8563ffffffff168585610f42565b50949350505050565b6000438210610da057506000919050565b4382108015610dba5750610db6610100436118a8565b8210155b15610dc457504090565b50600090815260c9602052604090205490565b919050565b610de4610e55565b6001600160a01b038116610e495760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b606482015260840161046d565b610e5281611100565b50565b6065546001600160a01b031633146109225760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015260640161046d565b600080610eba61169d565b60005b60ff81108015610ed05750806001018510155b15610f02576000198186030180408360ff83066101008110610ef457610ef4611912565b602002015250600101610ebd565b5046611fe082015261200081209250834081610f1f60ff87611928565b6101008110610f3057610f30611912565b60200201526120009020919391925050565b600080806202bf206001600160401b03851611610f60576000610f67565b6202bf2084035b60cd546040890151919250600160801b90046001600160401b0390811681841601918116880290610fa49082610f9d858261126a565b0390611280565b9350505050610fc686602001516001600160401b031687600001518387611295565b915081600003610fd557600191505b94509492505050565b600060405160408152602080820152602060408201528460608201528560808201528360a08201528260c082015260208160e08360056107d05a03fa61102357600080fd5b5195945050505050565b6000806000198385098385029250828110838203039150509250929050565b60975460405163195ac1a960e21b815260048101859052602481018490526000916001600160a01b03169063656b06a490604401602060405180830381865afa15801561109d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110c1919061193c565b9050811580156110d857506001600160a01b038116155b1561090957604051631467050360e21b8152600481018590526024810184905260440161046d565b606580546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b600080856001600160401b031660000361116e5761116e611959565b600061117b6002886118ec565b90506111996001600160401b038816680755bf798b4a1bf1e461196f565b92506111b86111b384886001600160401b03168489611295565b611354565b915060006111c884848489611295565b905060006111e28585856111dd8b6002611989565b611295565b90506000826111f3836127106119b4565b6111fd91906119cb565b9050806001600160401b0316876001600160401b031614611244576040516331c2ec2360e21b81526001600160401b0380891660048301528216602482015260440161046d565b5050505094509492505050565b6112596113c1565b6112616113f0565b610e528161141f565b60008183116112795781610ced565b5090919050565b600081831161128f5782610ced565b50919050565b60006001600160801b038516158015906112b757506001600160801b03841615155b6112c3576112c3611959565b60006001600160401b038316156112da57826112dd565b60015b905060006112f4856001600160401b031688611468565b9050600061131461130584886119df565b6001600160401b031689611468565b90506001600160801b0387166001600160401b03841661133484846118a8565b61133e91906119cb565b61134891906119cb565b98975050505050505050565b60006001600160801b038211156113bd5760405162461bcd60e51b815260206004820152602760248201527f53616665436173743a2076616c756520646f65736e27742066697420696e20316044820152663238206269747360c81b606482015260840161046d565b5090565b600054610100900460ff166113e85760405162461bcd60e51b815260040161046d90611a06565b6109226114ba565b600054610100900460ff166114175760405162461bcd60e51b815260040161046d90611a06565b6109226114e7565b6001600160a01b03811661144657604051634d084d8560e11b815260040160405180910390fd5b609780546001600160a01b0319166001600160a01b0392909216919091179055565b60008061147e6001600160801b038416856119b4565b9050680755bf798b4a1bf1e481106114a9576040516372de381d60e01b815260040160405180910390fd5b6114b281611517565b949350505050565b600054610100900460ff166114e15760405162461bcd60e51b815260040161046d90611a06565b60018055565b600054610100900460ff1661150e5760405162461bcd60e51b815260040161046d90611a06565b61092233611100565b6000680248ce36a70cb26b3e19821361153257506000919050565b680755bf798b4a1bf1e5821261155b57604051631a93c68960e11b815260040160405180910390fd5b6503782dace9d9604e83901b059150600060606bb17217f7d1cf79abc9e3b39884821b6d2c06887d92262d378b9593af35346c09791803c2923d5d9721c3da80929091056001605f1b0190921d6bb17217f7d1cf79abc9e3b39881029095039081018102606090811d6d019dd9374d4315c8464a395fc09881016c1bff318b126baa436ea9aeaffd19840102821d93840193016d29c9ad45cc0beb0a2ff097a7bab40192909202821d6dcf3c27b2e487711b467e90f19320016c22fcd1cffa6fa000f6e27eeca082018202831d6d022f98fbc368092c79210d196fa0018202831d6d13aaae3ba38de06adc25ebfacc0901820290921d6d624dcbeb5e25df590e409325888a01026d360d7aeea093263ec6495851bd9760621b010574029d9dc38563c32e5c2f6dc192ee70ef65f9978af30260c3939093039290921c92915050565b604051806120000160405280610100906020820280368337509192915050565b6001600160a01b0381168114610e5257600080fd5b6000602082840312156116e457600080fd5b8135610909816116bd565b80356001600160401b0381168114610dd757600080fd5b6000806000806080858703121561171c57600080fd5b8435935060208501359250611733604086016116ef565b9150611741606086016116ef565b905092959194509250565b6000806040838503121561175f57600080fd5b82359150602083013560ff8116811461177757600080fd5b809150509250929050565b80358015158114610dd757600080fd5b6000806000606084860312156117a757600080fd5b83359250602084013591506117be60408501611782565b90509250925092565b60008082840360c08112156117db57600080fd5b83356117e6816116bd565b925060a0601f19820112156117fa57600080fd5b506020830190509250929050565b6000806040838503121561181b57600080fd5b8235915061182b60208401611782565b90509250929050565b60006020828403121561184657600080fd5b5035919050565b60008060006060848603121561186257600080fd5b833563ffffffff8116811461187657600080fd5b9250611884602085016116ef565b91506117be604085016116ef565b634e487b7160e01b600052601160045260246000fd5b81810381811115610cf057610cf0611892565b6000602082840312156118cd57600080fd5b610ced826116ef565b634e487b7160e01b600052601260045260246000fd5b60006001600160401b0380841680611906576119066118d6565b92169190910492915050565b634e487b7160e01b600052603260045260246000fd5b600082611937576119376118d6565b500690565b60006020828403121561194e57600080fd5b8151610909816116bd565b634e487b7160e01b600052600160045260246000fd5b60006001600160801b0380841680611906576119066118d6565b6001600160401b038181168382160280821691908281146119ac576119ac611892565b505092915050565b8082028115828204841417610cf057610cf0611892565b6000826119da576119da6118d6565b500490565b6001600160401b038181168382160190808211156119ff576119ff611892565b5092915050565b6020808252602b908201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960408201526a6e697469616c697a696e6760a81b60608201526080019056fea26469706673582212203890f26859c50d4bcb2990b86955150cc1db102725f3e4bc015ad2ec3f168ef764736f6c63430008120033", + "balance": "0x0" + }, + "0x1000777700000000000000000000000000000001": { + "contractName": "TaikoL2Proxy", + "storage": { + "0x00000000000000000000000000000000000000000000000000000000000000cb": "0xdec49b32a269dacf8af649c78ad8106484a218de96500f2e3cae7afa7871599b", + "0x00000000000000000000000000000000000000000000000000000000000000cc": "0x00000000001e8480000000022a83d6720000001c43c970ab8e4d088428ca4b6f", + "0x00000000000000000000000000000000000000000000000000000000000000cd": "0x000000000000000000000001b171ea0000000000000000000000000064707075", + "0x0000000000000000000000000000000000000000000000000000000000000097": "0x0000000000000000000000001000777700000000000000000000000000000006", + "0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103": "0x113cE23c9e0cc50F4D41d7cE6DA02dCAFf8BFF85", + "0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc": "0x0000777700000000000000000000000000000001" + }, + "code": "0x60806040526004361061004e5760003560e01c80633659cfe6146100655780634f1ef286146100855780635c60da1b146100985780638f283970146100c9578063f851a440146100e95761005d565b3661005d5761005b6100fe565b005b61005b6100fe565b34801561007157600080fd5b5061005b6100803660046106c2565b610118565b61005b6100933660046106dd565b610155565b3480156100a457600080fd5b506100ad6101bc565b6040516001600160a01b03909116815260200160405180910390f35b3480156100d557600080fd5b5061005b6100e43660046106c2565b6101ed565b3480156100f557600080fd5b506100ad61020d565b610106610269565b6101166101116102fe565b610308565b565b61012061032c565b6001600160a01b0316330361014d5761014a8160405180602001604052806000815250600061035f565b50565b61014a6100fe565b61015d61032c565b6001600160a01b031633036101b4576101af8383838080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152506001925061035f915050565b505050565b6101af6100fe565b60006101c661032c565b6001600160a01b031633036101e2576101dd6102fe565b905090565b6101ea6100fe565b90565b6101f561032c565b6001600160a01b0316330361014d5761014a8161038a565b600061021761032c565b6001600160a01b031633036101e2576101dd61032c565b606061025383836040518060600160405280602781526020016107d4602791396103de565b9392505050565b6001600160a01b03163b151590565b61027161032c565b6001600160a01b031633036101165760405162461bcd60e51b815260206004820152604260248201527f5472616e73706172656e745570677261646561626c6550726f78793a2061646d60448201527f696e2063616e6e6f742066616c6c6261636b20746f2070726f78792074617267606482015261195d60f21b608482015260a4015b60405180910390fd5b60006101dd610456565b3660008037600080366000845af43d6000803e808015610327573d6000f35b3d6000fd5b60007fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035b546001600160a01b0316919050565b6103688361047e565b6000825111806103755750805b156101af57610384838361022e565b50505050565b7f7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f6103b361032c565b604080516001600160a01b03928316815291841660208301520160405180910390a161014a816104be565b6060600080856001600160a01b0316856040516103fb9190610784565b600060405180830381855af49150503d8060008114610436576040519150601f19603f3d011682016040523d82523d6000602084013e61043b565b606091505b509150915061044c86838387610567565b9695505050505050565b60007f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc610350565b610487816105e8565b6040516001600160a01b038216907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b90600090a250565b6001600160a01b0381166105235760405162461bcd60e51b815260206004820152602660248201527f455243313936373a206e65772061646d696e20697320746865207a65726f206160448201526564647265737360d01b60648201526084016102f5565b807fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035b80546001600160a01b0319166001600160a01b039290921691909117905550565b606083156105d65782516000036105cf576001600160a01b0385163b6105cf5760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e747261637400000060448201526064016102f5565b50816105e0565b6105e0838361067c565b949350505050565b6001600160a01b0381163b6106555760405162461bcd60e51b815260206004820152602d60248201527f455243313936373a206e657720696d706c656d656e746174696f6e206973206e60448201526c1bdd08184818dbdb9d1c9858dd609a1b60648201526084016102f5565b807f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc610546565b81511561068c5781518083602001fd5b8060405162461bcd60e51b81526004016102f591906107a0565b80356001600160a01b03811681146106bd57600080fd5b919050565b6000602082840312156106d457600080fd5b610253826106a6565b6000806000604084860312156106f257600080fd5b6106fb846106a6565b9250602084013567ffffffffffffffff8082111561071857600080fd5b818601915086601f83011261072c57600080fd5b81358181111561073b57600080fd5b87602082850101111561074d57600080fd5b6020830194508093505050509250925092565b60005b8381101561077b578181015183820152602001610763565b50506000910152565b60008251610796818460208701610760565b9190910192915050565b60208152600082518060208401526107bf816040850160208701610760565b601f01601f1916919091016040019291505056fe416464726573733a206c6f772d6c6576656c2064656c65676174652063616c6c206661696c6564a2646970667358221220f44b4bd0f73d4a6c872717d3b99f5935a2080af0980894ed447890241a743cdb64736f6c63430008120033", + "balance": "0x0" + }, + "0x0000777700000000000000000000000000000004": { + "contractName": "ProxiedBridge", + "storage": {}, + "code": "0x60806040526004361061012e5760003560e01c8063715018a6116100ab578063bac443e21161006f578063bac443e21461041b578063ce70f39b1461043b578063d0496d6a1461045b578063f2fde38b146104ca578063f9803919146104ea578063fee99b221461050a57600080fd5b8063715018a6146103955780638da5cb5b146103aa57806396e17852146103c8578063a4444efd146103db578063a86f9d9e146103fb57600080fd5b8063540be6a3116100f2578063540be6a3146102e75780635817b0c3146103075780635d0bd98614610335578063606b5b74146103555780636c6563f61461037557600080fd5b80630652b57a1461020357806319ab453c14610223578063343b643c146102435780633ab76e9f146102885780635075a9d4146102ba57600080fd5b366101fe5761014c6a1d1bdad95b97dd985d5b1d60aa1b600161052a565b6001600160a01b0316336001600160a01b03161415801561019757506101816a195d1a195c97dd985d5b1d60aa1b600161052a565b6001600160a01b0316336001600160a01b031614155b80156101c757506101b1647461696b6f60d81b600161052a565b6001600160a01b0316336001600160a01b031614155b80156101de57506065546001600160a01b03163314155b156101fc576040516345dd044560e11b815260040160405180910390fd5b005b600080fd5b34801561020f57600080fd5b506101fc61021e366004612b75565b610540565b34801561022f57600080fd5b506101fc61023e366004612b75565b6105c3565b34801561024f57600080fd5b5061027361025e366004612b92565b600090815260cd602052604090205460ff1690565b60405190151581526020015b60405180910390f35b34801561029457600080fd5b506097546001600160a01b03165b6040516001600160a01b03909116815260200161027f565b3480156102c657600080fd5b506102da6102d5366004612b92565b6106db565b60405161027f9190612be3565b3480156102f357600080fd5b50610273610302366004612b92565b6106e6565b34801561031357600080fd5b50610327610322366004612c0a565b6106f2565b60405190815260200161027f565b34801561034157600080fd5b50610273610350366004612b92565b610705565b34801561036157600080fd5b50610327610370366004612b92565b610718565b34801561038157600080fd5b506102a2610390366004612c4c565b610723565b3480156103a157600080fd5b506101fc61073a565b3480156103b657600080fd5b506065546001600160a01b03166102a2565b6103276103d6366004612c0a565b61074e565b3480156103e757600080fd5b506102736103f6366004612ccd565b61077c565b34801561040757600080fd5b506102a2610416366004612d1f565b61052a565b34801561042757600080fd5b506101fc610436366004612d4f565b610794565b34801561044757600080fd5b50610273610456366004612ccd565b6107b8565b34801561046757600080fd5b50604080516060808201835260008083526020808401829052928401528251808201845260ca5480825260cb546001600160a01b0390811683860190815260cc54938701938452865192835251169381019390935251928201929092520161027f565b3480156104d657600080fd5b506101fc6104e5366004612b75565b6107c7565b3480156104f657600080fd5b506101fc610505366004612db7565b610840565b34801561051657600080fd5b506101fc610525366004612d4f565b61085e565b6000610537468484610874565b90505b92915050565b610548610928565b6001600160a01b03811661056f57604051634d084d8560e11b815260040160405180910390fd5b609780546001600160a01b0319166001600160a01b0383169081179091556040519081527f399ded90cb5ed8d89ef7e76ff4af65c373f06d3bf5d7eef55f4228e7b702a18b9060200160405180910390a150565b600054610100900460ff16158080156105e35750600054600160ff909116105b806105fd5750303b1580156105fd575060005460ff166001145b6106655760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b60648201526084015b60405180910390fd5b6000805460ff191660011790558015610688576000805461ff0019166101001790555b61069182610982565b80156106d7576000805461ff0019169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b5050565b600061053a8261099b565b600061053a30836109c6565b600061053a61070083612f0d565b610aa7565b60006107113083610ad7565b5092915050565b600061053a82610b60565b6000610730848484610874565b90505b9392505050565b610742610928565b61074c6000610b9b565b565b6000610758610bed565b61076c60c93061076785612f0d565b610c46565b905061077760018055565b919050565b600061078b3086868686610f27565b95945050505050565b61079c610bed565b6107aa60c93085858561108a565b6107b360018055565b505050565b600061078b308686868661137b565b6107cf610928565b6001600160a01b0381166108345760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b606482015260840161065c565b61083d81610b9b565b50565b610848610bed565b61085560c9308484611600565b6106d760018055565b610866610bed565b6107aa60c930858585611838565b60975460405163195ac1a960e21b815260048101859052602481018490526000916001600160a01b03169063656b06a490604401602060405180830381865afa1580156108c5573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108e9919061300e565b90508115801561090057506001600160a01b038116155b1561073357604051631467050360e21b8152600481018590526024810184905260440161065c565b6065546001600160a01b0316331461074c5760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015260640161065c565b61098a611d37565b610992611d66565b61083d81611d95565b6000806109a783610b60565b80549091508060038111156109be576109be612bab565b949350505050565b604051635437cecf60e11b81526000906001600160a01b0384169063a86f9d9e906109f590849060040161302b565b602060405180830381865afa158015610a12573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a36919061300e565b604051631933b5e360e11b8152306004820152602481018490526001600160a01b0391909116906332676bc690604401602060405180830381865afa158015610a83573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610537919061304d565b600081604051602001610aba91906130ba565b604051602081830303815290604052805190602001209050919050565b600080836001600160a01b0316636c6563f68460016040518363ffffffff1660e01b8152600401610b099291906131b4565b602060405180830381865afa158015610b26573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b4a919061300e565b6001600160a01b03811615159590945092505050565b60006040518060400160405280600e81526020016d4d4553534147455f53544154555360901b81525082604051602001610aba9291906131d3565b606580546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b600260015403610c3f5760405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c00604482015260640161065c565b6002600155565b60808101516000906001600160a01b0316610c74576040516301b1868360e71b815260040160405180910390fd5b600080610c85858560600151610ad7565b91509150811580610c995750468460600151145b15610cb75760405163e822b48d60e01b815260040160405180910390fd5b60a08401516001600160a01b03161580610ce65750806001600160a01b03168460a001516001600160a01b0316145b15610d045760405163b9ad6a0f60e01b815260040160405180910390fd5b60008461012001518561010001518660e00151610d21919061320b565b610d2b919061320b565b9050348114610d4d57604051632609a19760e21b815260040160405180910390fd5b604051635437cecf60e11b81526000906001600160a01b0388169063a86f9d9e90610d7d9060019060040161321e565b602060405180830381865afa158015610d9a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610dbe919061300e565b9050610dd36001600160a01b03821683611dde565b8754886000610de18361323d565b909155508652336020870152466040870152610dfc86610aa7565b604051635437cecf60e11b81529095506001600160a01b0388169063a86f9d9e90610e2c9060009060040161302b565b602060405180830381865afa158015610e49573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e6d919061300e565b6001600160a01b03166366ca2bc0866040518263ffffffff1660e01b8152600401610e9a91815260200190565b6020604051808303816000875af1158015610eb9573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610edd9190613256565b50847f47866f7dacd4a276245be6ed543cae03c9c17eb17e6980cee28e3dd168b7f9f387604051610f0e91906130ba565b60405180910390a2505050509392505050565b60018055565b600080866001600160a01b0316636c6563f68660006040518363ffffffff1660e01b8152600401610f599291906131b4565b602060405180830381865afa158015610f76573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f9a919061300e565b604051635437cecf60e11b81529091506001600160a01b0388169063a86f9d9e90610fca9060009060040161302b565b602060405180830381865afa158015610fe7573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061100b919061300e565b6001600160a01b0316635221f61386838988886040518663ffffffff1660e01b815260040161103e95949392919061326f565b602060405180830381865afa15801561105b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061107f919061304d565b979650505050505050565b600061109c60a0850160808601612b75565b6001600160a01b0316036110c3576040516301b1868360e71b815260040160405180910390fd5b468360400135146110e75760405163e822b48d60e01b815260040160405180910390fd5b60006110f561070085612f0d565b600081815260048801602052604090205490915060ff16151560010361112e5760405163afde133560e01b815260040160405180910390fd5b61113f85828660600135868661137b565b61115c5760405163498b0b1d60e01b815260040160405180910390fd5b60008181526004870160205260408120805460ff1916600117905561118a61010086013560e087013561320b565b9050801561131f57604051635437cecf60e11b81526000906001600160a01b0388169063a86f9d9e906111c29060019060040161321e565b602060405180830381865afa1580156111df573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611203919061300e565b90506001600160a01b03811615611298576001600160a01b03811663ba0bbd9561123360a0890160808a01612b75565b6040516001600160e01b031960e084901b1681526001600160a01b03909116600482015260248101859052604401600060405180830381600087803b15801561127b57600080fd5b505af115801561128f573d6000803e3d6000fd5b5050505061131d565b60006112aa60a0880160808901612b75565b6001600160a01b03168360405160006040518083038185875af1925050503d80600081146112f4576040519150601f19603f3d011682016040523d82523d6000602084013e6112f9565b606091505b505090508061131b5760405163f6664cf160e01b815260040160405180910390fd5b505b505b817fea00c741e39d1d9ab1c6703152d71f9da09a782ed4ae128414730dadbb9bd84761135160a0880160808901612b75565b604080516001600160a01b039092168252602082018590520160405180910390a250505050505050565b600046840361139d5760405163e822b48d60e01b815260040160405180910390fd5b60008590036113bf5760405163a6407c9360e01b815260040160405180910390fd5b60006113cd83850185613359565b604051635437cecf60e11b8152647461696b6f60d81b60048201526000602482018190529192506001600160a01b0389169063a86f9d9e90604401602060405180830381865afa158015611425573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611449919061300e565b8251610100015160405163bacb386d60e01b81526001600160801b0390911660048201526001600160a01b03919091169063bacb386d90602401602060405180830381865afa1580156114a0573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906114c49190613256565b90508015806114dd575081516114d990611e94565b8114155b156114ed5760009250505061078b565b815160600151604051633632b1fb60e11b8152735075901Fdd1d57Ca754472cb94967f564bA7dc6E9163a5427462916001600160a01b038c1690636c6563f69061153e908c906000906004016131b4565b602060405180830381865afa15801561155b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061157f919061300e565b6115888b610b60565b602087015160405160e086901b6001600160e01b03191681526115b3949392916003916004016134fd565b602060405180830381865af41580156115d0573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906115f4919061304d565b98975050505050505050565b610140820135158061160f5750805b156116555761162460a0830160808401612b75565b6001600160a01b0316336001600160a01b0316146116555760405163d7f4fc9f60e01b815260040160405180910390fd5b600061166361070084612f0d565b905060016116708261099b565b600381111561168157611681612bab565b1461169f57604051631f6646b560e01b815260040160405180910390fd5b604051635437cecf60e11b81526000906001600160a01b0386169063a86f9d9e906116cf9060019060040161321e565b602060405180830381865afa1580156116ec573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611710919061300e565b90506001600160a01b0381161561178057604051630d73bb3d60e41b815261010085013560048201526001600160a01b0382169063d73bb3d090602401600060405180830381600087803b15801561176757600080fd5b505af115801561177b573d6000803e3d6000fd5b505050505b61178c8685845a611eb9565b156117a15761179c826002612011565b611830565b8215611818576117b2826003612011565b6000806117c560e0870160c08801612b75565b6001600160a01b0316146117e8576117e360e0860160c08701612b75565b6117f8565b6117f860a0860160808701612b75565b90506118126001600160a01b038216610100870135611dde565b50611830565b6118306001600160a01b038216610100860135611dde565b505050505050565b61014083013515801561186c575061185660a0840160808501612b75565b6001600160a01b0316336001600160a01b031614155b1561188a5760405163398b635960e21b815260040160405180910390fd5b468360600135146118ae5760405163e822b48d60e01b815260040160405180910390fd5b60006118bc61070085612f0d565b905060006118c98261099b565b60038111156118da576118da612bab565b146118f857604051630cfafbf960e01b815260040160405180910390fd5b6000856001600160a01b0316636c6563f6866040013560006040518363ffffffff1660e01b815260040161192d9291906131b4565b602060405180830381865afa15801561194a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061196e919061300e565b604051635437cecf60e11b81529091506001600160a01b0387169063a86f9d9e9061199e9060009060040161302b565b602060405180830381865afa1580156119bb573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906119df919061300e565b6001600160a01b0316635221f6138660400135838588886040518663ffffffff1660e01b8152600401611a1695949392919061326f565b602060405180830381865afa158015611a33573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611a57919061304d565b611a74576040516314504c7360e31b815260040160405180910390fd5b6000610120860135611a8f61010088013560e089013561320b565b611a99919061320b565b90506000876001600160a01b031663a86f9d9e60016040518263ffffffff1660e01b8152600401611aca919061321e565b602060405180830381865afa158015611ae7573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611b0b919061300e565b90506001600160a01b03811615801590611b255750600082115b15611b8557604051630d73bb3d60e41b8152600481018390526001600160a01b0382169063d73bb3d090602401600060405180830381600087803b158015611b6c57600080fd5b505af1158015611b80573d6000803e3d6000fd5b505050505b611bac60e0880135611b9d60a08a0160808b01612b75565b6001600160a01b031690611dde565b60008030611bc060c08b0160a08c01612b75565b6001600160a01b03161480611bed57506000611be260c08b0160a08c01612b75565b6001600160a01b0316145b15611c02575060029050610100880135611c79565b6000611c1460a08b0160808c01612b75565b6001600160a01b0316336001600160a01b031614611c3757896101400135611c39565b5a5b90506000611c498d8c8a85611eb9565b90508015611c5a5760029350611c76565b60019350611c766001600160a01b0386166101008d0135611dde565b50505b611c838683612011565b600080611c9660e08c0160c08d01612b75565b6001600160a01b031614611cb957611cb460e08b0160c08c01612b75565b611cc9565b611cc960a08b0160808c01612b75565b90506001600160a01b0381163303611d07576000611cec836101208d013561320b565b9050611d016001600160a01b03831682611dde565b50611d29565b611d16336101208c0135611dde565b611d296001600160a01b03821683611dde565b505050505050505050505050565b600054610100900460ff16611d5e5760405162461bcd60e51b815260040161065c90613530565b61074c61208a565b600054610100900460ff16611d8d5760405162461bcd60e51b815260040161065c90613530565b61074c6120b1565b6001600160a01b038116611dbc57604051634d084d8560e11b815260040160405180910390fd5b609780546001600160a01b0319166001600160a01b0392909216919091179055565b801580611df257506001600160a01b038216155b15611dfb575050565b6000826001600160a01b03168260405160006040518083038185875af1925050503d8060008114611e48576040519150601f19603f3d011682016040523d82523d6000602084013e611e4d565b606091505b50509050806107b35760405162461bcd60e51b8152602060048201526013602482015272115512081d1c985b9cd9995c8819985a5b1959606a1b604482015260640161065c565b600080611eaa611ea58460006120e1565b612502565b80516020909101209392505050565b600081600003611edc57604051637f0e960960e11b815260040160405180910390fd5b6040518060600160405280848152602001856020016020810190611f009190612b75565b6001600160a01b039081168252604087810135602093840152835160018a0155918301516002890180546001600160a01b0319169190921617905501516003860155611f5260c0850160a08601612b75565b6001600160a01b031682610100860135611f7061016088018861357b565b604051611f7e9291906135c1565b600060405180830381858888f193505050503d8060008114611fbc576040519150601f19603f3d011682016040523d82523d6000602084013e611fc1565b606091505b505060408051606081018252600180825260208201819052600019919092018190528782018290556002880180546001600160a01b03191690921790915560039096019590955550929392505050565b80600381111561202357612023612bab565b61202c8361099b565b600381111561203d5761203d612bab565b146106d75761204c8282612546565b817f0af4d5247f6a4028d6699afb62871a76b398da1d1a626c8a9b90e0bd5f54c73c823360405161207e9291906135d1565b60405180910390a25050565b600054610100900460ff16610f215760405162461bcd60e51b815260040161065c90613530565b600054610100900460ff166120d85760405162461bcd60e51b815260040161065c90613530565b61074c33610b9b565b6102008201516060901561214c576120fa82601161320b565b6001600160401b0381111561211157612111612dfd565b60405190808252806020026020018201604052801561214457816020015b606081526020019060019003908161212f5790505b5090506121bb565b6101e083015115612162576120fa82601061320b565b61216d82600f61320b565b6001600160401b0381111561218457612184612dfd565b6040519080825280602002602001820160405280156121b757816020015b60608152602001906001900390816121a25790505b5090505b82516121c69061256f565b816000815181106121d9576121d96135f7565b60200260200101819052506121f1836020015161256f565b81600181518110612204576122046135f7565b602002602001018190525061221c8360400151612582565b8160028151811061222f5761222f6135f7565b6020026020010181905250612247836060015161256f565b8160038151811061225a5761225a6135f7565b6020026020010181905250612272836080015161256f565b81600481518110612285576122856135f7565b602002602001018190525061229d8360a0015161256f565b816005815181106122b0576122b06135f7565b60200260200101819052506122e78360c001516040516020016122d3919061360d565b6040516020818303038152906040526125ab565b816006815181106122fa576122fa6135f7565b60200260200101819052506123128360e0015161261a565b81600781518110612325576123256135f7565b60200260200101819052506123478361010001516001600160801b031661261a565b8160088151811061235a5761235a6135f7565b6020026020010181905250612373836101200151612628565b81600981518110612386576123866135f7565b602002602001018190525061239f836101400151612628565b81600a815181106123b2576123b26135f7565b60200260200101819052506123cb836101600151612628565b81600b815181106123de576123de6135f7565b60200260200101819052506123f78361018001516125ab565b81600c8151811061240a5761240a6135f7565b6020026020010181905250612423836101a0015161256f565b81600d81518110612436576124366135f7565b602002602001018190525061246d836101c001516040516020016122d3919060c09190911b6001600160c01b031916815260080190565b81600e81518110612480576124806135f7565b6020026020010181905250826101e001516000146124c5576124a6836101e0015161261a565b81600f815181106124b9576124b96135f7565b60200260200101819052505b6102008301511561053a576124de83610200015161256f565b816010815181106124f1576124f16135f7565b602002602001018190525092915050565b6060600061250f8361263f565b905061251d815160c0612774565b8160405160200161252f929190613642565b604051602081830303815290604052915050919050565b600061255183610b60565b9050600082600381111561256757612567612bab565b909155505050565b606061053a61257d8361291c565b6125ab565b604051606082811b6bffffffffffffffffffffffff191660208301529061053a906034016122d3565b606080825160011480156125d957506080836000815181106125cf576125cf6135f7565b016020015160f81c105b156125e557508161053a565b6125f183516080612774565b83604051602001612603929190613642565b604051602081830303815290604052905092915050565b606061053a61257d836129ce565b606061053a61257d836001600160401b03166129ce565b60608151600003612660576040805160008082526020820190925290610711565b6000805b83518110156126a55783818151811061267f5761267f6135f7565b60200260200101515182612693919061320b565b915061269e8161323d565b9050612664565b6000826001600160401b038111156126bf576126bf612dfd565b6040519080825280601f01601f1916602001820160405280156126e9576020820181803683370190505b50600092509050602081015b855183101561276b576000868481518110612712576127126135f7565b60200260200101519050600060208201905061273083828451612af8565b878581518110612742576127426135f7565b60200260200101515183612756919061320b565b92505050826127649061323d565b92506126f5565b50949350505050565b60608060388410156127db57604080516001808252818301909252906020820181803683370190505090506127a98385613671565b60f81b816000815181106127bf576127bf6135f7565b60200101906001600160f81b031916908160001a905350610537565b600060015b6127ea81876136a0565b1561280d576127f88261323d565b9150612806610100826136b4565b90506127e0565b61281882600161320b565b6001600160401b0381111561282f5761282f612dfd565b6040519080825280601f01601f191660200182016040528015612859576020820181803683370190505b5092506128668583613671565b612871906037613671565b60f81b83600081518110612887576128876135f7565b60200101906001600160f81b031916908160001a905350600190505b818111612913576101006128b782846136cb565b6128c3906101006137c2565b6128cd90886136a0565b6128d791906137ce565b60f81b8382815181106128ec576128ec6135f7565b60200101906001600160f81b031916908160001a90535061290c8161323d565b90506128a3565b50509392505050565b606060008260405160200161293391815260200190565b60408051808303601f1901815260208084528383019092529250600091829160208201818036833701905050905060005b815181101561276b5783836129788161323d565b94508151811061298a5761298a6135f7565b602001015160f81c60f81b8282815181106129a7576129a76135f7565b60200101906001600160f81b031916908160001a9053506129c78161323d565b9050612964565b60606000826040516020016129e591815260200190565b604051602081830303815290604052905060005b6020811015612a3a57818181518110612a1457612a146135f7565b01602001516001600160f81b031916600003612a3a57612a338161323d565b90506129f9565b6000612a478260206136cb565b6001600160401b03811115612a5e57612a5e612dfd565b6040519080825280601f01601f191660200182016040528015612a88576020820181803683370190505b50905060005b815181101561276b578383612aa28161323d565b945081518110612ab457612ab46135f7565b602001015160f81c60f81b828281518110612ad157612ad16135f7565b60200101906001600160f81b031916908160001a905350612af18161323d565b9050612a8e565b8282825b60208110612b345781518352612b1360208461320b565b9250612b2060208361320b565b9150612b2d6020826136cb565b9050612afc565b905182516020929092036101000a6000190180199091169116179052505050565b6001600160a01b038116811461083d57600080fd5b803561077781612b55565b600060208284031215612b8757600080fd5b813561053781612b55565b600060208284031215612ba457600080fd5b5035919050565b634e487b7160e01b600052602160045260246000fd5b60048110612bdf57634e487b7160e01b600052602160045260246000fd5b9052565b6020810161053a8284612bc1565b60006101a08284031215612c0457600080fd5b50919050565b600060208284031215612c1c57600080fd5b81356001600160401b03811115612c3257600080fd5b6109be84828501612bf1565b801515811461083d57600080fd5b600080600060608486031215612c6157600080fd5b83359250602084013591506040840135612c7a81612c3e565b809150509250925092565b60008083601f840112612c9757600080fd5b5081356001600160401b03811115612cae57600080fd5b602083019150836020828501011115612cc657600080fd5b9250929050565b60008060008060608587031215612ce357600080fd5b843593506020850135925060408501356001600160401b03811115612d0757600080fd5b612d1387828801612c85565b95989497509550505050565b60008060408385031215612d3257600080fd5b823591506020830135612d4481612c3e565b809150509250929050565b600080600060408486031215612d6457600080fd5b83356001600160401b0380821115612d7b57600080fd5b612d8787838801612bf1565b94506020860135915080821115612d9d57600080fd5b50612daa86828701612c85565b9497909650939450505050565b60008060408385031215612dca57600080fd5b82356001600160401b03811115612de057600080fd5b612dec85828601612bf1565b9250506020830135612d4481612c3e565b634e487b7160e01b600052604160045260246000fd5b6040516101a081016001600160401b0381118282101715612e3657612e36612dfd565b60405290565b604080519081016001600160401b0381118282101715612e3657612e36612dfd565b60405161022081016001600160401b0381118282101715612e3657612e36612dfd565b600082601f830112612e9257600080fd5b81356001600160401b0380821115612eac57612eac612dfd565b604051601f8301601f19908116603f01168101908282118183101715612ed457612ed4612dfd565b81604052838152866020858801011115612eed57600080fd5b836020870160208301376000602085830101528094505050505092915050565b60006101a08236031215612f2057600080fd5b612f28612e13565b82358152612f3860208401612b6a565b60208201526040830135604082015260608301356060820152612f5d60808401612b6a565b6080820152612f6e60a08401612b6a565b60a0820152612f7f60c08401612b6a565b60c082015260e08381013590820152610100808401359082015261012080840135908201526101408084013590820152610160808401356001600160401b0380821115612fcb57600080fd5b612fd736838801612e81565b83850152610180925082860135915080821115612ff357600080fd5b5061300036828701612e81565b918301919091525092915050565b60006020828403121561302057600080fd5b815161053781612b55565b6d7369676e616c5f7365727669636560901b8152901515602082015260400190565b60006020828403121561305f57600080fd5b815161053781612c3e565b60005b8381101561308557818101518382015260200161306d565b50506000910152565b600081518084526130a681602086016020860161306a565b601f01601f19169290920160200192915050565b6020815281516020820152600060208301516130e160408401826001600160a01b03169052565b506040830151606083015260608301516080830152608083015161311060a08401826001600160a01b03169052565b5060a08301516001600160a01b03811660c08401525060c08301516001600160a01b03811660e08401525060e0830151610100838101919091528301516101208084019190915283015161014080840191909152830151610160808401919091528301516101a061018080850182905261318e6101c086018461308e565b90860151858203601f1901838701529092506131aa838261308e565b9695505050505050565b9182526562726964676560d01b60208301521515604082015260600190565b600083516131e581846020880161306a565b9190910191825250602001919050565b634e487b7160e01b600052601160045260246000fd5b8082018082111561053a5761053a6131f5565b6a195d1a195c97dd985d5b1d60aa1b8152901515602082015260400190565b60006001820161324f5761324f6131f5565b5060010190565b60006020828403121561326857600080fd5b5051919050565b8581526001600160a01b0385166020820152604081018490526080606082018190528101829052818360a0830137600081830160a090810191909152601f909201601f19160101949350505050565b600082601f8301126132cf57600080fd5b6040516101008082018281106001600160401b03821117156132f3576132f3612dfd565b6040528301818582111561330657600080fd5b845b82811015613320578035825260209182019101613308565b509195945050505050565b80356001600160801b038116811461077757600080fd5b80356001600160401b038116811461077757600080fd5b60006020828403121561336b57600080fd5b81356001600160401b038082111561338257600080fd5b908301906040828603121561339657600080fd5b61339e612e3c565b8235828111156133ad57600080fd5b830161030081880312156133c057600080fd5b6133c8612e5e565b81358152602082013560208201526133e260408301612b6a565b6040820152606082013560608201526080820135608082015260a082013560a08201526134128860c084016132be565b60c08201526101c08083013560e08301526101e061343181850161332b565b610100840152610200613445818601613342565b6101208501526134586102208601613342565b61014085015261346b6102408601613342565b6101608501526102608501358781111561348457600080fd5b6134908c828801612e81565b610180860152506102808501356101a08501526134b06102a08601613342565b838501526102c0850135828501526102e08501358185015250505080835250506020830135828111156134e257600080fd5b6134ee87828601612e81565b60208301525095945050505050565b85815260018060a01b038516602082015283604082015282606082015260a06080820152600061107f60a083018461308e565b6020808252602b908201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960408201526a6e697469616c697a696e6760a81b606082015260800190565b6000808335601e1984360301811261359257600080fd5b8301803591506001600160401b038211156135ac57600080fd5b602001915036819003821315612cc657600080fd5b8183823760009101908152919050565b604081016135df8285612bc1565b6001600160a01b039290921660209190910152919050565b634e487b7160e01b600052603260045260246000fd5b60008183825b6008811015613632578151835260209283019290910190600101613613565b5050506101008201905092915050565b6000835161365481846020880161306a565b83519083019061366881836020880161306a565b01949350505050565b60ff818116838216019081111561053a5761053a6131f5565b634e487b7160e01b600052601260045260246000fd5b6000826136af576136af61368a565b500490565b808202811582820484141761053a5761053a6131f5565b8181038181111561053a5761053a6131f5565b600181815b808511156137195781600019048211156136ff576136ff6131f5565b8085161561370c57918102915b93841c93908002906136e3565b509250929050565b6000826137305750600161053a565b8161373d5750600061053a565b8160018114613753576002811461375d57613779565b600191505061053a565b60ff84111561376e5761376e6131f5565b50506001821b61053a565b5060208310610133831016604e8410600b841016171561379c575081810a61053a565b6137a683836136de565b80600019048211156137ba576137ba6131f5565b029392505050565b60006105378383613721565b6000826137dd576137dd61368a565b50069056fea26469706673582212209944d85d0cc8409987bf496ae9ba9d199c3992cdf3a3f5d304737e8c526b4f3c64736f6c63430008120033", + "balance": "0x0" + }, + "0x1000777700000000000000000000000000000004": { + "contractName": "BridgeProxy", + "storage": { + "0x0000000000000000000000000000000000000000000000000000000000000000": "0x0000000000000000000000000000000000000000000000000000000000000001", + "0x0000000000000000000000000000000000000000000000000000000000000001": "0x0000000000000000000000000000000000000000000000000000000000000001", + "0x0000000000000000000000000000000000000000000000000000000000000065": "0x00000000000000000000000019b4f9c381c7927fe33d853e48b560141a380c44", + "0x0000000000000000000000000000000000000000000000000000000000000097": "0x0000000000000000000000001000777700000000000000000000000000000006", + "0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103": "0x113cE23c9e0cc50F4D41d7cE6DA02dCAFf8BFF85", + "0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc": "0x0000777700000000000000000000000000000004" + }, + "code": "0x60806040526004361061004e5760003560e01c80633659cfe6146100655780634f1ef286146100855780635c60da1b146100985780638f283970146100c9578063f851a440146100e95761005d565b3661005d5761005b6100fe565b005b61005b6100fe565b34801561007157600080fd5b5061005b6100803660046106c2565b610118565b61005b6100933660046106dd565b610155565b3480156100a457600080fd5b506100ad6101bc565b6040516001600160a01b03909116815260200160405180910390f35b3480156100d557600080fd5b5061005b6100e43660046106c2565b6101ed565b3480156100f557600080fd5b506100ad61020d565b610106610269565b6101166101116102fe565b610308565b565b61012061032c565b6001600160a01b0316330361014d5761014a8160405180602001604052806000815250600061035f565b50565b61014a6100fe565b61015d61032c565b6001600160a01b031633036101b4576101af8383838080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152506001925061035f915050565b505050565b6101af6100fe565b60006101c661032c565b6001600160a01b031633036101e2576101dd6102fe565b905090565b6101ea6100fe565b90565b6101f561032c565b6001600160a01b0316330361014d5761014a8161038a565b600061021761032c565b6001600160a01b031633036101e2576101dd61032c565b606061025383836040518060600160405280602781526020016107d4602791396103de565b9392505050565b6001600160a01b03163b151590565b61027161032c565b6001600160a01b031633036101165760405162461bcd60e51b815260206004820152604260248201527f5472616e73706172656e745570677261646561626c6550726f78793a2061646d60448201527f696e2063616e6e6f742066616c6c6261636b20746f2070726f78792074617267606482015261195d60f21b608482015260a4015b60405180910390fd5b60006101dd610456565b3660008037600080366000845af43d6000803e808015610327573d6000f35b3d6000fd5b60007fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035b546001600160a01b0316919050565b6103688361047e565b6000825111806103755750805b156101af57610384838361022e565b50505050565b7f7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f6103b361032c565b604080516001600160a01b03928316815291841660208301520160405180910390a161014a816104be565b6060600080856001600160a01b0316856040516103fb9190610784565b600060405180830381855af49150503d8060008114610436576040519150601f19603f3d011682016040523d82523d6000602084013e61043b565b606091505b509150915061044c86838387610567565b9695505050505050565b60007f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc610350565b610487816105e8565b6040516001600160a01b038216907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b90600090a250565b6001600160a01b0381166105235760405162461bcd60e51b815260206004820152602660248201527f455243313936373a206e65772061646d696e20697320746865207a65726f206160448201526564647265737360d01b60648201526084016102f5565b807fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035b80546001600160a01b0319166001600160a01b039290921691909117905550565b606083156105d65782516000036105cf576001600160a01b0385163b6105cf5760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e747261637400000060448201526064016102f5565b50816105e0565b6105e0838361067c565b949350505050565b6001600160a01b0381163b6106555760405162461bcd60e51b815260206004820152602d60248201527f455243313936373a206e657720696d706c656d656e746174696f6e206973206e60448201526c1bdd08184818dbdb9d1c9858dd609a1b60648201526084016102f5565b807f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc610546565b81511561068c5781518083602001fd5b8060405162461bcd60e51b81526004016102f591906107a0565b80356001600160a01b03811681146106bd57600080fd5b919050565b6000602082840312156106d457600080fd5b610253826106a6565b6000806000604084860312156106f257600080fd5b6106fb846106a6565b9250602084013567ffffffffffffffff8082111561071857600080fd5b818601915086601f83011261072c57600080fd5b81358181111561073b57600080fd5b87602082850101111561074d57600080fd5b6020830194508093505050509250925092565b60005b8381101561077b578181015183820152602001610763565b50506000910152565b60008251610796818460208701610760565b9190910192915050565b60208152600082518060208401526107bf816040850160208701610760565b601f01601f1916919091016040019291505056fe416464726573733a206c6f772d6c6576656c2064656c65676174652063616c6c206661696c6564a2646970667358221220f44b4bd0f73d4a6c872717d3b99f5935a2080af0980894ed447890241a743cdb64736f6c63430008120033", + "balance": "0x0" + }, + "0x0000777700000000000000000000000000000002": { + "contractName": "ProxiedTokenVault", + "storage": {}, + "code": "0x6080604052600436106100e85760003560e01c8063780b64f01161008a578063a86f9d9e11610059578063a86f9d9e146102ca578063c287e578146102ea578063ee1490b21461032a578063f2fde38b1461033d57600080fd5b8063780b64f0146101fc5780638da5cb5b1461025b5780639754149b146102795780639aa8605c1461029957600080fd5b80633ab76e9f116100c65780633ab76e9f1461014f57806367090ccf146101865780636c6563f6146101c7578063715018a6146101e757600080fd5b80630652b57a146100ed5780630c6fab821461010f57806319ab453c1461012f575b600080fd5b3480156100f957600080fd5b5061010d610108366004611fe4565b61035d565b005b34801561011b57600080fd5b5061010d61012a366004612001565b6103e0565b34801561013b57600080fd5b5061010d61014a366004611fe4565b6105f7565b34801561015b57600080fd5b506097546001600160a01b03165b6040516001600160a01b0390911681526020015b60405180910390f35b34801561019257600080fd5b506101696101a1366004612070565b60cb6020908152600092835260408084209091529082529020546001600160a01b031681565b3480156101d357600080fd5b506101696101e23660046120ae565b61070f565b3480156101f357600080fd5b5061010d610726565b34801561020857600080fd5b5061023c6102173660046120e7565b60cc60205260009081526040902080546001909101546001600160a01b039091169082565b604080516001600160a01b03909316835260208301919091520161017d565b34801561026757600080fd5b506065546001600160a01b0316610169565b34801561028557600080fd5b5061010d610294366004612100565b61073a565b3480156102a557600080fd5b506102b96102b4366004611fe4565b610a88565b60405161017d9594939291906121f0565b3480156102d657600080fd5b506101696102e5366004612241565b610bd9565b3480156102f657600080fd5b5061031a610305366004611fe4565b60c96020526000908152604090205460ff1681565b604051901515815260200161017d565b61010d6103383660046122d5565b610bef565b34801561034957600080fd5b5061010d610358366004611fe4565b61141f565b610365611498565b6001600160a01b03811661038c57604051634d084d8560e11b815260040160405180910390fd5b609780546001600160a01b0319166001600160a01b0383169081179091556040519081527f399ded90cb5ed8d89ef7e76ff4af65c373f06d3bf5d7eef55f4228e7b702a18b9060200160405180910390a150565b6103e86114f2565b6562726964676560d01b6103fd816000610bd9565b6001600160a01b0316336001600160a01b03161461042e57604051630d85cccf60e11b815260040160405180910390fd5b6000336001600160a01b031663d0496d6a6040518163ffffffff1660e01b8152600401606060405180830381865afa15801561046e573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061049291906123b4565b90506104b281604001516a1d1bdad95b97dd985d5b1d60aa1b600061070f565b6001600160a01b031681602001516001600160a01b0316146104e7576040516320258b8760e21b815260040160405180910390fd5b60004687350361051c576105016040880160208901611fe4565b90506105176001600160a01b038216868661154b565b61058c565b610525876115ae565b6040516342e91bb360e01b81526001600160a01b03878116600483015260248201879052919250908216906342e91bb390604401600060405180830381600087803b15801561057357600080fd5b505af1158015610587573d6000803e3d6000fd5b505050505b815160408084015181519081526001600160a01b0384811660208301529181018790528188169291891691907fe5da926519fc972010fe65b35c1e3339e6dc72b35ffaec203999c2a2a2593eac9060600160405180910390a45050506105f160018055565b50505050565b600054610100900460ff16158080156106175750600054600160ff909116105b806106315750303b158015610631575060005460ff166001145b6106995760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b60648201526084015b60405180910390fd5b6000805460ff1916600117905580156106bc576000805461ff0019166101001790555b6106c58261160d565b801561070b576000805461ff0019169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b5050565b600061071c848484611626565b90505b9392505050565b61072e611498565b61073860006116da565b565b6107426114f2565b600061075460a0850160808601611fe4565b6001600160a01b03160361077b576040516372b41cdf60e01b815260040160405180910390fd5b4683604001351461079f576040516348bc100560e01b815260040160405180910390fd5b60006107b56562726964676560d01b6000610bd9565b90506000816001600160a01b0316635817b0c3866040518263ffffffff1660e01b81526004016107e5919061248c565b602060405180830381865afa158015610802573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061082691906125aa565b600081815260cc6020526040902080546001909101549192506001600160a01b0316908161086757604051637c6addb760e01b815260040160405180910390fd5b60405163ce70f39b60e01b81526001600160a01b0385169063ce70f39b9061089d90869060608c0135908b908b906004016125c3565b602060405180830381865afa1580156108ba573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108de91906125ed565b6108fb576040516308ba49e560e31b815260040160405180910390fd5b6040805180820182526000808252602080830182815287835260cc909152929020905181546001600160a01b0319166001600160a01b0390911617815590516001909101558015610a0f576001600160a01b038216600090815260c9602052604090205460ff16156109eb576001600160a01b0382166342e91bb361098660a08a0160808b01611fe4565b6040516001600160e01b031960e084901b1681526001600160a01b03909116600482015260248101849052604401600060405180830381600087803b1580156109ce57600080fd5b505af11580156109e2573d6000803e3d6000fd5b50505050610a0f565b610a0f6109fe60a0890160808a01611fe4565b6001600160a01b038416908361154b565b610a1f60a0880160808901611fe4565b6001600160a01b0316837fc5d9f7cd7998e24ecf12ad69eca9339764e2cb13788d5d9616f502601b219af68484604051610a6e9291906001600160a01b03929092168252602082015260400190565b60405180910390a350505050610a8360018055565b505050565b60ca6020526000908152604090208054600182015460028301805492936001600160a01b03831693600160a01b90930460ff1692909190610ac89061260a565b80601f0160208091040260200160405190810160405280929190818152602001828054610af49061260a565b8015610b415780601f10610b1657610100808354040283529160200191610b41565b820191906000526020600020905b815481529060010190602001808311610b2457829003601f168201915b505050505090806003018054610b569061260a565b80601f0160208091040260200160405190810160405280929190818152602001828054610b829061260a565b8015610bcf5780601f10610ba457610100808354040283529160200191610bcf565b820191906000526020600020905b815481529060010190602001808311610bb257829003601f168201915b5050505050905085565b6000610be6468484611626565b90505b92915050565b610bf76114f2565b6001600160a01b0387161580610c375750610c22886a1d1bdad95b97dd985d5b1d60aa1b600061070f565b6001600160a01b0316876001600160a01b0316145b15610c5557604051634694641b60e01b815260040160405180910390fd5b6001600160a01b038616610c7c57604051637c6addb760e01b815260040160405180910390fd5b84600003610c9c5760405162af849960e11b815260040160405180910390fd5b6040805160a08101825260008082526020820181905291810191909152606080820181905260808201526001600160a01b038716600090815260c9602052604081205460ff1615610ef357604051630ef7c31560e31b8152336004820152602481018890526001600160a01b038916906377be18a890604401600060405180830381600087803b158015610d2f57600080fd5b505af1158015610d43573d6000803e3d6000fd5b505050506001600160a01b03888116600090815260ca6020908152604091829020825160a08101845281548152600182015494851692810192909252600160a01b90930460ff1691810191909152600282018054919291606084019190610da99061260a565b80601f0160208091040260200160405190810160405280929190818152602001828054610dd59061260a565b8015610e225780601f10610df757610100808354040283529160200191610e22565b820191906000526020600020905b815481529060010190602001808311610e0557829003601f168201915b50505050508152602001600382018054610e3b9061260a565b80601f0160208091040260200160405190810160405280929190818152602001828054610e679061260a565b8015610eb45780601f10610e8957610100808354040283529160200191610eb4565b820191906000526020600020905b815481529060010190602001808311610e9757829003601f168201915b5050509190925250505060208101519092506001600160a01b0316610eec57604051633e45a03560e21b815260040160405180910390fd5b5085611153565b60008890506040518060a001604052804681526020018a6001600160a01b03168152602001826001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa158015610f56573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f7a9190612653565b60ff168152602001826001600160a01b03166395d89b416040518163ffffffff1660e01b8152600401600060405180830381865afa158015610fc0573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052610fe89190810190612670565b8152602001826001600160a01b03166306fdde036040518163ffffffff1660e01b8152600401600060405180830381865afa15801561102b573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526110539190810190612670565b90526040516370a0823160e01b81523060048201529093506000906001600160a01b038316906370a0823190602401602060405180830381865afa15801561109f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110c391906125aa565b90506110da6001600160a01b03831633308c61172c565b6040516370a0823160e01b815230600482015281906001600160a01b038416906370a0823190602401602060405180830381865afa158015611120573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061114491906125aa565b61114e91906126e7565b925050505b6111e2604051806101a001604052806000815260200160006001600160a01b03168152602001600081526020016000815260200160006001600160a01b0316815260200160006001600160a01b0316815260200160006001600160a01b031681526020016000815260200160008152602001600081526020016000815260200160608152602001606081525090565b606081018b90523360808201526112098b6a1d1bdad95b97dd985d5b1d60aa1b600061070f565b6001600160a01b031660a08201526080810151604051630637d5c160e11b9161123b918691908e908790602401612708565b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b0319909316929092179091526101608201526101408101879052610120810186905261128d86346126e7565b60e08201526001600160a01b03851660c0820152610180810184905260006112be6562726964676560d01b82610bd9565b6001600160a01b03166396e1785234846040518363ffffffff1660e01b81526004016112ea91906127a0565b60206040518083038185885af1158015611308573d6000803e3d6000fd5b50505050506040513d601f19601f8201168201806040525081019061132d91906125aa565b905060405180604001604052808b6001600160a01b031681526020018481525060cc600083815260200190815260200160002060008201518160000160006101000a8154816001600160a01b0302191690836001600160a01b03160217905550602082015181600101559050508a6001600160a01b031682608001516001600160a01b0316827f325cab7553038374e17f39bb45e2a2c90f66c6a52798cb5f95c20d94c11c95e28f8e88604051611400939291909283526001600160a01b03919091166020830152604082015260600190565b60405180910390a45050505061141560018055565b5050505050505050565b611427611498565b6001600160a01b03811661148c5760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b6064820152608401610690565b611495816116da565b50565b6065546001600160a01b031633146107385760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610690565b6002600154036115445760405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c006044820152606401610690565b6002600155565b6040516001600160a01b038316602482015260448101829052610a8390849063a9059cbb60e01b906064015b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b031990931692909217909152611764565b8035600090815260cb602090815260408083208392909183916115d5918701908701611fe4565b6001600160a01b03908116825260208201929092526040016000205416905080610be95761160283611836565b61071f565b60018055565b611615611abb565b61161d611aea565b61149581611b19565b60975460405163195ac1a960e21b815260048101859052602481018490526000916001600160a01b03169063656b06a490604401602060405180830381865afa158015611677573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061169b9190612890565b9050811580156116b257506001600160a01b038116155b1561071f57604051631467050360e21b81526004810185905260248101849052604401610690565b606580546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b6040516001600160a01b03808516602483015283166044820152606481018290526105f19085906323b872dd60e01b90608401611577565b60006117b9826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b0316611b629092919063ffffffff16565b805190915015610a8357808060200190518101906117d791906125ed565b610a835760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6044820152691bdd081cdd58d8d9595960b21b6064820152608401610690565b60006118af81833561184e6040860160208701611fe4565b60405161187192916001600160a01b031690602001918252602082015260400190565b604051602081830303815290604052805190602001206040518060200161189790611fb2565b601f1982820381018352601f90910116604052611b71565b6097549091506001600160a01b0380831691636c0db62b91166118d86040860160208701611fe4565b85356118ea60608801604089016128ad565b6118f760608901896128ca565b61190460808b018b6128ca565b61190e8c35611c75565b60405160200161192093929190612911565b6040516020818303038152906040526040518863ffffffff1660e01b8152600401611951979695949392919061295a565b600060405180830381600087803b15801561196b57600080fd5b505af115801561197f573d6000803e3d6000fd5b5050506001600160a01b038216600090815260c960209081526040808320805460ff1916600117905560ca90915290208391506119bc8282612ac6565b50508135600090815260cb602090815260408083208493909290916119e691908701908701611fe4565b6001600160a01b03166001600160a01b0316815260200190815260200160002060006101000a8154816001600160a01b0302191690836001600160a01b03160217905550806001600160a01b0316826020016020810190611a479190611fe4565b6001600160a01b031683357f9e465b29e576a3e01584e31d607353f21b80c055e813af907c0a495f6cf4f7bc611a8060608701876128ca565b611a8d60808901896128ca565b611a9d60608b0160408c016128ad565b604051611aae959493929190612b4d565b60405180910390a4919050565b600054610100900460ff16611ae25760405162461bcd60e51b815260040161069090612b8a565b610738611d08565b600054610100900460ff16611b115760405162461bcd60e51b815260040161069090612b8a565b610738611d2f565b6001600160a01b038116611b4057604051634d084d8560e11b815260040160405180910390fd5b609780546001600160a01b0319166001600160a01b0392909216919091179055565b606061071c8484600085611d5f565b600083471015611bc35760405162461bcd60e51b815260206004820152601d60248201527f437265617465323a20696e73756666696369656e742062616c616e63650000006044820152606401610690565b8151600003611c145760405162461bcd60e51b815260206004820181905260248201527f437265617465323a2062797465636f6465206c656e677468206973207a65726f6044820152606401610690565b8282516020840186f590506001600160a01b03811661071f5760405162461bcd60e51b815260206004820152601960248201527f437265617465323a204661696c6564206f6e206465706c6f79000000000000006044820152606401610690565b60606000611c8283611e3c565b600101905060008167ffffffffffffffff811115611ca257611ca2612266565b6040519080825280601f01601f191660200182016040528015611ccc576020820181803683370190505b5090508181016020015b600019016f181899199a1a9b1b9c1cb0b131b232b360811b600a86061a8153600a8504945084611cd657509392505050565b600054610100900460ff166116075760405162461bcd60e51b815260040161069090612b8a565b600054610100900460ff16611d565760405162461bcd60e51b815260040161069090612b8a565b610738336116da565b606082471015611dc05760405162461bcd60e51b815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f6044820152651c8818d85b1b60d21b6064820152608401610690565b600080866001600160a01b03168587604051611ddc9190612bd5565b60006040518083038185875af1925050503d8060008114611e19576040519150601f19603f3d011682016040523d82523d6000602084013e611e1e565b606091505b5091509150611e2f87838387611f14565b925050505b949350505050565b60008072184f03e93ff9f4daa797ed6e38ed64bf6a1f0160401b8310611e7b5772184f03e93ff9f4daa797ed6e38ed64bf6a1f0160401b830492506040015b6d04ee2d6d415b85acef81000000008310611ea7576d04ee2d6d415b85acef8100000000830492506020015b662386f26fc100008310611ec557662386f26fc10000830492506010015b6305f5e1008310611edd576305f5e100830492506008015b6127108310611ef157612710830492506004015b60648310611f03576064830492506002015b600a8310610be95760010192915050565b60608315611f83578251600003611f7c576001600160a01b0385163b611f7c5760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610690565b5081611e34565b611e348383815115611f985781518083602001fd5b8060405162461bcd60e51b81526004016106909190612bf1565b6116ce80612c0583390190565b6001600160a01b038116811461149557600080fd5b8035611fdf81611fbf565b919050565b600060208284031215611ff657600080fd5b813561071f81611fbf565b6000806000806080858703121561201757600080fd5b843567ffffffffffffffff81111561202e57600080fd5b850160a0818803121561204057600080fd5b9350602085013561205081611fbf565b9250604085013561206081611fbf565b9396929550929360600135925050565b6000806040838503121561208357600080fd5b82359150602083013561209581611fbf565b809150509250929050565b801515811461149557600080fd5b6000806000606084860312156120c357600080fd5b833592506020840135915060408401356120dc816120a0565b809150509250925092565b6000602082840312156120f957600080fd5b5035919050565b60008060006040848603121561211557600080fd5b833567ffffffffffffffff8082111561212d57600080fd5b908501906101a0828803121561214257600080fd5b9093506020850135908082111561215857600080fd5b818601915086601f83011261216c57600080fd5b81358181111561217b57600080fd5b87602082850101111561218d57600080fd5b6020830194508093505050509250925092565b60005b838110156121bb5781810151838201526020016121a3565b50506000910152565b600081518084526121dc8160208601602086016121a0565b601f01601f19169290920160200192915050565b8581526001600160a01b038516602082015260ff8416604082015260a060608201819052600090612223908301856121c4565b828103608084015261223581856121c4565b98975050505050505050565b6000806040838503121561225457600080fd5b823591506020830135612095816120a0565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f1916810167ffffffffffffffff811182821017156122a5576122a5612266565b604052919050565b600067ffffffffffffffff8211156122c7576122c7612266565b50601f01601f191660200190565b600080600080600080600080610100898b0312156122f257600080fd5b88359750602089013561230481611fbf565b9650604089013561231481611fbf565b9550606089013594506080890135935060a0890135925060c089013561233981611fbf565b915060e089013567ffffffffffffffff81111561235557600080fd5b8901601f81018b1361236657600080fd5b8035612379612374826122ad565b61227c565b8181528c602083850101111561238e57600080fd5b816020840160208301376000602083830101528093505050509295985092959890939650565b6000606082840312156123c657600080fd5b6040516060810181811067ffffffffffffffff821117156123e9576123e9612266565b6040528251815260208301516123fe81611fbf565b60208201526040928301519281019290925250919050565b6000808335601e1984360301811261242d57600080fd5b830160208101925035905067ffffffffffffffff81111561244d57600080fd5b80360382131561245c57600080fd5b9250929050565b81835281816020850137506000828201602090810191909152601f909101601f19169091010190565b602081528135602082015260006124a560208401611fd4565b6001600160a01b03811660408401525060408301356060830152606083013560808301526124d560808401611fd4565b6001600160a01b03811660a0840152506124f160a08401611fd4565b6001600160a01b03811660c08401525061250d60c08401611fd4565b6001600160a01b03811660e08401525061010060e08401358184015261012081850135818501526101409150808501358285015250610160818501358185015261255981860186612416565b925090506101a061018081818701526125776101c087018585612463565b935061258581880188612416565b878603601f1901848901529350905061259f848483612463565b979650505050505050565b6000602082840312156125bc57600080fd5b5051919050565b8481528360208201526060604082015260006125e3606083018486612463565b9695505050505050565b6000602082840312156125ff57600080fd5b815161071f816120a0565b600181811c9082168061261e57607f821691505b60208210810361263e57634e487b7160e01b600052602260045260246000fd5b50919050565b60ff8116811461149557600080fd5b60006020828403121561266557600080fd5b815161071f81612644565b60006020828403121561268257600080fd5b815167ffffffffffffffff81111561269957600080fd5b8201601f810184136126aa57600080fd5b80516126b8612374826122ad565b8181528560208385010111156126cd57600080fd5b6126de8260208301602086016121a0565b95945050505050565b81810381811115610be957634e487b7160e01b600052601160045260246000fd5b60808152845160808201526000602086015160018060a01b0380821660a085015260ff60408901511660c08501526060880151915060a060e08501526127526101208501836121c4565b91506080880151607f198584030161010086015261277083826121c4565b9188166020860152506001600160a01b038616604085015291506127919050565b82606083015295945050505050565b6020815281516020820152600060208301516127c760408401826001600160a01b03169052565b50604083015160608301526060830151608083015260808301516127f660a08401826001600160a01b03169052565b5060a08301516001600160a01b03811660c08401525060c08301516001600160a01b03811660e08401525060e0830151610100838101919091528301516101208084019190915283015161014080840191909152830151610160808401919091528301516101a06101808085018290526128746101c08601846121c4565b90860151858203601f1901838701529092506125e383826121c4565b6000602082840312156128a257600080fd5b815161071f81611fbf565b6000602082840312156128bf57600080fd5b813561071f81612644565b6000808335601e198436030181126128e157600080fd5b83018035915067ffffffffffffffff8211156128fc57600080fd5b60200191503681900382131561245c57600080fd5b8284823760008382016b050c4e4d2c8cecac9e13f19160a31b8152835161293f81600c8401602088016121a0565b602960f81b600c9290910191820152600d0195945050505050565b6001600160a01b038881168252871660208201526040810186905260ff8516606082015260c0608082018190526000906129979083018587612463565b82810360a08401526129a981856121c4565b9a9950505050505050505050565b601f821115610a8357600081815260208120601f850160051c810160208610156129de5750805b601f850160051c820191505b818110156129fd578281556001016129ea565b505050505050565b67ffffffffffffffff831115612a1d57612a1d612266565b612a3183612a2b835461260a565b836129b7565b6000601f841160018114612a655760008515612a4d5750838201355b600019600387901b1c1916600186901b178355612abf565b600083815260209020601f19861690835b82811015612a965786850135825560209485019460019092019101612a76565b5086821015612ab35760001960f88860031b161c19848701351681555b505060018560011b0183555b5050505050565b81358155600181016020830135612adc81611fbf565b81546040850135612aec81612644565b60ff60a01b60a09190911b166001600160a01b03929092166001600160a81b03199190911617179055612b2260608301836128ca565b612b30818360028601612a05565b5050612b3f60808301836128ca565b6105f1818360038601612a05565b606081526000612b61606083018789612463565b8281036020840152612b74818688612463565b91505060ff831660408301529695505050505050565b6020808252602b908201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960408201526a6e697469616c697a696e6760a81b606082015260800190565b60008251612be78184602087016121a0565b9190910192915050565b602081526000610be660208301846121c456fe608060405234801561001057600080fd5b506116ae806100206000396000f3fe608060405234801561001057600080fd5b50600436106101585760003560e01c80636c6563f6116100c357806395d89b411161007c57806395d89b4114610305578063a457c2d71461030d578063a86f9d9e14610320578063a9059cbb14610333578063dd62ed3e14610346578063f2fde38b1461035957600080fd5b80636c6563f61461028a57806370a082311461029d578063715018a6146102c657806377be18a8146102ce5780637cf8ed0d146102e15780638da5cb5b146102f457600080fd5b8063395093511161011557806339509351146101ed5780633ab76e9f1461020057806342e91bb31461022557806349d126051461023857806367e828bf146102415780636c0db62b1461027757600080fd5b80630652b57a1461015d57806306fdde0314610172578063095ea7b31461019057806318160ddd146101b357806323b872dd146101c5578063313ce567146101d8575b600080fd5b61017061016b3660046111d3565b61036c565b005b61017a6103ef565b60405161018791906111f0565b60405180910390f35b6101a361019e36600461123e565b610481565b6040519015158152602001610187565b60cb545b604051908152602001610187565b6101a36101d336600461126a565b61049b565b60fd5460405160ff9091168152602001610187565b6101a36101fb36600461123e565b6104db565b6097546001600160a01b03165b6040516001600160a01b039091168152602001610187565b61017061023336600461123e565b6104fd565b6101b760fc5481565b61025860fb5460fc546001600160a01b0390911691565b604080516001600160a01b039093168352602083019190915201610187565b61017061028536600461134e565b61059a565b61020d61029836600461140d565b610740565b6101b76102ab3660046111d3565b6001600160a01b0316600090815260c9602052604090205490565b61017061074d565b6101706102dc36600461123e565b610761565b60fb5461020d906001600160a01b031681565b6065546001600160a01b031661020d565b61017a6107f1565b6101a361031b36600461123e565b610800565b61020d61032e366004611442565b610886565b6101a361034136600461123e565b610893565b6101b761035436600461146e565b6108c8565b6101706103673660046111d3565b6108f3565b61037461096c565b6001600160a01b03811661039b57604051634d084d8560e11b815260040160405180910390fd5b609780546001600160a01b0319166001600160a01b0383169081179091556040519081527f399ded90cb5ed8d89ef7e76ff4af65c373f06d3bf5d7eef55f4228e7b702a18b9060200160405180910390a150565b606060cc80546103fe906114a7565b80601f016020809104026020016040519081016040528092919081815260200182805461042a906114a7565b80156104775780601f1061044c57610100808354040283529160200191610477565b820191906000526020600020905b81548152906001019060200180831161045a57829003601f168201915b5050505050905090565b60003361048f8185856109c6565b60019150505b92915050565b6000306001600160a01b038416036104c6576040516319a6f37760e21b815260040160405180910390fd5b6104d1848484610aeb565b90505b9392505050565b60003361048f8185856104ee83836108c8565b6104f891906114e1565b6109c6565b6a1d1bdad95b97dd985d5b1d60aa1b610517816000610886565b6001600160a01b0316336001600160a01b03161461054857604051630d85cccf60e11b815260040160405180910390fd5b6105528383610b04565b826001600160a01b03167f397b33b307fc137878ebfc75b295289ec0ee25a31bb5bf034f33256fe8ea2aa68360405161058d91815260200190565b60405180910390a2505050565b600054610100900460ff16158080156105ba5750600054600160ff909116105b806105d45750303b1580156105d4575060005460ff166001145b61063c5760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b60648201526084015b60405180910390fd5b6000805460ff19166001179055801561065f576000805461ff0019166101001790555b6001600160a01b0386161580610673575084155b8061067d57504685145b8061068757508251155b8061069157508151155b156106af576040516301e25ab360e71b815260040160405180910390fd5b6106b887610bc6565b6106c28284610bdf565b60fb80546001600160a01b0319166001600160a01b03881617905560fc85905560fd805460ff191660ff86161790558015610737576000805461ff0019169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b50505050505050565b60006104d1848484610c10565b61075561096c565b61075f6000610cc4565b565b6a1d1bdad95b97dd985d5b1d60aa1b61077b816000610886565b6001600160a01b0316336001600160a01b0316146107ac57604051630d85cccf60e11b815260040160405180910390fd5b6107b68383610d16565b826001600160a01b03167f9b5b9a05e4726d8bb959f1440e05c6b8109443f2083bc4e386237d76545265538360405161058d91815260200190565b606060cd80546103fe906114a7565b6000338161080e82866108c8565b90508381101561086e5760405162461bcd60e51b815260206004820152602560248201527f45524332303a2064656372656173656420616c6c6f77616e63652062656c6f77604482015264207a65726f60d81b6064820152608401610633565b61087b82868684036109c6565b506001949350505050565b60006104d4468484610c10565b6000306001600160a01b038416036108be576040516319a6f37760e21b815260040160405180910390fd5b6104d48383610e47565b6001600160a01b03918216600090815260ca6020908152604080832093909416825291909152205490565b6108fb61096c565b6001600160a01b0381166109605760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b6064820152608401610633565b61096981610cc4565b50565b6065546001600160a01b0316331461075f5760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610633565b6001600160a01b038316610a285760405162461bcd60e51b8152602060048201526024808201527f45524332303a20617070726f76652066726f6d20746865207a65726f206164646044820152637265737360e01b6064820152608401610633565b6001600160a01b038216610a895760405162461bcd60e51b815260206004820152602260248201527f45524332303a20617070726f766520746f20746865207a65726f206164647265604482015261737360f01b6064820152608401610633565b6001600160a01b03838116600081815260ca602090815260408083209487168084529482529182902085905590518481527f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92591015b60405180910390a3505050565b600033610af9858285610e55565b61087b858585610ecf565b6001600160a01b038216610b5a5760405162461bcd60e51b815260206004820152601f60248201527f45524332303a206d696e7420746f20746865207a65726f2061646472657373006044820152606401610633565b8060cb6000828254610b6c91906114e1565b90915550506001600160a01b038216600081815260c960209081526040808320805486019055518481527fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef910160405180910390a35b5050565b610bce61107a565b610bd66110a9565b610969816110d8565b600054610100900460ff16610c065760405162461bcd60e51b815260040161063390611502565b610bc28282611121565b60975460405163195ac1a960e21b815260048101859052602481018490526000916001600160a01b03169063656b06a490604401602060405180830381865afa158015610c61573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c85919061154d565b905081158015610c9c57506001600160a01b038116155b156104d457604051631467050360e21b81526004810185905260248101849052604401610633565b606580546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b6001600160a01b038216610d765760405162461bcd60e51b815260206004820152602160248201527f45524332303a206275726e2066726f6d20746865207a65726f206164647265736044820152607360f81b6064820152608401610633565b6001600160a01b038216600090815260c9602052604090205481811015610dea5760405162461bcd60e51b815260206004820152602260248201527f45524332303a206275726e20616d6f756e7420657863656564732062616c616e604482015261636560f01b6064820152608401610633565b6001600160a01b038316600081815260c960209081526040808320868603905560cb80548790039055518581529192917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9101610ade565b505050565b60003361048f818585610ecf565b6000610e6184846108c8565b90506000198114610ec95781811015610ebc5760405162461bcd60e51b815260206004820152601d60248201527f45524332303a20696e73756666696369656e7420616c6c6f77616e63650000006044820152606401610633565b610ec984848484036109c6565b50505050565b6001600160a01b038316610f335760405162461bcd60e51b815260206004820152602560248201527f45524332303a207472616e736665722066726f6d20746865207a65726f206164604482015264647265737360d81b6064820152608401610633565b6001600160a01b038216610f955760405162461bcd60e51b815260206004820152602360248201527f45524332303a207472616e7366657220746f20746865207a65726f206164647260448201526265737360e81b6064820152608401610633565b6001600160a01b038316600090815260c960205260409020548181101561100d5760405162461bcd60e51b815260206004820152602660248201527f45524332303a207472616e7366657220616d6f756e7420657863656564732062604482015265616c616e636560d01b6064820152608401610633565b6001600160a01b03808516600081815260c9602052604080822086860390559286168082529083902080548601905591517fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9061106d9086815260200190565b60405180910390a3610ec9565b600054610100900460ff166110a15760405162461bcd60e51b815260040161063390611502565b61075f611161565b600054610100900460ff166110d05760405162461bcd60e51b815260040161063390611502565b61075f61118e565b6001600160a01b0381166110ff57604051634d084d8560e11b815260040160405180910390fd5b609780546001600160a01b0319166001600160a01b0392909216919091179055565b600054610100900460ff166111485760405162461bcd60e51b815260040161063390611502565b60cc61115483826115b8565b5060cd610e4282826115b8565b600054610100900460ff166111885760405162461bcd60e51b815260040161063390611502565b60018055565b600054610100900460ff166111b55760405162461bcd60e51b815260040161063390611502565b61075f33610cc4565b6001600160a01b038116811461096957600080fd5b6000602082840312156111e557600080fd5b81356104d4816111be565b600060208083528351808285015260005b8181101561121d57858101830151858201604001528201611201565b506000604082860101526040601f19601f8301168501019250505092915050565b6000806040838503121561125157600080fd5b823561125c816111be565b946020939093013593505050565b60008060006060848603121561127f57600080fd5b833561128a816111be565b9250602084013561129a816111be565b929592945050506040919091013590565b634e487b7160e01b600052604160045260246000fd5b600082601f8301126112d257600080fd5b813567ffffffffffffffff808211156112ed576112ed6112ab565b604051601f8301601f19908116603f01168101908282118183101715611315576113156112ab565b8160405283815286602085880101111561132e57600080fd5b836020870160208301376000602085830101528094505050505092915050565b60008060008060008060c0878903121561136757600080fd5b8635611372816111be565b95506020870135611382816111be565b945060408701359350606087013560ff8116811461139f57600080fd5b9250608087013567ffffffffffffffff808211156113bc57600080fd5b6113c88a838b016112c1565b935060a08901359150808211156113de57600080fd5b506113eb89828a016112c1565b9150509295509295509295565b8035801515811461140857600080fd5b919050565b60008060006060848603121561142257600080fd5b8335925060208401359150611439604085016113f8565b90509250925092565b6000806040838503121561145557600080fd5b82359150611465602084016113f8565b90509250929050565b6000806040838503121561148157600080fd5b823561148c816111be565b9150602083013561149c816111be565b809150509250929050565b600181811c908216806114bb57607f821691505b6020821081036114db57634e487b7160e01b600052602260045260246000fd5b50919050565b8082018082111561049557634e487b7160e01b600052601160045260246000fd5b6020808252602b908201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960408201526a6e697469616c697a696e6760a81b606082015260800190565b60006020828403121561155f57600080fd5b81516104d4816111be565b601f821115610e4257600081815260208120601f850160051c810160208610156115915750805b601f850160051c820191505b818110156115b05782815560010161159d565b505050505050565b815167ffffffffffffffff8111156115d2576115d26112ab565b6115e6816115e084546114a7565b8461156a565b602080601f83116001811461161b57600084156116035750858301515b600019600386901b1c1916600185901b1785556115b0565b600085815260208120601f198616915b8281101561164a5788860151825594840194600190910190840161162b565b50858210156116685787850151600019600388901b60f8161c191681555b5050505050600190811b0190555056fea26469706673582212205ce93c18102792779a2e35d561c62ea243b85b80c5963767b571fcdab9e3d74a64736f6c63430008120033a26469706673582212205b590be2c7b9e2eb2401e8170149f7dba7d88f43691401f4ee5b704b6bdc8bb364736f6c63430008120033", + "balance": "0x0" + }, + "0x1000777700000000000000000000000000000002": { + "contractName": "TokenVaultProxy", + "storage": { + "0x0000000000000000000000000000000000000000000000000000000000000000": "0x0000000000000000000000000000000000000000000000000000000000000001", + "0x0000000000000000000000000000000000000000000000000000000000000001": "0x0000000000000000000000000000000000000000000000000000000000000001", + "0x0000000000000000000000000000000000000000000000000000000000000065": "0x00000000000000000000000019b4f9c381c7927fe33d853e48b560141a380c44", + "0x0000000000000000000000000000000000000000000000000000000000000097": "0x0000000000000000000000001000777700000000000000000000000000000006", + "0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103": "0x113cE23c9e0cc50F4D41d7cE6DA02dCAFf8BFF85", + "0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc": "0x0000777700000000000000000000000000000002" + }, + "code": "0x60806040526004361061004e5760003560e01c80633659cfe6146100655780634f1ef286146100855780635c60da1b146100985780638f283970146100c9578063f851a440146100e95761005d565b3661005d5761005b6100fe565b005b61005b6100fe565b34801561007157600080fd5b5061005b6100803660046106c2565b610118565b61005b6100933660046106dd565b610155565b3480156100a457600080fd5b506100ad6101bc565b6040516001600160a01b03909116815260200160405180910390f35b3480156100d557600080fd5b5061005b6100e43660046106c2565b6101ed565b3480156100f557600080fd5b506100ad61020d565b610106610269565b6101166101116102fe565b610308565b565b61012061032c565b6001600160a01b0316330361014d5761014a8160405180602001604052806000815250600061035f565b50565b61014a6100fe565b61015d61032c565b6001600160a01b031633036101b4576101af8383838080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152506001925061035f915050565b505050565b6101af6100fe565b60006101c661032c565b6001600160a01b031633036101e2576101dd6102fe565b905090565b6101ea6100fe565b90565b6101f561032c565b6001600160a01b0316330361014d5761014a8161038a565b600061021761032c565b6001600160a01b031633036101e2576101dd61032c565b606061025383836040518060600160405280602781526020016107d4602791396103de565b9392505050565b6001600160a01b03163b151590565b61027161032c565b6001600160a01b031633036101165760405162461bcd60e51b815260206004820152604260248201527f5472616e73706172656e745570677261646561626c6550726f78793a2061646d60448201527f696e2063616e6e6f742066616c6c6261636b20746f2070726f78792074617267606482015261195d60f21b608482015260a4015b60405180910390fd5b60006101dd610456565b3660008037600080366000845af43d6000803e808015610327573d6000f35b3d6000fd5b60007fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035b546001600160a01b0316919050565b6103688361047e565b6000825111806103755750805b156101af57610384838361022e565b50505050565b7f7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f6103b361032c565b604080516001600160a01b03928316815291841660208301520160405180910390a161014a816104be565b6060600080856001600160a01b0316856040516103fb9190610784565b600060405180830381855af49150503d8060008114610436576040519150601f19603f3d011682016040523d82523d6000602084013e61043b565b606091505b509150915061044c86838387610567565b9695505050505050565b60007f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc610350565b610487816105e8565b6040516001600160a01b038216907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b90600090a250565b6001600160a01b0381166105235760405162461bcd60e51b815260206004820152602660248201527f455243313936373a206e65772061646d696e20697320746865207a65726f206160448201526564647265737360d01b60648201526084016102f5565b807fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035b80546001600160a01b0319166001600160a01b039290921691909117905550565b606083156105d65782516000036105cf576001600160a01b0385163b6105cf5760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e747261637400000060448201526064016102f5565b50816105e0565b6105e0838361067c565b949350505050565b6001600160a01b0381163b6106555760405162461bcd60e51b815260206004820152602d60248201527f455243313936373a206e657720696d706c656d656e746174696f6e206973206e60448201526c1bdd08184818dbdb9d1c9858dd609a1b60648201526084016102f5565b807f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc610546565b81511561068c5781518083602001fd5b8060405162461bcd60e51b81526004016102f591906107a0565b80356001600160a01b03811681146106bd57600080fd5b919050565b6000602082840312156106d457600080fd5b610253826106a6565b6000806000604084860312156106f257600080fd5b6106fb846106a6565b9250602084013567ffffffffffffffff8082111561071857600080fd5b818601915086601f83011261072c57600080fd5b81358181111561073b57600080fd5b87602082850101111561074d57600080fd5b6020830194508093505050509250925092565b60005b8381101561077b578181015183820152602001610763565b50506000910152565b60008251610796818460208701610760565b9190910192915050565b60208152600082518060208401526107bf816040850160208701610760565b601f01601f1916919091016040019291505056fe416464726573733a206c6f772d6c6576656c2064656c65676174652063616c6c206661696c6564a2646970667358221220f44b4bd0f73d4a6c872717d3b99f5935a2080af0980894ed447890241a743cdb64736f6c63430008120033", + "balance": "0x0" + }, + "0x0000777700000000000000000000000000000003": { + "contractName": "ProxiedEtherVault", + "storage": {}, + "code": "0x6080604052600436106100ab5760003560e01c80638da5cb5b116100645780638da5cb5b146101c0578063a86f9d9e146101de578063ba0bbd95146101fe578063d73bb3d01461021e578063f2fde38b1461023e578063fe9fbb801461025e57600080fd5b80630652b57a146100f457806319ab453c146101145780632d1fb389146101345780633ab76e9f146101545780636c6563f61461018b578063715018a6146101ab57600080fd5b366100ef5747158015906100cf575033600090815260c9602052604090205460ff16155b156100ed57604051634fa3f24560e01b815260040160405180910390fd5b005b600080fd5b34801561010057600080fd5b506100ed61010f366004610a90565b6102a7565b34801561012057600080fd5b506100ed61012f366004610a90565b61032a565b34801561014057600080fd5b506100ed61014f366004610ac2565b610442565b34801561016057600080fd5b506097546001600160a01b03165b6040516001600160a01b0390911681526020015b60405180910390f35b34801561019757600080fd5b5061016e6101a6366004610af7565b6104fb565b3480156101b757600080fd5b506100ed610512565b3480156101cc57600080fd5b506065546001600160a01b031661016e565b3480156101ea57600080fd5b5061016e6101f9366004610b2c565b610526565b34801561020a57600080fd5b506100ed610219366004610b4f565b610533565b34801561022a57600080fd5b506100ed610239366004610b7b565b6105f1565b34801561024a57600080fd5b506100ed610259366004610a90565b610674565b34801561026a57600080fd5b50610297610279366004610a90565b6001600160a01b0316600090815260c9602052604090205460ff1690565b6040519015158152602001610182565b6102af6106ea565b6001600160a01b0381166102d657604051634d084d8560e11b815260040160405180910390fd5b609780546001600160a01b0319166001600160a01b0383169081179091556040519081527f399ded90cb5ed8d89ef7e76ff4af65c373f06d3bf5d7eef55f4228e7b702a18b9060200160405180910390a150565b600054610100900460ff161580801561034a5750600054600160ff909116105b806103645750303b158015610364575060005460ff166001145b6103cc5760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b60648201526084015b60405180910390fd5b6000805460ff1916600117905580156103ef576000805461ff0019166101001790555b6103f882610744565b801561043e576000805461ff0019169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b5050565b61044a6106ea565b6001600160a01b038216158061047e57506001600160a01b038216600090815260c9602052604090205460ff161515811515145b1561049c57604051631bebdfa760e21b815260040160405180910390fd5b6001600160a01b038216600081815260c96020908152604091829020805460ff191685151590811790915591519182527f4c0079b9bcd37cd5d29a13938effd97c881798cbc6bd52a3026a29d94b27d1bf910160405180910390a25050565b600061050884848461075d565b90505b9392505050565b61051a6106ea565b6105246000610811565b565b600061050b46848461075d565b33600090815260c9602052604090205460ff1661056357604051634fa3f24560e01b815260040160405180910390fd5b61056b610863565b6001600160a01b0382166105925760405163687563df60e01b815260040160405180910390fd5b6105a56001600160a01b038316826108bc565b816001600160a01b03167f7b9f77d35803cd201eac9c4ed739bc1fcd3f1be6ab8877d925d1e55517b6fd6e826040516105e091815260200190565b60405180910390a261043e60018055565b33600090815260c9602052604090205460ff1661062157604051634fa3f24560e01b815260040160405180910390fd5b610629610863565b61063333826108bc565b60405181815233907f7b9f77d35803cd201eac9c4ed739bc1fcd3f1be6ab8877d925d1e55517b6fd6e9060200160405180910390a261067160018055565b50565b61067c6106ea565b6001600160a01b0381166106e15760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b60648201526084016103c3565b61067181610811565b6065546001600160a01b031633146105245760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657260448201526064016103c3565b61074c61097d565b6107546109ac565b610671816109db565b60975460405163195ac1a960e21b815260048101859052602481018490526000916001600160a01b03169063656b06a490604401602060405180830381865afa1580156107ae573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906107d29190610b94565b9050811580156107e957506001600160a01b038116155b1561050b57604051631467050360e21b815260048101859052602481018490526044016103c3565b606580546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b6002600154036108b55760405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c0060448201526064016103c3565b6002600155565b8015806108d057506001600160a01b038216155b156108d9575050565b6000826001600160a01b03168260405160006040518083038185875af1925050503d8060008114610926576040519150601f19603f3d011682016040523d82523d6000602084013e61092b565b606091505b50509050806109725760405162461bcd60e51b8152602060048201526013602482015272115512081d1c985b9cd9995c8819985a5b1959606a1b60448201526064016103c3565b505050565b60018055565b600054610100900460ff166109a45760405162461bcd60e51b81526004016103c390610bb1565b610524610a24565b600054610100900460ff166109d35760405162461bcd60e51b81526004016103c390610bb1565b610524610a4b565b6001600160a01b038116610a0257604051634d084d8560e11b815260040160405180910390fd5b609780546001600160a01b0319166001600160a01b0392909216919091179055565b600054610100900460ff166109775760405162461bcd60e51b81526004016103c390610bb1565b600054610100900460ff16610a725760405162461bcd60e51b81526004016103c390610bb1565b61052433610811565b6001600160a01b038116811461067157600080fd5b600060208284031215610aa257600080fd5b813561050b81610a7b565b80358015158114610abd57600080fd5b919050565b60008060408385031215610ad557600080fd5b8235610ae081610a7b565b9150610aee60208401610aad565b90509250929050565b600080600060608486031215610b0c57600080fd5b8335925060208401359150610b2360408501610aad565b90509250925092565b60008060408385031215610b3f57600080fd5b82359150610aee60208401610aad565b60008060408385031215610b6257600080fd5b8235610b6d81610a7b565b946020939093013593505050565b600060208284031215610b8d57600080fd5b5035919050565b600060208284031215610ba657600080fd5b815161050b81610a7b565b6020808252602b908201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960408201526a6e697469616c697a696e6760a81b60608201526080019056fea26469706673582212207583c25e67e1b9db0f317fbe1c15cd5a0919373c4d9b26d98238ed2046695f9264736f6c63430008120033", + "balance": "0x0" + }, + "0x1000777700000000000000000000000000000003": { + "contractName": "EtherVaultProxy", + "storage": { + "0x0000000000000000000000000000000000000000000000000000000000000000": "0x0000000000000000000000000000000000000000000000000000000000000001", + "0x0000000000000000000000000000000000000000000000000000000000000001": "0x0000000000000000000000000000000000000000000000000000000000000001", + "0x0000000000000000000000000000000000000000000000000000000000000065": "0x00000000000000000000000019b4f9c381c7927fe33d853e48b560141a380c44", + "0x0000000000000000000000000000000000000000000000000000000000000097": "0x0000000000000000000000001000777700000000000000000000000000000006", + "0xa738d3397c1eb96f671d7e4bd29cabbfa1a9c9ebc0db4142aee17809c43ab720": "0x0000000000000000000000000000000000000000000000000000000000000001", + "0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103": "0x113cE23c9e0cc50F4D41d7cE6DA02dCAFf8BFF85", + "0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc": "0x0000777700000000000000000000000000000003" + }, + "code": "0x60806040526004361061004e5760003560e01c80633659cfe6146100655780634f1ef286146100855780635c60da1b146100985780638f283970146100c9578063f851a440146100e95761005d565b3661005d5761005b6100fe565b005b61005b6100fe565b34801561007157600080fd5b5061005b6100803660046106c2565b610118565b61005b6100933660046106dd565b610155565b3480156100a457600080fd5b506100ad6101bc565b6040516001600160a01b03909116815260200160405180910390f35b3480156100d557600080fd5b5061005b6100e43660046106c2565b6101ed565b3480156100f557600080fd5b506100ad61020d565b610106610269565b6101166101116102fe565b610308565b565b61012061032c565b6001600160a01b0316330361014d5761014a8160405180602001604052806000815250600061035f565b50565b61014a6100fe565b61015d61032c565b6001600160a01b031633036101b4576101af8383838080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152506001925061035f915050565b505050565b6101af6100fe565b60006101c661032c565b6001600160a01b031633036101e2576101dd6102fe565b905090565b6101ea6100fe565b90565b6101f561032c565b6001600160a01b0316330361014d5761014a8161038a565b600061021761032c565b6001600160a01b031633036101e2576101dd61032c565b606061025383836040518060600160405280602781526020016107d4602791396103de565b9392505050565b6001600160a01b03163b151590565b61027161032c565b6001600160a01b031633036101165760405162461bcd60e51b815260206004820152604260248201527f5472616e73706172656e745570677261646561626c6550726f78793a2061646d60448201527f696e2063616e6e6f742066616c6c6261636b20746f2070726f78792074617267606482015261195d60f21b608482015260a4015b60405180910390fd5b60006101dd610456565b3660008037600080366000845af43d6000803e808015610327573d6000f35b3d6000fd5b60007fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035b546001600160a01b0316919050565b6103688361047e565b6000825111806103755750805b156101af57610384838361022e565b50505050565b7f7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f6103b361032c565b604080516001600160a01b03928316815291841660208301520160405180910390a161014a816104be565b6060600080856001600160a01b0316856040516103fb9190610784565b600060405180830381855af49150503d8060008114610436576040519150601f19603f3d011682016040523d82523d6000602084013e61043b565b606091505b509150915061044c86838387610567565b9695505050505050565b60007f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc610350565b610487816105e8565b6040516001600160a01b038216907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b90600090a250565b6001600160a01b0381166105235760405162461bcd60e51b815260206004820152602660248201527f455243313936373a206e65772061646d696e20697320746865207a65726f206160448201526564647265737360d01b60648201526084016102f5565b807fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035b80546001600160a01b0319166001600160a01b039290921691909117905550565b606083156105d65782516000036105cf576001600160a01b0385163b6105cf5760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e747261637400000060448201526064016102f5565b50816105e0565b6105e0838361067c565b949350505050565b6001600160a01b0381163b6106555760405162461bcd60e51b815260206004820152602d60248201527f455243313936373a206e657720696d706c656d656e746174696f6e206973206e60448201526c1bdd08184818dbdb9d1c9858dd609a1b60648201526084016102f5565b807f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc610546565b81511561068c5781518083602001fd5b8060405162461bcd60e51b81526004016102f591906107a0565b80356001600160a01b03811681146106bd57600080fd5b919050565b6000602082840312156106d457600080fd5b610253826106a6565b6000806000604084860312156106f257600080fd5b6106fb846106a6565b9250602084013567ffffffffffffffff8082111561071857600080fd5b818601915086601f83011261072c57600080fd5b81358181111561073b57600080fd5b87602082850101111561074d57600080fd5b6020830194508093505050509250925092565b60005b8381101561077b578181015183820152602001610763565b50506000910152565b60008251610796818460208701610760565b9190910192915050565b60208152600082518060208401526107bf816040850160208701610760565b601f01601f1916919091016040019291505056fe416464726573733a206c6f772d6c6576656c2064656c65676174652063616c6c206661696c6564a2646970667358221220f44b4bd0f73d4a6c872717d3b99f5935a2080af0980894ed447890241a743cdb64736f6c63430008120033", + "balance": "0xffffffffffffff21f494c589bfffffff" + }, + "0x0000777700000000000000000000000000000007": { + "contractName": "ProxiedSignalService", + "storage": {}, + "code": "0x608060405234801561001057600080fd5b50600436106100b45760003560e01c80636c6563f6116100715780636c6563f614610162578063715018a6146101755780638da5cb5b1461017d578063a86f9d9e1461018e578063f2fde38b146101a1578063f8f3f844146101b457600080fd5b80630652b57a146100b957806319ab453c146100ce57806332676bc6146100e15780633ab76e9f146101095780635221f6131461012e57806366ca2bc014610141575b600080fd5b6100cc6100c7366004611a18565b6101e0565b005b6100cc6100dc366004611a18565b610263565b6100f46100ef366004611a35565b61037b565b60405190151581526020015b60405180910390f35b6097546001600160a01b03165b6040516001600160a01b039091168152602001610100565b6100f461013c366004611a61565b6103ed565b61015461014f366004611af7565b61055d565b604051908152602001610100565b610116610170366004611b25565b6105a2565b6100cc6105b9565b6065546001600160a01b0316610116565b61011661019c366004611b5a565b6105cd565b6100cc6101af366004611a18565b6105da565b6101546101c2366004611a35565b6040805192835260208301919091526034600c830120918101905290565b6101e8610653565b6001600160a01b03811661020f57604051634d084d8560e11b815260040160405180910390fd5b609780546001600160a01b0319166001600160a01b0383169081179091556040519081527f399ded90cb5ed8d89ef7e76ff4af65c373f06d3bf5d7eef55f4228e7b702a18b9060200160405180910390a150565b600054610100900460ff16158080156102835750600054600160ff909116105b8061029d5750303b15801561029d575060005460ff166001145b6103055760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b60648201526084015b60405180910390fd5b6000805460ff191660011790558015610328576000805461ff0019166101001790555b610331826106ad565b8015610377576000805461ff0019169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b5050565b60006001600160a01b0383166103a4576040516354cdfc8d60e11b815260040160405180910390fd5b60008290036103c65760405163014f1da760e21b815260040160405180910390fd5b5060408051838152602081018390526034600c820120908201909152546001145b92915050565b600046860361040f5760405163e822b48d60e01b815260040160405180910390fd5b6001600160a01b038516610436576040516354cdfc8d60e11b815260040160405180910390fd5b60008490036104585760405163014f1da760e21b815260040160405180910390fd5b600061046683850185611bf6565b9050600061047d647461696b6f60d81b60006105cd565b8251604051632e24533960e21b81526001600160a01b03929092169163b8914ce4916104af9160040190815260200190565b602060405180830381865afa1580156104cc573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906104f09190611cbd565b60408051898152602081018990526034600c820120818301909252606081019190915290915061055190608001604051602081830303815290604052604051806040016040528060018152602001600160f81b8152508460200151846106c6565b98975050505050505050565b600081810361057f5760405163014f1da760e21b815260040160405180910390fd5b506040805133815260208101929092526034600c83012091810190526001815590565b60006105af8484846106ea565b90505b9392505050565b6105c1610653565b6105cb600061079e565b565b60006105b24684846106ea565b6105e2610653565b6001600160a01b0381166106475760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b60648201526084016102fc565b6106508161079e565b50565b6065546001600160a01b031633146105cb5760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657260448201526064016102fc565b6106b56107f0565b6106bd61081f565b6106508161084e565b6000806106d286610897565b90506106e0818686866108c9565b9695505050505050565b60975460405163195ac1a960e21b815260048101859052602481018490526000916001600160a01b03169063656b06a490604401602060405180830381865afa15801561073b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061075f9190611cd6565b90508115801561077657506001600160a01b038116155b156105b257604051631467050360e21b815260048101859052602481018490526044016102fc565b606580546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b600054610100900460ff166108175760405162461bcd60e51b81526004016102fc90611cf3565b6105cb610906565b600054610100900460ff166108465760405162461bcd60e51b81526004016102fc90611cf3565b6105cb610933565b6001600160a01b03811661087557604051634d084d8560e11b815260040160405180910390fd5b609780546001600160a01b0319166001600160a01b0392909216919091179055565b606081805190602001206040516020016108b391815260200190565b6040516020818303038152906040529050919050565b60008060006108d9878686610963565b915091508180156108fb57508051602080830191909120875191880191909120145b979650505050505050565b600054610100900460ff1661092d5760405162461bcd60e51b81526004016102fc90611cf3565b60018055565b600054610100900460ff1661095a5760405162461bcd60e51b81526004016102fc90611cf3565b6105cb3361079e565b60006060600061097285610a3e565b90506000806000610984848a89610b37565b815192955090935091501580806109985750815b6109e45760405162461bcd60e51b815260206004820152601a60248201527f50726f76696465642070726f6f6620697320696e76616c69642e00000000000060448201526064016102fc565b600081610a005760405180602001604052806000815250610a2c565b610a2c86610a0f600188611d54565b81518110610a1f57610a1f611d67565b6020026020010151610f57565b919b919a509098505050505050505050565b60606000610a4b83610f7e565b90506000815167ffffffffffffffff811115610a6957610a69611b86565b604051908082528060200260200182016040528015610aae57816020015b6040805180820190915260608082526020820152815260200190600190039081610a875790505b50905060005b8251811015610b2f576000610ae1848381518110610ad457610ad4611d67565b6020026020010151610fb1565b90506040518060400160405280610af783610f7e565b815260200182815250838381518110610b1257610b12611d67565b60200260200101819052505080610b2890611d7d565b9050610ab4565b509392505050565b600060606000806000610b4987611041565b90506000869050600080610b70604051806040016040528060608152602001606081525090565b60005b8c51811015610f2f578c8181518110610b8e57610b8e611d67565b602002602001015191508284610ba49190611d96565b9350610bb1600188611d96565b965083600003610c0e578482602001518051906020012014610c095760405162461bcd60e51b8152602060048201526011602482015270092dcecc2d8d2c840e4dedee840d0c2e6d607b1b60448201526064016102fc565b610cd0565b602082602001515110610c75578482602001518051906020012014610c095760405162461bcd60e51b815260206004820152601b60248201527f496e76616c6964206c6172676520696e7465726e616c2068617368000000000060448201526064016102fc565b84610c83836020015161117a565b14610cd05760405162461bcd60e51b815260206004820152601a60248201527f496e76616c696420696e7465726e616c206e6f6465206861736800000000000060448201526064016102fc565b610cdc60106001611da9565b60ff1682600001515103610d4a5785518414610f2f576000868581518110610d0657610d06611d67565b01602001518351805160f89290921c925060009183908110610d2a57610d2a611d67565b60200260200101519050610d3d816111a2565b9650600194505050610f1f565b81515160011901610ed7576000610d60836111d8565b9050600081600081518110610d7757610d77611d67565b016020015160f81c90506000610d8e600283611dc2565b610d99906002611df2565b90506000610daa848360ff166111fc565b90506000610db88b8a6111fc565b90506000610dc68383611232565b905060ff851660021480610ddd575060ff85166003145b15610e1757808351148015610df25750808251145b15610e0457610e01818b611d96565b99505b50600160ff1b9950610f2f945050505050565b60ff85161580610e2a575060ff85166001145b15610e805782518114610e4a5750600160ff1b9950610f2f945050505050565b610e718860000151600181518110610e6457610e64611d67565b60200260200101516111a2565b9a509750610f1f945050505050565b60405162461bcd60e51b815260206004820152602660248201527f52656365697665642061206e6f6465207769746820616e20756e6b6e6f776e206044820152650e0e4caccd2f60d31b60648201526084016102fc565b60405162461bcd60e51b815260206004820152601d60248201527f526563656976656420616e20756e706172736561626c65206e6f64652e00000060448201526064016102fc565b610f2881611d7d565b9050610b73565b50600160ff1b841486610f4287866111fc565b909e909d50909b509950505050505050505050565b805180516060916103e791610f6e90600190611d54565b81518110610ad457610ad4611d67565b6040805180820182526000808252602091820152815180830190925282518252808301908201526060906103e7906112ac565b60606000806000610fc185611498565b919450925090506000816001811115610fdc57610fdc611e0b565b146110295760405162461bcd60e51b815260206004820152601860248201527f496e76616c696420524c502062797465732076616c75652e000000000000000060448201526064016102fc565b611038856020015184846117e2565b95945050505050565b60606000825160026110539190611e21565b67ffffffffffffffff81111561106b5761106b611b86565b6040519080825280601f01601f191660200182016040528015611095576020820181803683370190505b50905060005b83518110156111735760048482815181106110b8576110b8611d67565b01602001516001600160f81b031916901c826110d5836002611e21565b815181106110e5576110e5611d67565b60200101906001600160f81b031916908160001a905350601084828151811061111057611110611d67565b0160200151611122919060f81c611dc2565b60f81b82611131836002611e21565b61113c906001611d96565b8151811061114c5761114c611d67565b60200101906001600160f81b031916908160001a90535061116c81611d7d565b905061109b565b5092915050565b600060208251101561118e57506020015190565b818060200190518101906103e79190611cbd565b600060606020836000015110156111c3576111bc8361188b565b90506111cf565b6111cc83610fb1565b90505b6105b28161117a565b60606103e76111f78360000151600081518110610ad457610ad4611d67565b611041565b60608251821061121b57506040805160208101909152600081526103e7565b6105b2838384865161122d9190611d54565b611896565b6000805b8084511180156112465750808351115b8015611297575082818151811061125f5761125f611d67565b602001015160f81c60f81b6001600160f81b03191684828151811061128657611286611d67565b01602001516001600160f81b031916145b156105b2576112a581611d7d565b9050611236565b60606000806112ba84611498565b919350909150600190508160018111156112d6576112d6611e0b565b146113235760405162461bcd60e51b815260206004820152601760248201527f496e76616c696420524c50206c6973742076616c75652e00000000000000000060448201526064016102fc565b6040805160208082526104208201909252600091816020015b604080518082019091526000808252602082015281526020019060019003908161133c5790505090506000835b865181101561148d57602082106113d55760405162461bcd60e51b815260206004820152602a60248201527f50726f766964656420524c50206c6973742065786365656473206d6178206c6960448201526939ba103632b733ba341760b11b60648201526084016102fc565b6000806114126040518060400160405280858c600001516113f69190611d54565b8152602001858c6020015161140b9190611d96565b9052611498565b50915091506040518060400160405280838361142e9190611d96565b8152602001848b602001516114439190611d96565b81525085858151811061145857611458611d67565b602090810291909101015261146e600185611d96565b935061147a8183611d96565b6114849084611d96565b92505050611369565b508152949350505050565b6000806000808460000151116114f05760405162461bcd60e51b815260206004820152601860248201527f524c50206974656d2063616e6e6f74206265206e756c6c2e000000000000000060448201526064016102fc565b6020840151805160001a607f81116115155760006001600094509450945050506117db565b60b7811161159157600061152a608083611d54565b90508087600001511161157f5760405162461bcd60e51b815260206004820152601960248201527f496e76616c696420524c502073686f727420737472696e672e0000000000000060448201526064016102fc565b600195509350600092506117db915050565b60bf81116116805760006115a660b783611d54565b9050808760000151116115fb5760405162461bcd60e51b815260206004820152601f60248201527f496e76616c696420524c50206c6f6e6720737472696e67206c656e6774682e0060448201526064016102fc565b600183015160208290036101000a90046116158183611d96565b8851116116645760405162461bcd60e51b815260206004820152601860248201527f496e76616c696420524c50206c6f6e6720737472696e672e000000000000000060448201526064016102fc565b61166f826001611d96565b96509450600093506117db92505050565b60f781116116fb57600061169560c083611d54565b9050808760000151116116ea5760405162461bcd60e51b815260206004820152601760248201527f496e76616c696420524c502073686f7274206c6973742e00000000000000000060448201526064016102fc565b6001955093508492506117db915050565b600061170860f783611d54565b90508087600001511161175d5760405162461bcd60e51b815260206004820152601d60248201527f496e76616c696420524c50206c6f6e67206c697374206c656e6774682e00000060448201526064016102fc565b600183015160208290036101000a90046117778183611d96565b8851116117bf5760405162461bcd60e51b815260206004820152601660248201527524b73b30b634b210292628103637b733903634b9ba1760511b60448201526064016102fc565b6117ca826001611d96565b96509450600193506117db92505050565b9193909250565b606060008267ffffffffffffffff8111156117ff576117ff611b86565b6040519080825280601f01601f191660200182016040528015611829576020820181803683370190505b509050805160000361183c5790506105b2565b8484016020820160005b8581101561185e578281015182820152602001611846565b5060006001602087066020036101000a039050808251168119845116178252839450505050509392505050565b60606103e7826119ed565b6060816118a481601f611d96565b10156118e35760405162461bcd60e51b815260206004820152600e60248201526d736c6963655f6f766572666c6f7760901b60448201526064016102fc565b826118ee8382611d96565b101561192d5760405162461bcd60e51b815260206004820152600e60248201526d736c6963655f6f766572666c6f7760901b60448201526064016102fc565b6119378284611d96565b8451101561197b5760405162461bcd60e51b8152602060048201526011602482015270736c6963655f6f75744f66426f756e647360781b60448201526064016102fc565b60608215801561199a57604051915060008252602082016040526119e4565b6040519150601f8416801560200281840101858101878315602002848b0101015b818310156119d35780518352602092830192016119bb565b5050858452601f01601f1916604052505b50949350505050565b60606103e78260200151600084600001516117e2565b6001600160a01b038116811461065057600080fd5b600060208284031215611a2a57600080fd5b81356105b281611a03565b60008060408385031215611a4857600080fd5b8235611a5381611a03565b946020939093013593505050565b600080600080600060808688031215611a7957600080fd5b853594506020860135611a8b81611a03565b935060408601359250606086013567ffffffffffffffff80821115611aaf57600080fd5b818801915088601f830112611ac357600080fd5b813581811115611ad257600080fd5b896020828501011115611ae457600080fd5b9699959850939650602001949392505050565b600060208284031215611b0957600080fd5b5035919050565b80358015158114611b2057600080fd5b919050565b600080600060608486031215611b3a57600080fd5b8335925060208401359150611b5160408501611b10565b90509250925092565b60008060408385031215611b6d57600080fd5b82359150611b7d60208401611b10565b90509250929050565b634e487b7160e01b600052604160045260246000fd5b6040805190810167ffffffffffffffff81118282101715611bbf57611bbf611b86565b60405290565b604051601f8201601f1916810167ffffffffffffffff81118282101715611bee57611bee611b86565b604052919050565b60006020808385031215611c0957600080fd5b823567ffffffffffffffff80821115611c2157600080fd5b9084019060408287031215611c3557600080fd5b611c3d611b9c565b823581528383013582811115611c5257600080fd5b80840193505086601f840112611c6757600080fd5b823582811115611c7957611c79611b86565b611c8b601f8201601f19168601611bc5565b92508083528785828601011115611ca157600080fd5b8085850186850137600090830185015292830152509392505050565b600060208284031215611ccf57600080fd5b5051919050565b600060208284031215611ce857600080fd5b81516105b281611a03565b6020808252602b908201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960408201526a6e697469616c697a696e6760a81b606082015260800190565b634e487b7160e01b600052601160045260246000fd5b818103818111156103e7576103e7611d3e565b634e487b7160e01b600052603260045260246000fd5b600060018201611d8f57611d8f611d3e565b5060010190565b808201808211156103e7576103e7611d3e565b60ff81811683821601908111156103e7576103e7611d3e565b600060ff831680611de357634e487b7160e01b600052601260045260246000fd5b8060ff84160691505092915050565b60ff82811682821603908111156103e7576103e7611d3e565b634e487b7160e01b600052602160045260246000fd5b80820281158282048414176103e7576103e7611d3e56fea2646970667358221220914fd418156d9d9a0e4aa8f2d563552ff29aa367381c04f0e5db5dcc63b0ce7264736f6c63430008120033", + "balance": "0x0" + }, + "0x1000777700000000000000000000000000000007": { + "contractName": "SignalServiceProxy", + "storage": { + "0x0000000000000000000000000000000000000000000000000000000000000000": "0x0000000000000000000000000000000000000000000000000000000000000001", + "0x0000000000000000000000000000000000000000000000000000000000000001": "0x0000000000000000000000000000000000000000000000000000000000000001", + "0x0000000000000000000000000000000000000000000000000000000000000065": "0x00000000000000000000000019b4f9c381c7927fe33d853e48b560141a380c44", + "0x0000000000000000000000000000000000000000000000000000000000000097": "0x0000000000000000000000001000777700000000000000000000000000000006", + "0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103": "0x113cE23c9e0cc50F4D41d7cE6DA02dCAFf8BFF85", + "0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc": "0x0000777700000000000000000000000000000007" + }, + "code": "0x60806040526004361061004e5760003560e01c80633659cfe6146100655780634f1ef286146100855780635c60da1b146100985780638f283970146100c9578063f851a440146100e95761005d565b3661005d5761005b6100fe565b005b61005b6100fe565b34801561007157600080fd5b5061005b6100803660046106c2565b610118565b61005b6100933660046106dd565b610155565b3480156100a457600080fd5b506100ad6101bc565b6040516001600160a01b03909116815260200160405180910390f35b3480156100d557600080fd5b5061005b6100e43660046106c2565b6101ed565b3480156100f557600080fd5b506100ad61020d565b610106610269565b6101166101116102fe565b610308565b565b61012061032c565b6001600160a01b0316330361014d5761014a8160405180602001604052806000815250600061035f565b50565b61014a6100fe565b61015d61032c565b6001600160a01b031633036101b4576101af8383838080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152506001925061035f915050565b505050565b6101af6100fe565b60006101c661032c565b6001600160a01b031633036101e2576101dd6102fe565b905090565b6101ea6100fe565b90565b6101f561032c565b6001600160a01b0316330361014d5761014a8161038a565b600061021761032c565b6001600160a01b031633036101e2576101dd61032c565b606061025383836040518060600160405280602781526020016107d4602791396103de565b9392505050565b6001600160a01b03163b151590565b61027161032c565b6001600160a01b031633036101165760405162461bcd60e51b815260206004820152604260248201527f5472616e73706172656e745570677261646561626c6550726f78793a2061646d60448201527f696e2063616e6e6f742066616c6c6261636b20746f2070726f78792074617267606482015261195d60f21b608482015260a4015b60405180910390fd5b60006101dd610456565b3660008037600080366000845af43d6000803e808015610327573d6000f35b3d6000fd5b60007fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035b546001600160a01b0316919050565b6103688361047e565b6000825111806103755750805b156101af57610384838361022e565b50505050565b7f7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f6103b361032c565b604080516001600160a01b03928316815291841660208301520160405180910390a161014a816104be565b6060600080856001600160a01b0316856040516103fb9190610784565b600060405180830381855af49150503d8060008114610436576040519150601f19603f3d011682016040523d82523d6000602084013e61043b565b606091505b509150915061044c86838387610567565b9695505050505050565b60007f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc610350565b610487816105e8565b6040516001600160a01b038216907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b90600090a250565b6001600160a01b0381166105235760405162461bcd60e51b815260206004820152602660248201527f455243313936373a206e65772061646d696e20697320746865207a65726f206160448201526564647265737360d01b60648201526084016102f5565b807fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035b80546001600160a01b0319166001600160a01b039290921691909117905550565b606083156105d65782516000036105cf576001600160a01b0385163b6105cf5760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e747261637400000060448201526064016102f5565b50816105e0565b6105e0838361067c565b949350505050565b6001600160a01b0381163b6106555760405162461bcd60e51b815260206004820152602d60248201527f455243313936373a206e657720696d706c656d656e746174696f6e206973206e60448201526c1bdd08184818dbdb9d1c9858dd609a1b60648201526084016102f5565b807f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc610546565b81511561068c5781518083602001fd5b8060405162461bcd60e51b81526004016102f591906107a0565b80356001600160a01b03811681146106bd57600080fd5b919050565b6000602082840312156106d457600080fd5b610253826106a6565b6000806000604084860312156106f257600080fd5b6106fb846106a6565b9250602084013567ffffffffffffffff8082111561071857600080fd5b818601915086601f83011261072c57600080fd5b81358181111561073b57600080fd5b87602082850101111561074d57600080fd5b6020830194508093505050509250925092565b60005b8381101561077b578181015183820152602001610763565b50506000910152565b60008251610796818460208701610760565b9190910192915050565b60208152600082518060208401526107bf816040850160208701610760565b601f01601f1916919091016040019291505056fe416464726573733a206c6f772d6c6576656c2064656c65676174652063616c6c206661696c6564a2646970667358221220f44b4bd0f73d4a6c872717d3b99f5935a2080af0980894ed447890241a743cdb64736f6c63430008120033", + "balance": "0x0" + }, + "0x0000777700000000000000000000000000000005": { + "contractName": "RegularERC20", + "storage": { + "0x0000000000000000000000000000000000000000000000000000000000000003": "0x526567756c617245524332300000000000000000000000000000000000000018", + "0x0000000000000000000000000000000000000000000000000000000000000004": "0x52474c0000000000000000000000000000000000000000000000000000000006", + "0x0000000000000000000000000000000000000000000000000000000000000002": "0x00000000000000000000000000000000000000000000000000000000003e8000", + "0xc4fd933fc30203af5f8bd19ad30e064c96642a369b9fc4288ea95569541f4034": "0x00000000000000000000000000000000000000000000000000000000000fa000", + "0x967c153683def525608ec6efe0cac3319a9c97a6d4164fb43765c79311abffdc": "0x00000000000000000000000000000000000000000000000000000000000fa000", + "0x55385a0c2ad17c21b4fe396be9b1f10f500e7eebad11fcd1afe36c68ee5fa4cd": "0x00000000000000000000000000000000000000000000000000000000000fa000", + "0x478db7f3c43c550c1670aa0517a6d515b9e15f22ea28e4f99e8c5f8bcf58e406": "0x00000000000000000000000000000000000000000000000000000000000fa000" + }, + "code": "0x608060405234801561001057600080fd5b50600436106100a95760003560e01c80633950935111610071578063395093511461012357806370a082311461013657806395d89b411461015f578063a457c2d714610167578063a9059cbb1461017a578063dd62ed3e1461018d57600080fd5b806306fdde03146100ae578063095ea7b3146100cc57806318160ddd146100ef57806323b872dd14610101578063313ce56714610114575b600080fd5b6100b66101a0565b6040516100c3919061069c565b60405180910390f35b6100df6100da366004610706565b610232565b60405190151581526020016100c3565b6002545b6040519081526020016100c3565b6100df61010f366004610730565b61024c565b604051601281526020016100c3565b6100df610131366004610706565b610270565b6100f361014436600461076c565b6001600160a01b031660009081526020819052604090205490565b6100b6610292565b6100df610175366004610706565b6102a1565b6100df610188366004610706565b610321565b6100f361019b36600461078e565b61032f565b6060600380546101af906107c1565b80601f01602080910402602001604051908101604052809291908181526020018280546101db906107c1565b80156102285780601f106101fd57610100808354040283529160200191610228565b820191906000526020600020905b81548152906001019060200180831161020b57829003601f168201915b5050505050905090565b60003361024081858561035a565b60019150505b92915050565b60003361025a85828561047e565b6102658585856104f8565b506001949350505050565b600033610240818585610283838361032f565b61028d91906107fb565b61035a565b6060600480546101af906107c1565b600033816102af828661032f565b9050838110156103145760405162461bcd60e51b815260206004820152602560248201527f45524332303a2064656372656173656420616c6c6f77616e63652062656c6f77604482015264207a65726f60d81b60648201526084015b60405180910390fd5b610265828686840361035a565b6000336102408185856104f8565b6001600160a01b03918216600090815260016020908152604080832093909416825291909152205490565b6001600160a01b0383166103bc5760405162461bcd60e51b8152602060048201526024808201527f45524332303a20617070726f76652066726f6d20746865207a65726f206164646044820152637265737360e01b606482015260840161030b565b6001600160a01b03821661041d5760405162461bcd60e51b815260206004820152602260248201527f45524332303a20617070726f766520746f20746865207a65726f206164647265604482015261737360f01b606482015260840161030b565b6001600160a01b0383811660008181526001602090815260408083209487168084529482529182902085905590518481527f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925910160405180910390a3505050565b600061048a848461032f565b905060001981146104f257818110156104e55760405162461bcd60e51b815260206004820152601d60248201527f45524332303a20696e73756666696369656e7420616c6c6f77616e6365000000604482015260640161030b565b6104f2848484840361035a565b50505050565b6001600160a01b03831661055c5760405162461bcd60e51b815260206004820152602560248201527f45524332303a207472616e736665722066726f6d20746865207a65726f206164604482015264647265737360d81b606482015260840161030b565b6001600160a01b0382166105be5760405162461bcd60e51b815260206004820152602360248201527f45524332303a207472616e7366657220746f20746865207a65726f206164647260448201526265737360e81b606482015260840161030b565b6001600160a01b038316600090815260208190526040902054818110156106365760405162461bcd60e51b815260206004820152602660248201527f45524332303a207472616e7366657220616d6f756e7420657863656564732062604482015265616c616e636560d01b606482015260840161030b565b6001600160a01b03848116600081815260208181526040808320878703905593871680835291849020805487019055925185815290927fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef910160405180910390a36104f2565b600060208083528351808285015260005b818110156106c9578581018301518582016040015282016106ad565b506000604082860101526040601f19601f8301168501019250505092915050565b80356001600160a01b038116811461070157600080fd5b919050565b6000806040838503121561071957600080fd5b610722836106ea565b946020939093013593505050565b60008060006060848603121561074557600080fd5b61074e846106ea565b925061075c602085016106ea565b9150604084013590509250925092565b60006020828403121561077e57600080fd5b610787826106ea565b9392505050565b600080604083850312156107a157600080fd5b6107aa836106ea565b91506107b8602084016106ea565b90509250929050565b600181811c908216806107d557607f821691505b6020821081036107f557634e487b7160e01b600052602260045260246000fd5b50919050565b8082018082111561024657634e487b7160e01b600052601160045260246000fdfea26469706673582212209d989a5d58a4967fd0a1f669587c6ef0bd08d65b4de1b60d2f761d4c7661886164736f6c63430008120033", + "balance": "0x0" + } +}
diff --git ethereum/go-ethereum/core/taiko_genesis/internal.json taikoxyz/taiko-geth/core/taiko_genesis/internal.json new file mode 100644 index 0000000000000000000000000000000000000000..7080c1feeac49d45e574745e85d838ffead5fa32 --- /dev/null +++ taikoxyz/taiko-geth/core/taiko_genesis/internal.json @@ -0,0 +1,251 @@ +{ + "0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266": { + "balance": "0x3782dace9d90000000" + }, + "0x70997970C51812dc3A010C7d01b50e0d17dc79C8": { + "balance": "0x3782dace9d90000000" + }, + "0x3C44CdDdB6a900fa2b585dd299e03d12FA4293BC": { + "balance": "0x3782dace9d90000000" + }, + "0x90F79bf6EB2c4f870365E785982E1f101E93b906": { + "balance": "0x3782dace9d90000000" + }, + "0x15d34AAf54267DB7D7c367839AAf71A00a2C6A65": { + "balance": "0x3782dace9d90000000" + }, + "0x9965507D1a55bcC2695C58ba16FB37d819B0A4dc": { + "balance": "0x3782dace9d90000000" + }, + "0x976EA74026E726554dB657fA54763abd0C3a0aa9": { + "balance": "0x3782dace9d90000000" + }, + "0x14dC79964da2C08b23698B3D3cc7Ca32193d9955": { + "balance": "0x3782dace9d90000000" + }, + "0x23618e81E3f5cdF7f54C3d65f7FBc0aBf5B21E8f": { + "balance": "0x3782dace9d90000000" + }, + "0xa0Ee7A142d267C1f36714E4a8F75612F20a79720": { + "balance": "0x3782dace9d90000000" + }, + "0xBcd4042DE499D14e55001CcbB24a551F3b954096": { + "balance": "0x3782dace9d90000000" + }, + "0x71bE63f3384f5fb98995898A86B02Fb2426c5788": { + "balance": "0x3782dace9d90000000" + }, + "0xFABB0ac9d68B0B445fB7357272Ff202C5651694a": { + "balance": "0x3782dace9d90000000" + }, + "0x1CBd3b2770909D4e10f157cABC84C7264073C9Ec": { + "balance": "0x3782dace9d90000000" + }, + "0xdF3e18d64BC6A983f673Ab319CCaE4f1a57C7097": { + "balance": "0x3782dace9d90000000" + }, + "0xcd3B766CCDd6AE721141F452C550Ca635964ce71": { + "balance": "0x3782dace9d90000000" + }, + "0x2546BcD3c84621e976D8185a91A922aE77ECEc30": { + "balance": "0x3782dace9d90000000" + }, + "0xbDA5747bFD65F08deb54cb465eB87D40e51B197E": { + "balance": "0x3782dace9d90000000" + }, + "0xdD2FD4581271e230360230F9337D5c0430Bf44C0": { + "balance": "0x3782dace9d90000000" + }, + "0x8626f6940E2eb28930eFb4CeF49B2d1F2C9C1199": { + "balance": "0x3782dace9d90000000" + }, + "0x0000777700000000000000000000000000000006": { + "contractName": "ProxiedAddressManager", + "storage": {}, + "code": "0x608060405234801561001057600080fd5b50600436106100625760003560e01c8063656b06a414610067578063715018a6146100b75780638da5cb5b146100c1578063decd8e39146100d2578063e1c7392a146100e5578063f2fde38b146100ed575b600080fd5b61009b610075366004610428565b60009182526065602090815260408084209284529190529020546001600160a01b031690565b6040516001600160a01b03909116815260200160405180910390f35b6100bf610100565b005b6033546001600160a01b031661009b565b6100bf6100e0366004610466565b610114565b6100bf610196565b6100bf6100fb36600461049b565b6102ac565b610108610322565b610112600061037c565b565b61011c610322565b600083815260656020908152604080832085845282529182902080546001600160a01b038581166001600160a01b0319831681179093558451928352169181018290529091849186917fe41a6e8584d6e19a0dfc5f9331be4ebe61b5f025d45da164c9ca6ee9b837cea9910160405180910390a350505050565b600054610100900460ff16158080156101b65750600054600160ff909116105b806101d05750303b1580156101d0575060005460ff166001145b6102385760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b60648201526084015b60405180910390fd5b6000805460ff19166001179055801561025b576000805461ff0019166101001790555b6102636103ce565b80156102a9576000805461ff0019169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b50565b6102b4610322565b6001600160a01b0381166103195760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b606482015260840161022f565b6102a98161037c565b6033546001600160a01b031633146101125760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015260640161022f565b603380546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b600054610100900460ff166103f55760405162461bcd60e51b815260040161022f906104bd565b610112600054610100900460ff1661041f5760405162461bcd60e51b815260040161022f906104bd565b6101123361037c565b6000806040838503121561043b57600080fd5b50508035926020909101359150565b80356001600160a01b038116811461046157600080fd5b919050565b60008060006060848603121561047b57600080fd5b83359250602084013591506104926040850161044a565b90509250925092565b6000602082840312156104ad57600080fd5b6104b68261044a565b9392505050565b6020808252602b908201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960408201526a6e697469616c697a696e6760a81b60608201526080019056fea26469706673582212201bde2ef0e6b00897cd2f3d30bc5c6844d34e123c3113dc0529e54f445274212064736f6c63430008140033", + "balance": "0x0" + }, + "0x1000777700000000000000000000000000000006": { + "contractName": "AddressManagerProxy", + "storage": { + "0x0000000000000000000000000000000000000000000000000000000000000000": "0x0000000000000000000000000000000000000000000000000000000000000001", + "0x0000000000000000000000000000000000000000000000000000000000000033": "0x000000000000000000000000f39fd6e51aad88f6f4ce6ab8827279cfffb92266", + "0x6b013a0e951a047258ecfbbfd8b9a49a53289bd1f7cc04707d44361932bc1ff4": "0x0000000000000000000000001000777700000000000000000000000000000001", + "0x6e6c3efa1ea957de4ff121455278e0e3ab0563ed7474b931f9489cdd3cf93cfa": "0x0000000000000000000000001000777700000000000000000000000000000004", + "0x8cccc85990ef13759554efad0e53e3e7cfd323061cc78328ecdf3a80ef0c1c3d": "0x0000000000000000000000001000777700000000000000000000000000000002", + "0xe131db906218d663e9e5119cd125a18454ae4e666188c1c443835b798601a79b": "0x0000000000000000000000001000777700000000000000000000000000000008", + "0xecbd41677124623fc1ea9b1265db03dcd2ea4e07c2d70860be83cf7d831d413f": "0x0000000000000000000000001000777700000000000000000000000000000009", + "0xb89e0d65684560eb877371fa3bbdc47dfc9efc7e113ec86ce9ae0fa1c43b85b9": "0x0000000000000000000000001000777700000000000000000000000000000003", + "0x37ecd6787fe0bc6398f481a64352c06039ac5637068ea40e2973573d1042f212": "0x0000000000000000000000001000777700000000000000000000000000000007", + "0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103": "0x70997970C51812dc3A010C7d01b50e0d17dc79C8", + "0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc": "0x0000777700000000000000000000000000000006" + }, + "code": "0x60806040526004361061004e5760003560e01c80633659cfe6146100655780634f1ef286146100855780635c60da1b146100985780638f283970146100c9578063f851a440146100e95761005d565b3661005d5761005b6100fe565b005b61005b6100fe565b34801561007157600080fd5b5061005b6100803660046106b3565b610118565b61005b6100933660046106ce565b610155565b3480156100a457600080fd5b506100ad6101bc565b6040516001600160a01b03909116815260200160405180910390f35b3480156100d557600080fd5b5061005b6100e43660046106b3565b6101ed565b3480156100f557600080fd5b506100ad61020d565b61010661022e565b6101166101116102c3565b6102cd565b565b6101206102f1565b6001600160a01b0316330361014d5761014a81604051806020016040528060008152506000610324565b50565b61014a6100fe565b61015d6102f1565b6001600160a01b031633036101b4576101af8383838080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525060019250610324915050565b505050565b6101af6100fe565b60006101c66102f1565b6001600160a01b031633036101e2576101dd6102c3565b905090565b6101ea6100fe565b90565b6101f56102f1565b6001600160a01b0316330361014d5761014a8161034f565b60006102176102f1565b6001600160a01b031633036101e2576101dd6102f1565b6102366102f1565b6001600160a01b031633036101165760405162461bcd60e51b815260206004820152604260248201527f5472616e73706172656e745570677261646561626c6550726f78793a2061646d60448201527f696e2063616e6e6f742066616c6c6261636b20746f2070726f78792074617267606482015261195d60f21b608482015260a4015b60405180910390fd5b60006101dd6103a3565b3660008037600080366000845af43d6000803e8080156102ec573d6000f35b3d6000fd5b60007fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035b546001600160a01b0316919050565b61032d836103cb565b60008251118061033a5750805b156101af57610349838361040b565b50505050565b7f7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f6103786102f1565b604080516001600160a01b03928316815291841660208301520160405180910390a161014a81610437565b60007f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc610315565b6103d4816104e0565b6040516001600160a01b038216907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b90600090a250565b606061043083836040518060600160405280602781526020016107c560279139610574565b9392505050565b6001600160a01b03811661049c5760405162461bcd60e51b815260206004820152602660248201527f455243313936373a206e65772061646d696e20697320746865207a65726f206160448201526564647265737360d01b60648201526084016102ba565b807fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035b80546001600160a01b0319166001600160a01b039290921691909117905550565b6001600160a01b0381163b61054d5760405162461bcd60e51b815260206004820152602d60248201527f455243313936373a206e657720696d706c656d656e746174696f6e206973206e60448201526c1bdd08184818dbdb9d1c9858dd609a1b60648201526084016102ba565b807f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc6104bf565b6060600080856001600160a01b0316856040516105919190610775565b600060405180830381855af49150503d80600081146105cc576040519150601f19603f3d011682016040523d82523d6000602084013e6105d1565b606091505b50915091506105e2868383876105ec565b9695505050505050565b6060831561065b578251600003610654576001600160a01b0385163b6106545760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e747261637400000060448201526064016102ba565b5081610665565b610665838361066d565b949350505050565b81511561067d5781518083602001fd5b8060405162461bcd60e51b81526004016102ba9190610791565b80356001600160a01b03811681146106ae57600080fd5b919050565b6000602082840312156106c557600080fd5b61043082610697565b6000806000604084860312156106e357600080fd5b6106ec84610697565b9250602084013567ffffffffffffffff8082111561070957600080fd5b818601915086601f83011261071d57600080fd5b81358181111561072c57600080fd5b87602082850101111561073e57600080fd5b6020830194508093505050509250925092565b60005b8381101561076c578181015183820152602001610754565b50506000910152565b60008251610787818460208701610751565b9190910192915050565b60208152600082518060208401526107b0816040850160208701610751565b601f01601f1916919091016040019291505056fe416464726573733a206c6f772d6c6576656c2064656c65676174652063616c6c206661696c6564a2646970667358221220e0c34caa93cb549737d2002fe0da3463bee0317add6c2f3da35498d4b65a974464736f6c63430008140033", + "balance": "0x0" + }, + "0x0000777700000000000000000000000000000001": { + "contractName": "ProxiedTaikoL2", + "storage": {}, + "code": "0x608060405234801561001057600080fd5b50600436106101585760003560e01c80638da5cb5b116100c3578063cce03bf31161007c578063cce03bf314610359578063da69d3db1461036c578063dac5df781461037f578063e8e2c5fb14610388578063f2fde38b146103c4578063f535bd56146103d757600080fd5b80638da5cb5b146102a95780639ee512f2146102ba578063a7e022d1146102d3578063a86f9d9e146102e6578063c3f909d4146102f9578063c7b969081461032757600080fd5b80635c975abb116101155780635c975abb146102245780636c6563f614610238578063715018a61461024b5780638456cb59146102535780638551f41e1461025b5780638cfb04591461027b57600080fd5b806310da37381461015d57806323ac7136146101975780632f980473146101aa5780633ab76e9f146101bd5780633f4ba83a146101e8578063591aad8a146101f2575b600080fd5b6101847f92954368afd3caa1f3ce3ead0069c1af414054aefe1ef9aeacc1bf426222ce3881565b6040519081526020015b60405180910390f35b6101846101a536600461147d565b610402565b60005b604051901515815260200161018e565b6065546101d0906001600160a01b031681565b6040516001600160a01b03909116815260200161018e565b6101f0610461565b005b610205610200366004611498565b6104df565b6040805160ff909416845260208401929092529082015260600161018e565b6101ad609754610100900460ff1660021490565b6101d06102463660046114de565b61071a565b6101f0610731565b6101f0610745565b610184610269366004611513565b60c96020526000908152604090205481565b61028e61028936600461147d565b6107be565b6040805182518152602092830151928101929092520161018e565b6033546001600160a01b03166101d0565b6101d071777735367b36bc9b61c50022d9d0700db4ec81565b6101846102e1366004611540565b610833565b6101d06102f4366004611573565b610865565b604080518082018252630393870080825260086020928301908152835191825251918101919091520161018e565b60cc5461034190600160801b90046001600160401b031681565b6040516001600160401b03909116815260200161018e565b6101f06103673660046115ab565b61087b565b6101f061037a3660046115e5565b610a3a565b61018460cb5481565b6103af610396366004611513565b60ca602052600090815260409020805460019091015482565b6040805192835260208301919091520161018e565b6101f06103d236600461162b565b610cf9565b60cc546103ea906001600160801b031681565b6040516001600160801b03909116815260200161018e565b600043826001600160401b03161061041c57506000919050565b6104286101004361165e565b826001600160401b03161061044557506001600160401b03164090565b506001600160401b0316600090815260c9602052604090205490565b610475609754610100900460ff1660021490565b6104925760405163bae6e2a960e01b815260040160405180910390fd5b61049a610d72565b6097805461ff0019166101001790556040513381527f5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa906020015b60405180910390a1565b60008060008360ff166001141580156104fc57508360ff16600214155b1561051a5760405163bcd2d90d60e01b815260040160405180910390fd5b8360ff1660011461054b577fc6047f9441ed7d6d3045406e95c07cd85c778e4b8cef3ca7abac09b95c709ee561056d565b7f79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f817985b915060008460ff166001146105a2577fad77eceea844778cb4376153fc8f06f12f1695df4585bf75bfb17ec19ce908186105c4565b7fb4a95509ce05fe8d45987859a067780d16a367c0e2cacf79cd301b93fb7179405b905060008560ff166001146105f9577f71620584f61c57e688bbd3fd7a39a036e588d962c4c830f3dacbc15c917e02f261061b565b7f45b59254b0320fd853f3f38ac574999e91bd75fd5e6cab9c22c5e71fc6d276e45b82880192831001905060ff86166001036106555761064e8282600170014551231950b75fc4402da1732fc9bebe19610dcc565b92506106c4565b61069d7f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a16106988484600170014551231950b75fc4402da1732fc9bebe19610dcc565b610e1b565b90925090506106c18282600170014551231950b75fc4402da1732fc9bebe19610dcc565b92505b7f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a0831115610711576107088370014551231950b75fc4402da1732fc9bebe1961165e565b92506001851894505b50509250925092565b6000610727848484610e3a565b90505b9392505050565b610739610d72565b6107436000610eee565b565b610759609754610100900460ff1660021490565b156107775760405163bae6e2a960e01b815260040160405180910390fd5b61077f610d72565b6097805461ff0019166102001790556040513381527f62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a258906020016104d5565b604080518082019091526000808252602082015260006001600160401b038316156107e957826107fd565b60cc54600160801b90046001600160401b03165b6001600160401b0316600090815260ca602090815260409182902082518084019093528054835260010154908201529392505050565b600061085d61085660408051808201909152630393870081526008602082015290565b8484610f40565b509392505050565b6000610872468484610e3a565b90505b92915050565b600054610100900460ff161580801561089b5750600054600160ff909116105b806108b55750303b1580156108b5575060005460ff166001145b61091d5760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b60648201526084015b60405180910390fd5b6000805460ff191660011790558015610940576000805461ff0019166101001790555b61094983611093565b60014611158061096057506001600160401b034610155b1561097e576040516306cffa2760e01b815260040160405180910390fd5b60014311156109a057604051635a0f9e4160e11b815260040160405180910390fd5b43156109c75760006109b360014361165e565b600081815260c96020526040902090409055505b60cc80546001600160801b0319166001600160801b0384161790556109eb436110b6565b5060cb558015610a35576000805461ff0019169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b505050565b831580610a45575082155b80610a5757506001600160401b038216155b80610a72575043600114158015610a72575063ffffffff8116155b15610a905760405163053fd54760e01b815260040160405180910390fd5b3371777735367b36bc9b61c50022d9d0700db4ec14610ac257604051636494e9f760e01b815260040160405180910390fd5b6000194301600080610ad3836110b6565b915091508160cb5414610af95760405163d719258d60e01b815260040160405180910390fd5b6000610b1960408051808201909152630393870081526008602082015290565b90506000610b28828888610f40565b60cc80546001600160801b0319166001600160801b03929092169190911790559050488114610b6a576040516336d54d4f60e11b815260040160405180910390fd5b610b866d7369676e616c5f7365727669636560901b6000610865565b6001600160a01b03166366ca2bc0896040518263ffffffff1660e01b8152600401610bb391815260200190565b6020604051808303816000875af1158015610bd2573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610bf69190611671565b50604080518a8152602081018a90526001600160401b038916917e4ce985b8852a486571d0545799251fd671adcf33b7854a5f0f6a6a2431a555910160405180910390a2600085815260c960209081526040808320884090819055815180830183528d81528084018d81526001600160401b038d1680875260ca865295849020915182555160019091015560cb87905560cc8054600160801b90950267ffffffffffffffff60801b198616811790915582519182526001600160801b03908116941693909317918301919091527fb01a20e23471fa4d881340e2b742c2f84cb2f7a714b34ba370b815478ae4aae0910160405180910390a1505050505050505050565b610d01610d72565b6001600160a01b038116610d665760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b6064820152608401610914565b610d6f81610eee565b50565b6033546001600160a01b031633146107435760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610914565b600060405160408152602080820152602060408201528460608201528560808201528360a08201528260c082015260208160e08360056107d05a03fa610e1157600080fd5b5195945050505050565b6000806000198385098385029250828110838203039150509250929050565b60655460405163195ac1a960e21b815260048101859052602481018490526000916001600160a01b03169063656b06a490604401602060405180830381865afa158015610e8b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610eaf919061168a565b905081158015610ec657506001600160a01b038116155b1561072a57604051631467050360e21b81526004810185905260248101849052604401610914565b603380546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b60cc5460009081906001600160801b03161561107e5760cc54600090610f769063ffffffff8616906001600160801b03166116a7565b60cc54909150600090600160801b90046001600160401b031615801590610fb2575060cc546001600160401b03600160801b9091048116908716115b15610fe05760cc54610fd490600160801b90046001600160401b0316876116ba565b6001600160401b031690505b6001600160801b03811615611037578651600090611007906001600160401b0316836116e1565b9050806001600160801b03168311611020576001611033565b6110336001600160801b0382168461165e565b9250505b611048826001600160801b03611149565b9250611079836001600160801b031688600001516001600160401b03168960200151611074919061170c565b61115e565b935050505b8160000361108b57600191505b935093915050565b61109b6111a9565b6110a48161121d565b506097805461ffff1916610101179055565b6000806110c1611441565b60005b60ff811080156110d75750806001018510155b15611109576000198186030180408360ff830661010081106110fb576110fb611739565b6020020152506001016110c4565b5046611fe08201526120008120925083408161112660ff8761174f565b610100811061113757611137611739565b60200201526120009020919391925050565b60008183116111585782610872565b50919050565b60008160000361118157604051636296f1b960e11b815260040160405180910390fd5b81670de0b6b3a76400006111958585611266565b61119f9190611763565b6108729190611763565b600054610100900460ff166112145760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201526a6e697469616c697a696e6760a81b6064820152608401610914565b61074333610eee565b6001600160a01b03811661124457604051638ed88b2560e01b815260040160405180910390fd5b606580546001600160a01b0319166001600160a01b0392909216919091179055565b6000808261127c670de0b6b3a76400008661170c565b6112869190611763565b9050680755bf798b4a1bf1e48111156112a55750680755bf798b4a1bf1e45b6112ae816112b6565b949350505050565b6000680248ce36a70cb26b3e1982136112d157506000919050565b680755bf798b4a1bf1e582126112fa57604051631a93c68960e11b815260040160405180910390fd5b6503782dace9d9604e83901b059150600060606bb17217f7d1cf79abc9e3b39884821b056001605f1b01901d6bb17217f7d1cf79abc9e3b39881029093036c240c330e9fb2d9cbaf0fd5aafb1981018102606090811d6d0277594991cfc85f6e2461837cd9018202811d6d1a521255e34f6a5061b25ef1c9c319018202811d6db1bbb201f443cf962f1a1d3db4a5018202811d6e02c72388d9f74f51a9331fed693f1419018202811d6e05180bb14799ab47a8a8cb2a527d57016d02d16720577bd19bf614176fe9ea6c10fe68e7fd37d0007b713f765084018402831d9081019084016d01d3967ed30fc4f89c02bab5708119010290911d6e0587f503bb6ea29d25fcb740196450019091026d360d7aeea093263ecc6e0ecb291760621b010574029d9dc38563c32e5c2f6dc192ee70ef65f9978af30260c3939093039290921c92915050565b604051806120000160405280610100906020820280368337509192915050565b80356001600160401b038116811461147857600080fd5b919050565b60006020828403121561148f57600080fd5b61087282611461565b600080604083850312156114ab57600080fd5b82359150602083013560ff811681146114c357600080fd5b809150509250929050565b8035801515811461147857600080fd5b6000806000606084860312156114f357600080fd5b833592506020840135915061150a604085016114ce565b90509250925092565b60006020828403121561152557600080fd5b5035919050565b803563ffffffff8116811461147857600080fd5b6000806040838503121561155357600080fd5b61155c83611461565b915061156a6020840161152c565b90509250929050565b6000806040838503121561158657600080fd5b8235915061156a602084016114ce565b6001600160a01b0381168114610d6f57600080fd5b600080604083850312156115be57600080fd5b82356115c981611596565b915060208301356001600160801b03811681146114c357600080fd5b600080600080608085870312156115fb57600080fd5b843593506020850135925061161260408601611461565b91506116206060860161152c565b905092959194509250565b60006020828403121561163d57600080fd5b813561072a81611596565b634e487b7160e01b600052601160045260246000fd5b8181038181111561087557610875611648565b60006020828403121561168357600080fd5b5051919050565b60006020828403121561169c57600080fd5b815161072a81611596565b8082018082111561087557610875611648565b6001600160401b038281168282160390808211156116da576116da611648565b5092915050565b6001600160801b0381811683821602808216919082811461170457611704611648565b505092915050565b808202811582820484141761087557610875611648565b634e487b7160e01b600052601260045260246000fd5b634e487b7160e01b600052603260045260246000fd5b60008261175e5761175e611723565b500690565b60008261177257611772611723565b50049056fea264697066735822122067c761821b434d92eb46ff2854c0c72a1806271bfe35071900eb95aefcd53b4264736f6c63430008140033", + "balance": "0x0" + }, + "0x1000777700000000000000000000000000000001": { + "contractName": "TaikoL2Proxy", + "storage": { + "0x0000000000000000000000000000000000000000000000000000000000000033": "0x000000000000000000000000f39fd6e51aad88f6f4ce6ab8827279cfffb92266", + "0x0000000000000000000000000000000000000000000000000000000000000097": "0x0000000000000000000000000000000000000000000000000000000000000101", + "0x00000000000000000000000000000000000000000000000000000000000000cb": "0xf167b245aa70c0a5e2f44cd65a94f2b1c5c9e8c8ab059940e4bf1c47d7a39557", + "0x00000000000000000000000000000000000000000000000000000000000000cc": "0x0000000000000000000000000000000000000000000000000000000000000001", + "0x0000000000000000000000000000000000000000000000000000000000000065": "0x0000000000000000000000001000777700000000000000000000000000000006", + "0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103": "0x70997970C51812dc3A010C7d01b50e0d17dc79C8", + "0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc": "0x0000777700000000000000000000000000000001" + }, + "code": "0x60806040526004361061004e5760003560e01c80633659cfe6146100655780634f1ef286146100855780635c60da1b146100985780638f283970146100c9578063f851a440146100e95761005d565b3661005d5761005b6100fe565b005b61005b6100fe565b34801561007157600080fd5b5061005b6100803660046106b3565b610118565b61005b6100933660046106ce565b610155565b3480156100a457600080fd5b506100ad6101bc565b6040516001600160a01b03909116815260200160405180910390f35b3480156100d557600080fd5b5061005b6100e43660046106b3565b6101ed565b3480156100f557600080fd5b506100ad61020d565b61010661022e565b6101166101116102c3565b6102cd565b565b6101206102f1565b6001600160a01b0316330361014d5761014a81604051806020016040528060008152506000610324565b50565b61014a6100fe565b61015d6102f1565b6001600160a01b031633036101b4576101af8383838080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525060019250610324915050565b505050565b6101af6100fe565b60006101c66102f1565b6001600160a01b031633036101e2576101dd6102c3565b905090565b6101ea6100fe565b90565b6101f56102f1565b6001600160a01b0316330361014d5761014a8161034f565b60006102176102f1565b6001600160a01b031633036101e2576101dd6102f1565b6102366102f1565b6001600160a01b031633036101165760405162461bcd60e51b815260206004820152604260248201527f5472616e73706172656e745570677261646561626c6550726f78793a2061646d60448201527f696e2063616e6e6f742066616c6c6261636b20746f2070726f78792074617267606482015261195d60f21b608482015260a4015b60405180910390fd5b60006101dd6103a3565b3660008037600080366000845af43d6000803e8080156102ec573d6000f35b3d6000fd5b60007fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035b546001600160a01b0316919050565b61032d836103cb565b60008251118061033a5750805b156101af57610349838361040b565b50505050565b7f7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f6103786102f1565b604080516001600160a01b03928316815291841660208301520160405180910390a161014a81610437565b60007f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc610315565b6103d4816104e0565b6040516001600160a01b038216907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b90600090a250565b606061043083836040518060600160405280602781526020016107c560279139610574565b9392505050565b6001600160a01b03811661049c5760405162461bcd60e51b815260206004820152602660248201527f455243313936373a206e65772061646d696e20697320746865207a65726f206160448201526564647265737360d01b60648201526084016102ba565b807fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035b80546001600160a01b0319166001600160a01b039290921691909117905550565b6001600160a01b0381163b61054d5760405162461bcd60e51b815260206004820152602d60248201527f455243313936373a206e657720696d706c656d656e746174696f6e206973206e60448201526c1bdd08184818dbdb9d1c9858dd609a1b60648201526084016102ba565b807f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc6104bf565b6060600080856001600160a01b0316856040516105919190610775565b600060405180830381855af49150503d80600081146105cc576040519150601f19603f3d011682016040523d82523d6000602084013e6105d1565b606091505b50915091506105e2868383876105ec565b9695505050505050565b6060831561065b578251600003610654576001600160a01b0385163b6106545760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e747261637400000060448201526064016102ba565b5081610665565b610665838361066d565b949350505050565b81511561067d5781518083602001fd5b8060405162461bcd60e51b81526004016102ba9190610791565b80356001600160a01b03811681146106ae57600080fd5b919050565b6000602082840312156106c557600080fd5b61043082610697565b6000806000604084860312156106e357600080fd5b6106ec84610697565b9250602084013567ffffffffffffffff8082111561070957600080fd5b818601915086601f83011261071d57600080fd5b81358181111561072c57600080fd5b87602082850101111561073e57600080fd5b6020830194508093505050509250925092565b60005b8381101561076c578181015183820152602001610754565b50506000910152565b60008251610787818460208701610751565b9190910192915050565b60208152600082518060208401526107b0816040850160208701610751565b601f01601f1916919091016040019291505056fe416464726573733a206c6f772d6c6576656c2064656c65676174652063616c6c206661696c6564a2646970667358221220e0c34caa93cb549737d2002fe0da3463bee0317add6c2f3da35498d4b65a974464736f6c63430008140033", + "balance": "0x0" + }, + "0x0000777700000000000000000000000000000004": { + "contractName": "ProxiedBridge", + "storage": {}, + "code": "0x6080604052600436106101395760003560e01c80635fc34de7116100ab578063a665077e1161006f578063a665077e1461039f578063a86f9d9e146103bf578063aedf6cd3146103df578063d0496d6a146103ff578063eefbf17e1461043f578063f2fde38b1461047757600080fd5b80635fc34de7146103165780636c6563f614610337578063715018a6146103575780638456cb591461036c5780638da5cb5b1461038157600080fd5b80633c6cf473116100fd5780633c6cf473146102145780633f4ba83a1461025157806340d0ff96146102665780634f5f9772146102865780635c975abb146102b65780635d0bd986146102d757600080fd5b80630be0b938146101455780631136c0501461016757806319ab453c146101875780631b5fd0ab146101a75780633ab76e9f146101dc57600080fd5b3661014057005b600080fd5b34801561015157600080fd5b50610165610160366004611c78565b610497565b005b34801561017357600080fd5b50610165610182366004611cca565b6106be565b34801561019357600080fd5b506101656101a2366004611d86565b610a6a565b3480156101b357600080fd5b506101c76101c2366004611cca565b610b82565b60405190151581526020015b60405180910390f35b3480156101e857600080fd5b506065546101fc906001600160a01b031681565b6040516001600160a01b0390911681526020016101d3565b34801561022057600080fd5b5061024461022f366004611da3565b60cb6020526000908152604090205460ff1681565b6040516101d39190611dd2565b34801561025d57600080fd5b50610165610be0565b34801561027257600080fd5b50610165610281366004611cca565b610c5e565b34801561029257600080fd5b506101c76102a1366004611da3565b60ca6020526000908152604090205460ff1681565b3480156102c257600080fd5b506101c7609754610100900460ff1660021490565b3480156102e357600080fd5b506102f76102f2366004611da3565b610f29565b6040805192151583526001600160a01b039091166020830152016101d3565b610329610324366004611dfa565b610f56565b6040516101d3929190611f6f565b34801561034357600080fd5b506101fc610352366004611f88565b6112d7565b34801561036357600080fd5b506101656112e4565b34801561037857600080fd5b506101656112f8565b34801561038d57600080fd5b506033546001600160a01b03166101fc565b3480156103ab57600080fd5b506101c76103ba366004611cca565b611371565b3480156103cb57600080fd5b506101fc6103da366004611fc1565b6113bc565b3480156103eb57600080fd5b506101c76103fa366004611dfa565b6113d2565b34801561040b57600080fd5b506104146114ab565b60408051825181526020808401516001600160a01b03169082015291810151908201526060016101d3565b34801561044b57600080fd5b5060c95461045f906001600160801b031681565b6040516001600160801b0390911681526020016101d3565b34801561048357600080fd5b50610165610492366004611d86565b611525565b60975460ff16600119016104be5760405163dfc60d8560e01b815260040160405180910390fd5b6097805460ff191660021790556104df609754610100900460ff1660021490565b156104fd5760405163bae6e2a960e01b815260040160405180910390fd5b816060013546811461052257604051631c6c777560e31b815260040160405180910390fd5b61012083013515806105315750815b156105775761054660a0840160808501611d86565b6001600160a01b0316336001600160a01b031614610577576040516372b6e1c360e11b815260040160405180910390fd5b60008360405160200161058a9190612182565b60408051601f19818403018152919052805160209091012090506001600082815260cb602052604090205460ff1660038111156105c9576105c9611dbc565b146105e757604051636e10a9f360e01b815260040160405180910390fd5b60006106026a195d1a195c97dd985d5b1d60aa1b60006113bc565b60405163ba0bbd9560e01b815230600482015260e087013560248201529091506001600160a01b0382169063ba0bbd9590604401600060405180830381600087803b15801561065057600080fd5b505af1158015610664573d6000803e3d6000fd5b5050505061067385835a61159e565b15610688576106838260026116e5565b6106aa565b6106938260036116e5565b6106aa6001600160a01b03821660e0870135611838565b50506097805460ff19166001179055505050565b60975460ff16600119016106e55760405163dfc60d8560e01b815260040160405180910390fd5b6097805460ff19166002179055610706609754610100900460ff1660021490565b156107245760405163bae6e2a960e01b815260040160405180910390fd5b826060013546811461074957604051631c6c777560e31b815260040160405180910390fd5b61012084013515801561077d575061076760a0850160808601611d86565b6001600160a01b0316336001600160a01b031614155b1561079b576040516372b6e1c360e11b815260040160405180910390fd5b6000846040516020016107ae9190612182565b60408051601f198184030181529190528051602090910120905060008082815260cb602052604090205460ff1660038111156107ec576107ec611dbc565b1461080a57604051630cfafbf960e01b815260040160405180910390fd5b600061081c82876040013587876118d3565b90508061083c57604051635ea5ecc760e01b815260040160405180910390fd5b60006108576a195d1a195c97dd985d5b1d60aa1b60006113bc565b90506001600160a01b03811663ba0bbd953061087c6101008b013560e08c01356121ab565b6040516001600160e01b031960e085901b1681526001600160a01b0390921660048301526024820152604401600060405180830381600087803b1580156108c257600080fd5b505af11580156108d6573d6000803e3d6000fd5b50600092508291503090506108f160c08b0160a08c01611d86565b6001600160a01b0316148061091e5750600061091360c08b0160a08c01611d86565b6001600160a01b0316145b1561093257506002905060e08801356109a1565b600061094460a08b0160808c01611d86565b6001600160a01b0316336001600160a01b03161461096757896101200135610969565b5a5b90506109768a878361159e565b15610984576002925061099f565b6001925061099f6001600160a01b03851660e08c0135611838565b505b6109ab85836116e5565b6000806109be60e08c0160c08d01611d86565b6001600160a01b0316146109e1576109dc60e08b0160c08c01611d86565b6109f1565b6109f160a08b0160808c01611d86565b90506001600160a01b0381163303610a2f576000610a14836101008d01356121ab565b9050610a296001600160a01b03831682611838565b50610a51565b610a3e336101008c0135611838565b610a516001600160a01b03821683611838565b50506097805460ff191660011790555050505050505050565b600054610100900460ff1615808015610a8a5750600054600160ff909116105b80610aa45750303b158015610aa4575060005460ff166001145b610b0c5760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b60648201526084015b60405180910390fd5b6000805460ff191660011790558015610b2f576000805461ff0019166101001790555b610b3882611982565b8015610b7e576000805461ff0019169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b5050565b600046846040013514610b9757506000610bd9565b610bd6610bca85604051602001610bae9190612182565b6040516020818303038152906040528051906020012060031890565b856060013585856118d3565b90505b9392505050565b610bf4609754610100900460ff1660021490565b610c115760405163bae6e2a960e01b815260040160405180910390fd5b610c196119a5565b6097805461ff0019166101001790556040513381527f5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa906020015b60405180910390a1565b60975460ff1660011901610c855760405163dfc60d8560e01b815260040160405180910390fd5b6097805460ff19166002179055610ca6609754610100900460ff1660021490565b15610cc45760405163bae6e2a960e01b815260040160405180910390fd5b8260400135468114610ce957604051631c6c777560e31b815260040160405180910390fd5b600084604051602001610cfc9190612182565b60408051601f198184030181529181528151602092830120600081815260ca90935291205490915060ff1615610d4557604051638759835d60e01b815260040160405180910390fd5b6000610d5a60038318876060013587876118d3565b905080610d7a5760405163f149234f60e01b815260040160405180910390fd5b600082815260ca60205260408120805460ff19166001179055610dac906a195d1a195c97dd985d5b1d60aa1b906113bc565b60405163ba0bbd9560e01b815230600482015260e088013560248201526001600160a01b03919091169063ba0bbd9590604401600060405180830381600087803b158015610df957600080fd5b505af1158015610e0d573d6000803e3d6000fd5b505050506000610e40630600bf7360e31b886020016020810190610e319190611d86565b6001600160a01b0316906119ff565b90508015610ec157610e586040880160208901611d86565b6001600160a01b0316633005fb988860e0013589866040518463ffffffff1660e01b8152600401610e8a9291906121be565b6000604051808303818588803b158015610ea357600080fd5b505af1158015610eb7573d6000803e3d6000fd5b5050505050610ee8565b610ee860e0880135610ed960a08a0160808b01611d86565b6001600160a01b031690611838565b60405183907fc6fbc1fa0145a394c9c414b2ae7bd634eb50dd888938bcd75692ae427b680fa290600090a250506097805460ff191660011790555050505050565b600080610f41836562726964676560d01b60016112d7565b6001600160a01b038116151594909350915050565b604080516101808101825260008082526020820181905291810182905260608082018390526080820183905260a0820183905260c0820183905260e0820183905261010082018390526101208201839052610140820181905261016082015260975460ff1660011901610fdc5760405163dfc60d8560e01b815260040160405180910390fd5b6097805460ff19166002179055610ffd609754610100900460ff1660021490565b1561101b5760405163bae6e2a960e01b815260040160405180910390fd5b600061102d60a0850160808601611d86565b6001600160a01b03160361105457604051633c4f94dd60e11b815260040160405180910390fd5b6000806110648560600135610f29565b915091508161108657604051631c6c777560e31b815260040160405180910390fd5b468560600135036110aa57604051631c6c777560e31b815260040160405180910390fd5b60006110bc60c0870160a08801611d86565b6001600160a01b0316036110e357604051636401c93560e11b815260040160405180910390fd5b6001600160a01b0381166110fd60c0870160a08801611d86565b6001600160a01b03160361112457604051636401c93560e11b815260040160405180910390fd5b600061113961010087013560e08801356121ab565b905034811461115b57604051634ac2abdf60e11b815260040160405180910390fd5b61117881610ed96a195d1a195c97dd985d5b1d60aa1b60006113bc565b611181866122ad565b60c980549195506001600160801b0390911690600061119f836123ab565b82546101009290920a6001600160801b038181021990931691831602179091551684523360208086019190915246604080870191909152516111e3918691016123d1565b6040516020818303038152906040528051906020012094506112176d7369676e616c5f7365727669636560901b60006113bc565b6001600160a01b03166366ca2bc0866040518263ffffffff1660e01b815260040161124491815260200190565b6020604051808303816000875af1158015611263573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061128791906123e4565b50847f769685e0f49529ee2429cb28b4b48bd962ff754c08a2849804458ad716d75dcf856040516112b891906123d1565b60405180910390a250506097805460ff19166001179055509092909150565b6000610bd6848484611a8e565b6112ec6119a5565b6112f66000611b42565b565b61130c609754610100900460ff1660021490565b1561132a5760405163bae6e2a960e01b815260040160405180910390fd5b6113326119a5565b6097805461ff0019166102001790556040513381527f62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a25890602001610c54565b60004684606001351461138657506000610bd9565b610bd68460405160200161139a9190612182565b60405160208183030381529060405280519060200120856040013585856118d3565b60006113c9468484611a8e565b90505b92915050565b6000468260400135146113e757506000919050565b6114036d7369676e616c5f7365727669636560901b60006113bc565b6001600160a01b03166332676bc630846040516020016114239190612182565b604051602081830303815290604052805190602001206040518363ffffffff1660e01b815260040161146a9291906001600160a01b03929092168252602082015260400190565b602060405180830381865afa158015611487573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906113cc91906123fd565b604080516060810182526000808252602082018190529181019190915260cc5415806114d9575060cc546001145b156114f757604051635ceed17360e01b815260040160405180910390fd5b506040805160608101825260cc54815260cd546001600160a01b0316602082015260ce549181019190915290565b61152d6119a5565b6001600160a01b0381166115925760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b6064820152608401610b03565b61159b81611b42565b50565b6000816000036115c1576040516308c2ad5360e01b815260040160405180910390fd5b60405180606001604052808481526020018560200160208101906115e59190611d86565b6001600160a01b039081168252604087810135602093840152835160cc559183015160cd80546001600160a01b03191691909216179055015160ce5561163160c0850160a08601611d86565b6001600160a01b03168260e086013561164e61014088018861241a565b60405161165c929190612461565b600060405180830381858888f193505050503d806000811461169a576040519150601f19603f3d011682016040523d82523d6000602084013e61169f565b606091505b5050604080516060810182526001808252602082018190526000199190920181905260cc82905560cd80546001600160a01b03191690921790915560ce55949350505050565b8060038111156116f7576116f7611dbc565b600083815260cb602052604090205460ff16600381111561171a5761171a611dbc565b03611723575050565b600082815260cb60205260409020805482919060ff1916600183600381111561174e5761174e611dbc565b0217905550817f6c51882bc2ed67617f77a1e9b9a25d2caad8448647ecb093b357a603b2575634826040516117839190611dd2565b60405180910390a2600381600381111561179f5761179f611dbc565b146117a8575050565b6117c46d7369676e616c5f7365727669636560901b60006113bc565b60405163019b28af60e61b81526003841860048201526001600160a01b0391909116906366ca2bc0906024016020604051808303816000875af115801561180f573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061183391906123e4565b505050565b6001600160a01b03821661185f57604051634c67134d60e11b815260040160405180910390fd5b6000826001600160a01b03168260405160006040518083038185875af1925050503d80600081146118ac576040519150601f19603f3d011682016040523d82523d6000602084013e6118b1565b606091505b505090508061183357604051634c67134d60e11b815260040160405180910390fd5b60006118f16d7369676e616c5f7365727669636560901b60006113bc565b6001600160a01b03166392824e9085611915876562726964676560d01b60006112d7565b8887876040518663ffffffff1660e01b8152600401611938959493929190612471565b602060405180830381865afa158015611955573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061197991906123fd565b95945050505050565b61198a611b94565b61199381611c08565b506097805461ffff1916610101179055565b6033546001600160a01b031633146112f65760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610b03565b60006001600160a01b0383163b611a18575060006113cc565b6040516301ffc9a760e01b81526001600160e01b0319831660048201526001600160a01b038416906301ffc9a790602401602060405180830381865afa925050508015611a82575060408051601f3d908101601f19168201909252611a7f918101906123fd565b60015b156113cc579392505050565b60655460405163195ac1a960e21b815260048101859052602481018490526000916001600160a01b03169063656b06a490604401602060405180830381865afa158015611adf573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611b03919061249f565b905081158015611b1a57506001600160a01b038116155b15610bd957604051631467050360e21b81526004810185905260248101849052604401610b03565b603380546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b600054610100900460ff16611bff5760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201526a6e697469616c697a696e6760a81b6064820152608401610b03565b6112f633611b42565b6001600160a01b038116611c2f57604051638ed88b2560e01b815260040160405180910390fd5b606580546001600160a01b0319166001600160a01b0392909216919091179055565b60006101808284031215611c6457600080fd5b50919050565b801515811461159b57600080fd5b60008060408385031215611c8b57600080fd5b823567ffffffffffffffff811115611ca257600080fd5b611cae85828601611c51565b9250506020830135611cbf81611c6a565b809150509250929050565b600080600060408486031215611cdf57600080fd5b833567ffffffffffffffff80821115611cf757600080fd5b611d0387838801611c51565b94506020860135915080821115611d1957600080fd5b818601915086601f830112611d2d57600080fd5b813581811115611d3c57600080fd5b876020828501011115611d4e57600080fd5b6020830194508093505050509250925092565b6001600160a01b038116811461159b57600080fd5b8035611d8181611d61565b919050565b600060208284031215611d9857600080fd5b81356113c981611d61565b600060208284031215611db557600080fd5b5035919050565b634e487b7160e01b600052602160045260246000fd5b6020810160048310611df457634e487b7160e01b600052602160045260246000fd5b91905290565b600060208284031215611e0c57600080fd5b813567ffffffffffffffff811115611e2357600080fd5b611e2f84828501611c51565b949350505050565b6000815180845260005b81811015611e5d57602081850181015186830182015201611e41565b506000602082860101526020601f19601f83011685010191505092915050565b80516001600160801b0316825260006101806020830151611ea960208601826001600160a01b03169052565b5060408301516040850152606083015160608501526080830151611ed860808601826001600160a01b03169052565b5060a0830151611ef360a08601826001600160a01b03169052565b5060c0830151611f0e60c08601826001600160a01b03169052565b5060e083015160e0850152610100808401518186015250610120808401518186015250610140808401518282870152611f4983870182611e37565b925050506101608084015185830382870152611f658382611e37565b9695505050505050565b828152604060208201526000610bd66040830184611e7d565b600080600060608486031215611f9d57600080fd5b83359250602084013591506040840135611fb681611c6a565b809150509250925092565b60008060408385031215611fd457600080fd5b823591506020830135611cbf81611c6a565b80356001600160801b0381168114611d8157600080fd5b6000808335601e1984360301811261201457600080fd5b830160208101925035905067ffffffffffffffff81111561203457600080fd5b80360382131561204357600080fd5b9250929050565b81835281816020850137506000828201602090810191909152601f909101601f19169091010190565b60006101806120928461208585611fe6565b6001600160801b03169052565b61209e60208401611d76565b6001600160a01b03811660208601525060408301356040850152606083013560608501526120ce60808401611d76565b6001600160a01b031660808501526120e860a08401611d76565b6001600160a01b031660a085015261210260c08401611d76565b6001600160a01b031660c085015260e083810135908501526101008084013590850152610120808401359085015261014061213f81850185611ffd565b8383880152612151848801828461204a565b935050505061016061216581850185611ffd565b8684038388015261217784828461204a565b979650505050505050565b6020815260006113c96020830184612073565b634e487b7160e01b600052601160045260246000fd5b808201808211156113cc576113cc612195565b6040815260006121d16040830185612073565b90508260208301529392505050565b634e487b7160e01b600052604160045260246000fd5b604051610180810167ffffffffffffffff8111828210171561221a5761221a6121e0565b60405290565b600082601f83011261223157600080fd5b813567ffffffffffffffff8082111561224c5761224c6121e0565b604051601f8301601f19908116603f01168101908282118183101715612274576122746121e0565b8160405283815286602085880101111561228d57600080fd5b836020870160208301376000602085830101528094505050505092915050565b600061018082360312156122c057600080fd5b6122c86121f6565b6122d183611fe6565b81526122df60208401611d76565b6020820152604083013560408201526060830135606082015261230460808401611d76565b608082015261231560a08401611d76565b60a082015261232660c08401611d76565b60c082015260e08381013590820152610100808401359082015261012080840135908201526101408084013567ffffffffffffffff8082111561236857600080fd5b61237436838801612220565b8385015261016092508286013591508082111561239057600080fd5b5061239d36828701612220565b918301919091525092915050565b60006001600160801b038083168181036123c7576123c7612195565b6001019392505050565b6020815260006113c96020830184611e7d565b6000602082840312156123f657600080fd5b5051919050565b60006020828403121561240f57600080fd5b81516113c981611c6a565b6000808335601e1984360301811261243157600080fd5b83018035915067ffffffffffffffff82111561244c57600080fd5b60200191503681900382131561204357600080fd5b8183823760009101908152919050565b85815260018060a01b038516602082015283604082015260806060820152600061217760808301848661204a565b6000602082840312156124b157600080fd5b81516113c981611d6156fea2646970667358221220bdf6e4c607be4929a07ffb57e3f5adbfaa96fc291580488d4c42c69696cb0c1264736f6c63430008140033", + "balance": "0x0" + }, + "0x1000777700000000000000000000000000000004": { + "contractName": "BridgeProxy", + "storage": { + "0x0000000000000000000000000000000000000000000000000000000000000000": "0x0000000000000000000000000000000000000000000000000000000000000001", + "0x0000000000000000000000000000000000000000000000000000000000000097": "0x0000000000000000000000000000000000000000000000000000000000000101", + "0x0000000000000000000000000000000000000000000000000000000000000033": "0x000000000000000000000000f39fd6e51aad88f6f4ce6ab8827279cfffb92266", + "0x0000000000000000000000000000000000000000000000000000000000000065": "0x0000000000000000000000001000777700000000000000000000000000000006", + "0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103": "0x70997970C51812dc3A010C7d01b50e0d17dc79C8", + "0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc": "0x0000777700000000000000000000000000000004" + }, + "code": "0x60806040526004361061004e5760003560e01c80633659cfe6146100655780634f1ef286146100855780635c60da1b146100985780638f283970146100c9578063f851a440146100e95761005d565b3661005d5761005b6100fe565b005b61005b6100fe565b34801561007157600080fd5b5061005b6100803660046106b3565b610118565b61005b6100933660046106ce565b610155565b3480156100a457600080fd5b506100ad6101bc565b6040516001600160a01b03909116815260200160405180910390f35b3480156100d557600080fd5b5061005b6100e43660046106b3565b6101ed565b3480156100f557600080fd5b506100ad61020d565b61010661022e565b6101166101116102c3565b6102cd565b565b6101206102f1565b6001600160a01b0316330361014d5761014a81604051806020016040528060008152506000610324565b50565b61014a6100fe565b61015d6102f1565b6001600160a01b031633036101b4576101af8383838080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525060019250610324915050565b505050565b6101af6100fe565b60006101c66102f1565b6001600160a01b031633036101e2576101dd6102c3565b905090565b6101ea6100fe565b90565b6101f56102f1565b6001600160a01b0316330361014d5761014a8161034f565b60006102176102f1565b6001600160a01b031633036101e2576101dd6102f1565b6102366102f1565b6001600160a01b031633036101165760405162461bcd60e51b815260206004820152604260248201527f5472616e73706172656e745570677261646561626c6550726f78793a2061646d60448201527f696e2063616e6e6f742066616c6c6261636b20746f2070726f78792074617267606482015261195d60f21b608482015260a4015b60405180910390fd5b60006101dd6103a3565b3660008037600080366000845af43d6000803e8080156102ec573d6000f35b3d6000fd5b60007fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035b546001600160a01b0316919050565b61032d836103cb565b60008251118061033a5750805b156101af57610349838361040b565b50505050565b7f7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f6103786102f1565b604080516001600160a01b03928316815291841660208301520160405180910390a161014a81610437565b60007f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc610315565b6103d4816104e0565b6040516001600160a01b038216907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b90600090a250565b606061043083836040518060600160405280602781526020016107c560279139610574565b9392505050565b6001600160a01b03811661049c5760405162461bcd60e51b815260206004820152602660248201527f455243313936373a206e65772061646d696e20697320746865207a65726f206160448201526564647265737360d01b60648201526084016102ba565b807fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035b80546001600160a01b0319166001600160a01b039290921691909117905550565b6001600160a01b0381163b61054d5760405162461bcd60e51b815260206004820152602d60248201527f455243313936373a206e657720696d706c656d656e746174696f6e206973206e60448201526c1bdd08184818dbdb9d1c9858dd609a1b60648201526084016102ba565b807f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc6104bf565b6060600080856001600160a01b0316856040516105919190610775565b600060405180830381855af49150503d80600081146105cc576040519150601f19603f3d011682016040523d82523d6000602084013e6105d1565b606091505b50915091506105e2868383876105ec565b9695505050505050565b6060831561065b578251600003610654576001600160a01b0385163b6106545760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e747261637400000060448201526064016102ba565b5081610665565b610665838361066d565b949350505050565b81511561067d5781518083602001fd5b8060405162461bcd60e51b81526004016102ba9190610791565b80356001600160a01b03811681146106ae57600080fd5b919050565b6000602082840312156106c557600080fd5b61043082610697565b6000806000604084860312156106e357600080fd5b6106ec84610697565b9250602084013567ffffffffffffffff8082111561070957600080fd5b818601915086601f83011261071d57600080fd5b81358181111561072c57600080fd5b87602082850101111561073e57600080fd5b6020830194508093505050509250925092565b60005b8381101561076c578181015183820152602001610754565b50506000910152565b60008251610787818460208701610751565b9190910192915050565b60208152600082518060208401526107b0816040850160208701610751565b601f01601f1916919091016040019291505056fe416464726573733a206c6f772d6c6576656c2064656c65676174652063616c6c206661696c6564a2646970667358221220e0c34caa93cb549737d2002fe0da3463bee0317add6c2f3da35498d4b65a974464736f6c63430008140033", + "balance": "0x0" + }, + "0x0000777700000000000000000000000000000002": { + "contractName": "ProxiedERC20Vault", + "storage": {}, + "code": "0x608060405260043610620001135760003560e01c8063715018a611620000a1578063a86f9d9e116200006c578063a86f9d9e1462000308578063c287e578146200032d578063cb03d23c1462000361578063e2dc90331462000378578063f2fde38b146200038f57600080fd5b8063715018a614620002805780638456cb5914620002985780638da5cb5b14620002b05780639aa8605c14620002d057600080fd5b80633f4ba83a11620000e25780633f4ba83a14620001db5780635c975abb14620001f357806367090ccf14620002165780636c6563f6146200025b57600080fd5b806301ffc9a7146200011857806319ab453c14620001625780633005fb9814620001895780633ab76e9f14620001a0575b600080fd5b3480156200012557600080fd5b506200014d6200013736600462002097565b6001600160e01b031916630600bf7360e31b1490565b60405190151581526020015b60405180910390f35b3480156200016f57600080fd5b506200018762000181366004620020d9565b620003b4565b005b620001876200019a366004620020f9565b620004d4565b348015620001ad57600080fd5b50606554620001c2906001600160a01b031681565b6040516001600160a01b03909116815260200162000159565b348015620001e857600080fd5b50620001876200074b565b3480156200020057600080fd5b506200014d609754610100900460ff1660021490565b3480156200022357600080fd5b50620001c26200023536600462002146565b60cb6020908152600092835260408084209091529082529020546001600160a01b031681565b3480156200026857600080fd5b50620001c26200027a36600462002188565b620007cd565b3480156200028d57600080fd5b5062000187620007e6565b348015620002a557600080fd5b5062000187620007fe565b348015620002bd57600080fd5b506033546001600160a01b0316620001c2565b348015620002dd57600080fd5b50620002f5620002ef366004620020d9565b6200087c565b6040516200015995949392919062002218565b3480156200031557600080fd5b50620001c2620003273660046200226d565b620009dd565b3480156200033a57600080fd5b506200014d6200034c366004620020d9565b60c96020526000908152604090205460ff1681565b620001876200037236600462002295565b620009f5565b62000187620003893660046200230a565b62000c69565b3480156200039c57600080fd5b5062000187620003ae366004620020d9565b62001056565b600054610100900460ff1615808015620003d55750600054600160ff909116105b80620003f15750303b158015620003f1575060005460ff166001145b6200045a5760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b60648201526084015b60405180910390fd5b6000805460ff1916600117905580156200047e576000805461ff0019166101001790555b6200048982620010d5565b8015620004d0576000805461ff0019169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b5050565b60975460ff1660011901620004fc5760405163dfc60d8560e01b815260040160405180910390fd5b6097805460ff191660021790556200051e609754610100900460ff1660021490565b156200053d5760405163bae6e2a960e01b815260040160405180910390fd5b6562726964676560d01b62000554816001620009dd565b6001600160a01b0316336001600160a01b0316146200058657604051630d85cccf60e11b815260040160405180910390fd5b6000806200059961014086018662002348565b620005a991600490829062002398565b810190620005b8919062002501565b919450909250506001600160a01b0383169050620005e9576040516303f8a7d360e01b815260040160405180910390fd5b8015620006a2576001600160a01b038216600090815260c9602052604090205460ff16156200067a57604051632770a7eb60e21b8152306004820152602481018290526001600160a01b03831690639dc29fac90604401600060405180830381600087803b1580156200065b57600080fd5b505af115801562000670573d6000803e3d6000fd5b50505050620006a2565b620006a26200069060a0870160808801620020d9565b6001600160a01b0384169083620010fc565b620006cd60e0860135620006bd60a0880160808901620020d9565b6001600160a01b03169062001155565b620006df60a0860160808701620020d9565b6001600160a01b0316847f75c5fedbd5fff6123ad9b70827e9742ea1eee996583d6e14249f1429fc4fd99384846040516200072f9291906001600160a01b03929092168252602082015260400190565b60405180910390a350506097805460ff19166001179055505050565b62000760609754610100900460ff1660021490565b6200077e5760405163bae6e2a960e01b815260040160405180910390fd5b62000788620011f4565b6097805461ff0019166101001790556040513381527f5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa906020015b60405180910390a1565b6000620007dc84848462001250565b90505b9392505050565b620007f0620011f4565b620007fc60006200130a565b565b62000813609754610100900460ff1660021490565b15620008325760405163bae6e2a960e01b815260040160405180910390fd5b6200083c620011f4565b6097805461ff0019166102001790556040513381527f62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a25890602001620007c3565b60ca6020526000908152604090208054600182015460028301805492936001600160a01b03831693600160a01b90930460ff1692909190620008be90620025ee565b80601f0160208091040260200160405190810160405280929190818152602001828054620008ec90620025ee565b80156200093d5780601f1062000911576101008083540402835291602001916200093d565b820191906000526020600020905b8154815290600101906020018083116200091f57829003601f168201915b5050505050908060030180546200095490620025ee565b80601f01602080910402602001604051908101604052809291908181526020018280546200098290620025ee565b8015620009d35780601f10620009a757610100808354040283529160200191620009d3565b820191906000526020600020905b815481529060010190602001808311620009b557829003601f168201915b5050505050905085565b6000620009ec46848462001250565b90505b92915050565b60975460ff166001190162000a1d5760405163dfc60d8560e01b815260040160405180910390fd5b6097805460ff1916600217905562000a3f609754610100900460ff1660021490565b1562000a5e5760405163bae6e2a960e01b815260040160405180910390fd5b6562726964676560d01b62000a75816001620009dd565b6001600160a01b0316336001600160a01b03161462000aa757604051630d85cccf60e11b815260040160405180910390fd5b60405163881107d960e01b81526a195c98cc8c17dd985d5b1d60aa1b6004820152306024820152600090736B9cDdfFBee4D2c5a6001C8d5cAf6A940CaEDCEA9063881107d990604401606060405180830381865af415801562000b0e573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062000b34919062002637565b905060004687350362000b715762000b536040880160208901620020d9565b905062000b6b6001600160a01b0382168686620010fc565b62000be5565b62000b7c876200135c565b6040516340c10f1960e01b81526001600160a01b03878116600483015260248201879052919250908216906340c10f1990604401600060405180830381600087803b15801562000bcb57600080fd5b505af115801562000be0573d6000803e3d6000fd5b505050505b62000bfa6001600160a01b0386163462001155565b815160408084015181519081526001600160a01b0384811660208301529181018790528188169291891691907f883b72735ca0ee2cdd2a462a393658b1a0b36ebd8756e4c22b7509a92ff86a029060600160405180910390a450506097805460ff191660011790555050505050565b60975460ff166001190162000c915760405163dfc60d8560e01b815260040160405180910390fd5b6097805460ff1916600217905562000cb3609754610100900460ff1660021490565b1562000cd25760405163bae6e2a960e01b815260040160405180910390fd5b80356a195c98cc8c17dd985d5b1d60aa1b62000cf56040840160208501620020d9565b62000d076060850160408601620020d9565b6001600160a01b038216158062000d3c575062000d2784846000620007cd565b6001600160a01b0316826001600160a01b0316145b1562000d5b5760405163def9481360e01b815260040160405180910390fd5b6001600160a01b03811662000d83576040516303f8a7d360e01b815260040160405180910390fd5b846060013560000362000da957604051634299323b60e11b815260040160405180910390fd5b604080516101808101825260008082526020820181905291810182905260608082018390526080820183905260a0820183905260c0820183905260e0820183905261010082018390526101208201839052610140820181905261016082015262000e3c3362000e1f60608a0160408b01620020d9565b62000e3160408b0160208c01620020d9565b8a60600135620013bb565b61014083019190915287356060830181905233608084015290925062000e73906a195c98cc8c17dd985d5b1d60aa1b6000620007cd565b6001600160a01b031660a080830191909152608088013561012083015262000e9f90880135346200269e565b60e08083019190915260a088013561010083015262000ec490880160c08901620020d9565b6001600160a01b031660c082015262000ee160e088018862002348565b8080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201829052506101608601949094525082915062000f3590506562726964676560d01b82620009dd565b6001600160a01b0316635fc34de734856040518363ffffffff1660e01b815260040162000f639190620026c0565b60006040518083038185885af115801562000f82573d6000803e3d6000fd5b50505050506040513d6000823e601f3d908101601f1916820160405262000fad919081019062002827565b909250905062000fc460408a0160208b01620020d9565b6001600160a01b031681608001516001600160a01b0316837f91462591aed3d13dcadac8ed73fdc175ec6e79b798ca205822e7ec33dc019e888c600001358d6040016020810190620010179190620020d9565b604080519283526001600160a01b039091166020830152810189905260600160405180910390a450506097805460ff1916600117905550505050505050565b62001060620011f4565b6001600160a01b038116620010c75760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b606482015260840162000451565b620010d2816200130a565b50565b620010df6200196b565b620010ea81620019e3565b506097805461ffff1916610101179055565b604080516001600160a01b038416602482015260448082018490528251808303909101815260649091019091526020810180516001600160e01b031663a9059cbb60e01b1790526200115090849062001a2d565b505050565b6001600160a01b0382166200117d57604051634c67134d60e11b815260040160405180910390fd5b6000826001600160a01b03168260405160006040518083038185875af1925050503d8060008114620011cc576040519150601f19603f3d011682016040523d82523d6000602084013e620011d1565b606091505b50509050806200115057604051634c67134d60e11b815260040160405180910390fd5b6033546001600160a01b03163314620007fc5760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015260640162000451565b60655460405163195ac1a960e21b815260048101859052602481018490526000916001600160a01b03169063656b06a490604401602060405180830381865afa158015620012a2573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620012c8919062002966565b905081158015620012e057506001600160a01b038116155b15620007df57604051631467050360e21b8152600481018590526024810184905260440162000451565b603380546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b8035600090815260cb602090815260408083209183916200138391908601908601620020d9565b6001600160a01b03908116825260208201929092526040016000205416905080620013b657620013b38262001b06565b90505b919050565b60606000620013fe6040518060a001604052806000815260200160006001600160a01b03168152602001600060ff16815260200160608152602001606081525090565b6001600160a01b038616600090815260c9602052604090205460ff161562001632576001600160a01b03868116600090815260ca6020908152604091829020825160a08101845281548152600182015494851692810192909252600160a01b90930460ff16918101919091526002820180549192916060840191906200148490620025ee565b80601f0160208091040260200160405190810160405280929190818152602001828054620014b290620025ee565b8015620015035780601f10620014d75761010080835404028352916020019162001503565b820191906000526020600020905b815481529060010190602001808311620014e557829003601f168201915b505050505081526020016003820180546200151e90620025ee565b80601f01602080910402602001604051908101604052809291908181526020018280546200154c90620025ee565b80156200159d5780601f1062001571576101008083540402835291602001916200159d565b820191906000526020600020905b8154815290600101906020018083116200157f57829003601f168201915b5050509190925250505060208101519091506001600160a01b0316620015c757620015c762002986565b604051632770a7eb60e21b8152336004820152602481018590526001600160a01b03871690639dc29fac90604401600060405180830381600087803b1580156200161057600080fd5b505af115801562001625573d6000803e3d6000fd5b505050508391506200190a565b60008690506040518060a00160405280468152602001886001600160a01b03168152602001826001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa15801562001696573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620016bc91906200299c565b60ff168152602001826001600160a01b03166395d89b416040518163ffffffff1660e01b8152600401600060405180830381865afa15801562001703573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526200172d9190810190620029bc565b8152602001826001600160a01b03166306fdde036040518163ffffffff1660e01b8152600401600060405180830381865afa15801562001771573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526200179b9190810190620029bc565b90526040516370a0823160e01b81523060048201529092506000906001600160a01b038316906370a0823190602401602060405180830381865afa158015620017e8573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200180e9190620029f4565b6040516323b872dd60e01b8152336004820152306024820152604481018890529091506001600160a01b038316906323b872dd906064016020604051808303816000875af115801562001865573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200188b919062002a0e565b506040516370a0823160e01b815230600482015281906001600160a01b038416906370a0823190602401602060405180830381865afa158015620018d3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620018f99190620029f4565b6200190591906200269e565b935050505b6040516332c0f48f60e21b906200192c9083908a908990879060240162002a2e565b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b0319909316929092179091529791965090945050505050565b600054610100900460ff16620019d85760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201526a6e697469616c697a696e6760a81b606482015260840162000451565b620007fc336200130a565b6001600160a01b03811662001a0b57604051638ed88b2560e01b815260040160405180910390fd5b606580546001600160a01b0319166001600160a01b0392909216919091179055565b600062001a84826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b031662001de29092919063ffffffff16565b80519091501562001150578080602001905181019062001aa5919062002a0e565b620011505760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6044820152691bdd081cdd58d8d9595960b21b606482015260840162000451565b60008062001b6360008460405160200162001b22919062002b3c565b604051602081830303815290604052805190602001206040518060200162001b4a9062002089565b601f1982820381018352601f9091011660405262001df3565b9050736B9cDdfFBee4D2c5a6001C8d5cAf6A940CaEDCEA6378adc0d68262001b936033546001600160a01b031690565b606554636c0db62b60e01b906001600160a01b031662001bba60408a0160208b01620020d9565b893562001bce60608c0160408d0162002bd4565b62001bdd60608d018d62002348565b62001bec60808f018f62002348565b60405160200162001c0598979695949392919062002bf4565b60408051601f198184030181529082905262001c25929160200162002c57565b6040516020818303038152906040526040518463ffffffff1660e01b815260040162001c549392919062002c8a565b602060405180830381865af415801562001c72573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062001c98919062002966565b6001600160a01b038116600090815260c960209081526040808320805460ff1916600117905560ca9091529020909250839062001cd6828262002de0565b50508235600090815260cb6020908152604080832085939092909162001d0291908801908801620020d9565b6001600160a01b03166001600160a01b0316815260200190815260200160002060006101000a8154816001600160a01b0302191690836001600160a01b03160217905550816001600160a01b031683602001602081019062001d659190620020d9565b6001600160a01b031684357fb6b427556e8cb0ebf9175da4bc48c64c4f56e44cfaf8c3ab5ebf8e2ea130907962001da0606088018862002348565b62001daf60808a018a62002348565b62001dc160608c0160408d0162002bd4565b60405162001dd495949392919062002e79565b60405180910390a450919050565b6060620007dc848460008562001efd565b60008347101562001e475760405162461bcd60e51b815260206004820152601d60248201527f437265617465323a20696e73756666696369656e742062616c616e6365000000604482015260640162000451565b815160000362001e9a5760405162461bcd60e51b815260206004820181905260248201527f437265617465323a2062797465636f6465206c656e677468206973207a65726f604482015260640162000451565b8282516020840186f590506001600160a01b038116620007df5760405162461bcd60e51b815260206004820152601960248201527f437265617465323a204661696c6564206f6e206465706c6f7900000000000000604482015260640162000451565b60608247101562001f605760405162461bcd60e51b815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f6044820152651c8818d85b1b60d21b606482015260840162000451565b600080866001600160a01b0316858760405162001f7e919062002eba565b60006040518083038185875af1925050503d806000811462001fbd576040519150601f19603f3d011682016040523d82523d6000602084013e62001fc2565b606091505b509150915062001fd58783838762001fe2565b925050505b949350505050565b60608315620020565782516000036200204e576001600160a01b0385163b6200204e5760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e7472616374000000604482015260640162000451565b508162001fda565b62001fda83838151156200206d5781518083602001fd5b8060405162461bcd60e51b815260040162000451919062002ed8565b6119868062002eee83390190565b600060208284031215620020aa57600080fd5b81356001600160e01b031981168114620007df57600080fd5b6001600160a01b0381168114620010d257600080fd5b600060208284031215620020ec57600080fd5b8135620007df81620020c3565b600080604083850312156200210d57600080fd5b82356001600160401b038111156200212457600080fd5b830161018081860312156200213857600080fd5b946020939093013593505050565b600080604083850312156200215a57600080fd5b8235915060208301356200216e81620020c3565b809150509250929050565b8015158114620010d257600080fd5b6000806000606084860312156200219e57600080fd5b83359250602084013591506040840135620021b98162002179565b809150509250925092565b60005b83811015620021e1578181015183820152602001620021c7565b50506000910152565b6000815180845262002204816020860160208601620021c4565b601f01601f19169290920160200192915050565b8581526001600160a01b038516602082015260ff8416604082015260a0606082018190526000906200224d90830185620021ea565b8281036080840152620022618185620021ea565b98975050505050505050565b600080604083850312156200228157600080fd5b8235915060208301356200216e8162002179565b60008060008060808587031215620022ac57600080fd5b84356001600160401b03811115620022c357600080fd5b850160a08188031215620022d657600080fd5b93506020850135620022e881620020c3565b92506040850135620022fa81620020c3565b9396929550929360600135925050565b6000602082840312156200231d57600080fd5b81356001600160401b038111156200233457600080fd5b82016101008185031215620007df57600080fd5b6000808335601e198436030181126200236057600080fd5b8301803591506001600160401b038211156200237b57600080fd5b6020019150368190038213156200239157600080fd5b9250929050565b60008085851115620023a957600080fd5b83861115620023b757600080fd5b5050820193919092039150565b634e487b7160e01b600052604160045260246000fd5b60405160a081016001600160401b0381118282101715620023ff57620023ff620023c4565b60405290565b60405161018081016001600160401b0381118282101715620023ff57620023ff620023c4565b604051601f8201601f191681016001600160401b0381118282101715620024565762002456620023c4565b604052919050565b60ff81168114620010d257600080fd5b60006001600160401b038211156200248a576200248a620023c4565b50601f01601f191660200190565b600082601f830112620024aa57600080fd5b8135620024c1620024bb826200246e565b6200242b565b818152846020838601011115620024d757600080fd5b816020850160208301376000918101602001919091529392505050565b8035620013b681620020c3565b600080600080608085870312156200251857600080fd5b84356001600160401b03808211156200253057600080fd5b9086019060a082890312156200254557600080fd5b6200254f620023da565b8235815260208301356200256381620020c3565b6020820152604083013562002578816200245e565b60408201526060830135828111156200259057600080fd5b6200259e8a82860162002498565b606083015250608083013582811115620025b757600080fd5b620025c58a82860162002498565b6080830152509550620025de91505060208601620024f4565b9250620022fa60408601620024f4565b600181811c908216806200260357607f821691505b6020821081036200262457634e487b7160e01b600052602260045260246000fd5b50919050565b8051620013b681620020c3565b6000606082840312156200264a57600080fd5b604051606081018181106001600160401b03821117156200266f576200266f620023c4565b6040528251815260208301516200268681620020c3565b60208201526040928301519281019290925250919050565b81810381811115620009ef57634e487b7160e01b600052601160045260246000fd5b60208152620026db6020820183516001600160801b03169052565b60006020830151620026f860408401826001600160a01b03169052565b50604083015160608301526060830151608083015260808301516200272860a08401826001600160a01b03169052565b5060a08301516001600160a01b03811660c08401525060c08301516001600160a01b03811660e08401525060e08301516101008381019190915283015161012080840191909152830151610140808401919091528301516101806101608085018290526200279b6101a0860184620021ea565b90860151858203601f190183870152909250620027b98382620021ea565b9695505050505050565b80516001600160801b0381168114620013b657600080fd5b600082601f830112620027ed57600080fd5b8151620027fe620024bb826200246e565b8181528460208386010111156200281457600080fd5b62001fda826020830160208701620021c4565b600080604083850312156200283b57600080fd5b8251915060208301516001600160401b03808211156200285a57600080fd5b9084019061018082870312156200287057600080fd5b6200287a62002405565b6200288583620027c3565b815262002895602084016200262a565b60208201526040830151604082015260608301516060820152620028bc608084016200262a565b6080820152620028cf60a084016200262a565b60a0820152620028e260c084016200262a565b60c082015260e083810151908201526101008084015190820152610120808401519082015261014080840151838111156200291c57600080fd5b6200292a89828701620027db565b82840152505061016080840151838111156200294557600080fd5b6200295389828701620027db565b8284015250508093505050509250929050565b6000602082840312156200297957600080fd5b8151620007df81620020c3565b634e487b7160e01b600052600160045260246000fd5b600060208284031215620029af57600080fd5b8151620007df816200245e565b600060208284031215620029cf57600080fd5b81516001600160401b03811115620029e657600080fd5b62001fda84828501620027db565b60006020828403121562002a0757600080fd5b5051919050565b60006020828403121562002a2157600080fd5b8151620007df8162002179565b60808152845160808201526000602086015160018060a01b0380821660a085015260ff60408901511660c08501526060880151915060a060e085015262002a7a610120850183620021ea565b91506080880151607f198584030161010086015262002a9a8382620021ea565b9188166020860152506001600160a01b0386166040850152915062002abc9050565b82606083015295945050505050565b6000808335601e1984360301811262002ae357600080fd5b83016020810192503590506001600160401b0381111562002b0357600080fd5b8036038213156200239157600080fd5b81835281816020850137506000828201602090810191909152601f909101601f19169091010190565b60208152813560208201526000602083013562002b5981620020c3565b6001600160a01b031660408381019190915283013562002b79816200245e565b60ff811660608401525062002b92606084018462002acb565b60a0608085015262002ba960c08501828462002b13565b91505062002bbb608085018562002acb565b848303601f190160a0860152620027b983828462002b13565b60006020828403121562002be757600080fd5b8135620007df816200245e565b6001600160a01b038981168252881660208201526040810187905260ff8616606082015260c06080820181905260009062002c33908301868862002b13565b82810360a084015262002c4881858762002b13565b9b9a5050505050505050505050565b6001600160e01b031983168152815160009062002c7c816004850160208701620021c4565b919091016004019392505050565b6001600160a01b0384811682528316602082015260606040820181905260009062002cb890830184620021ea565b95945050505050565b601f8211156200115057600081815260208120601f850160051c8101602086101562002cea5750805b601f850160051c820191505b8181101562002d0b5782815560010162002cf6565b505050505050565b6001600160401b0383111562002d2d5762002d2d620023c4565b62002d458362002d3e8354620025ee565b8362002cc1565b6000601f84116001811462002d7c576000851562002d635750838201355b600019600387901b1c1916600186901b17835562002dd9565b600083815260209020601f19861690835b8281101562002daf578685013582556020948501946001909201910162002d8d565b508682101562002dcd5760001960f88860031b161c19848701351681555b505060018560011b0183555b5050505050565b8135815560018101602083013562002df881620020c3565b8154604085013562002e0a816200245e565b60ff60a01b60a09190911b166001600160a01b03929092166001600160a81b0319919091161717905562002e42606083018362002348565b62002e5281836002860162002d13565b505062002e63608083018362002348565b62002e7381836003860162002d13565b50505050565b60608152600062002e8f60608301878962002b13565b828103602084015262002ea481868862002b13565b91505060ff831660408301529695505050505050565b6000825162002ece818460208701620021c4565b9190910192915050565b602081526000620009ec6020830184620021ea56fe608060405234801561001057600080fd5b5061001961001e565b6100de565b600054610100900460ff161561008a5760405162461bcd60e51b815260206004820152602760248201527f496e697469616c697a61626c653a20636f6e747261637420697320696e697469604482015266616c697a696e6760c81b606482015260840160405180910390fd5b60005460ff90811610156100dc576000805460ff191660ff9081179091556040519081527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b565b611899806100ed6000396000f3fe608060405234801561001057600080fd5b506004361061018e5760003560e01c80636c6563f6116100de57806395d89b4111610097578063a86f9d9e11610071578063a86f9d9e1461036d578063a9059cbb14610380578063dd62ed3e14610393578063f2fde38b146103a657600080fd5b806395d89b411461033f5780639dc29fac14610347578063a457c2d71461035a57600080fd5b80636c6563f6146102cf57806370a08231146102e2578063715018a61461030b5780637cf8ed0d146103135780638456cb59146103265780638da5cb5b1461032e57600080fd5b8063395093511161014b57806340c10f191161012557806340c10f191461028c57806349d126051461029f5780635c975abb146102a85780636c0db62b146102bc57600080fd5b806339509351146102445780633ab76e9f146102575780633f4ba83a1461028257600080fd5b806306fdde0314610193578063095ea7b3146101b157806318160ddd146101d457806323b872dd146101e657806326afaadd146101f9578063313ce5671461022f575b600080fd5b61019b6103b9565b6040516101a89190611366565b60405180910390f35b6101c46101bf3660046113ae565b6103f3565b60405190151581526020016101a8565b60cb545b6040519081526020016101a8565b6101c46101f43660046113da565b61040d565b61021060fb5460fc546001600160a01b0390911691565b604080516001600160a01b0390931683526020830191909152016101a8565b60fd5460405160ff90911681526020016101a8565b6101c46102523660046113ae565b61044d565b60655461026a906001600160a01b031681565b6040516001600160a01b0390911681526020016101a8565b61028a61046f565b005b61028a61029a3660046113ae565b6104ed565b6101d860fc5481565b6101c4609754610100900460ff1660021490565b61028a6102ca3660046114be565b610577565b61026a6102dd36600461157d565b61071d565b6101d86102f03660046115b2565b6001600160a01b0316600090815260c9602052604090205490565b61028a61072a565b60fb5461026a906001600160a01b031681565b61028a61073e565b6033546001600160a01b031661026a565b61019b6107b7565b61028a6103553660046113ae565b610849565b6101c46103683660046113ae565b6108ca565b61026a61037b3660046115cf565b610950565b6101c461038e3660046113ae565b61095d565b6101d86103a13660046115fb565b610992565b61028a6103b43660046115b2565b6109bd565b60606103c3610a36565b6103ce60fc54610a45565b6040516020016103df929190611634565b604051602081830303815290604052905090565b600033610401818585610ad8565b60019150505b92915050565b6000306001600160a01b0384160361043857604051636cfe544760e01b815260040160405180910390fd5b610443848484610bf4565b90505b9392505050565b6000336104018185856104608383610992565b61046a9190611672565b610ad8565b610483609754610100900460ff1660021490565b6104a05760405163bae6e2a960e01b815260040160405180910390fd5b6104a8610c0d565b6097805461ff0019166101001790556040513381527f5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa906020015b60405180910390a1565b6a195c98cc8c17dd985d5b1d60aa1b610507816001610950565b6001600160a01b0316336001600160a01b03161461053857604051630d85cccf60e11b815260040160405180910390fd5b6105428383610c67565b6040518281526001600160a01b03841690600090600080516020611844833981519152906020015b60405180910390a3505050565b600054610100900460ff16158080156105975750600054600160ff909116105b806105b15750303b1580156105b1575060005460ff166001145b6106195760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b60648201526084015b60405180910390fd5b6000805460ff19166001179055801561063c576000805461ff0019166101001790555b6001600160a01b0386161580610650575084155b8061065a57504685145b8061066457508251155b8061066e57508151155b1561068c57604051635d061ab760e11b815260040160405180910390fd5b61069587610d17565b61069f8284610d3a565b60fb80546001600160a01b0319166001600160a01b03881617905560fc85905560fd805460ff191660ff86161790558015610714576000805461ff0019169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b50505050505050565b6000610443848484610d6b565b610732610c0d565b61073c6000610e1f565b565b610752609754610100900460ff1660021490565b156107705760405163bae6e2a960e01b815260040160405180910390fd5b610778610c0d565b6097805461ff0019166102001790556040513381527f62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a258906020016104e3565b606060cd80546107c690611693565b80601f01602080910402602001604051908101604052809291908181526020018280546107f290611693565b801561083f5780601f106108145761010080835404028352916020019161083f565b820191906000526020600020905b81548152906001019060200180831161082257829003601f168201915b5050505050905090565b6a195c98cc8c17dd985d5b1d60aa1b610863816001610950565b6001600160a01b0316336001600160a01b03161461089457604051630d85cccf60e11b815260040160405180910390fd5b61089e8383610e71565b6040518281526000906001600160a01b038516906000805160206118448339815191529060200161056a565b600033816108d88286610992565b9050838110156109385760405162461bcd60e51b815260206004820152602560248201527f45524332303a2064656372656173656420616c6c6f77616e63652062656c6f77604482015264207a65726f60d81b6064820152608401610610565b6109458286868403610ad8565b506001949350505050565b6000610446468484610d6b565b6000306001600160a01b0384160361098857604051636cfe544760e01b815260040160405180910390fd5b6104468383610f90565b6001600160a01b03918216600090815260ca6020908152604080832093909416825291909152205490565b6109c5610c0d565b6001600160a01b038116610a2a5760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b6064820152608401610610565b610a3381610e1f565b50565b606060cc80546107c690611693565b60606000610a5283610f9e565b600101905060008167ffffffffffffffff811115610a7257610a7261141b565b6040519080825280601f01601f191660200182016040528015610a9c576020820181803683370190505b5090508181016020015b600019016f181899199a1a9b1b9c1cb0b131b232b360811b600a86061a8153600a8504945084610aa657509392505050565b6001600160a01b038316610b3a5760405162461bcd60e51b8152602060048201526024808201527f45524332303a20617070726f76652066726f6d20746865207a65726f206164646044820152637265737360e01b6064820152608401610610565b6001600160a01b038216610b9b5760405162461bcd60e51b815260206004820152602260248201527f45524332303a20617070726f766520746f20746865207a65726f206164647265604482015261737360f01b6064820152608401610610565b6001600160a01b03838116600081815260ca602090815260408083209487168084529482529182902085905590518481527f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925910161056a565b600033610c02858285611076565b6109458585856110f0565b6033546001600160a01b0316331461073c5760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610610565b6001600160a01b038216610cbd5760405162461bcd60e51b815260206004820152601f60248201527f45524332303a206d696e7420746f20746865207a65726f2061646472657373006044820152606401610610565b8060cb6000828254610ccf9190611672565b90915550506001600160a01b038216600081815260c96020908152604080832080548601905551848152600080516020611844833981519152910160405180910390a35b5050565b610d1f611289565b610d28816112b9565b506097805461ffff1916610101179055565b600054610100900460ff16610d615760405162461bcd60e51b8152600401610610906116cd565b610d138282611302565b60655460405163195ac1a960e21b815260048101859052602481018490526000916001600160a01b03169063656b06a490604401602060405180830381865afa158015610dbc573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610de09190611718565b905081158015610df757506001600160a01b038116155b1561044657604051631467050360e21b81526004810185905260248101849052604401610610565b603380546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b6001600160a01b038216610ed15760405162461bcd60e51b815260206004820152602160248201527f45524332303a206275726e2066726f6d20746865207a65726f206164647265736044820152607360f81b6064820152608401610610565b6001600160a01b038216600090815260c9602052604090205481811015610f455760405162461bcd60e51b815260206004820152602260248201527f45524332303a206275726e20616d6f756e7420657863656564732062616c616e604482015261636560f01b6064820152608401610610565b6001600160a01b038316600081815260c960209081526040808320868603905560cb8054879003905551858152919291600080516020611844833981519152910161056a565b505050565b6000336104018185856110f0565b60008072184f03e93ff9f4daa797ed6e38ed64bf6a1f0160401b8310610fdd5772184f03e93ff9f4daa797ed6e38ed64bf6a1f0160401b830492506040015b6d04ee2d6d415b85acef81000000008310611009576d04ee2d6d415b85acef8100000000830492506020015b662386f26fc10000831061102757662386f26fc10000830492506010015b6305f5e100831061103f576305f5e100830492506008015b612710831061105357612710830492506004015b60648310611065576064830492506002015b600a83106104075760010192915050565b60006110828484610992565b905060001981146110ea57818110156110dd5760405162461bcd60e51b815260206004820152601d60248201527f45524332303a20696e73756666696369656e7420616c6c6f77616e63650000006044820152606401610610565b6110ea8484848403610ad8565b50505050565b6001600160a01b0383166111545760405162461bcd60e51b815260206004820152602560248201527f45524332303a207472616e736665722066726f6d20746865207a65726f206164604482015264647265737360d81b6064820152608401610610565b6001600160a01b0382166111b65760405162461bcd60e51b815260206004820152602360248201527f45524332303a207472616e7366657220746f20746865207a65726f206164647260448201526265737360e81b6064820152608401610610565b6001600160a01b038316600090815260c960205260409020548181101561122e5760405162461bcd60e51b815260206004820152602660248201527f45524332303a207472616e7366657220616d6f756e7420657863656564732062604482015265616c616e636560d01b6064820152608401610610565b6001600160a01b03808516600081815260c9602052604080822086860390559286168082529083902080548601905591516000805160206118448339815191529061127c9086815260200190565b60405180910390a36110ea565b600054610100900460ff166112b05760405162461bcd60e51b8152600401610610906116cd565b61073c33610e1f565b6001600160a01b0381166112e057604051638ed88b2560e01b815260040160405180910390fd5b606580546001600160a01b0319166001600160a01b0392909216919091179055565b600054610100900460ff166113295760405162461bcd60e51b8152600401610610906116cd565b60cc6113358382611783565b5060cd610f8b8282611783565b60005b8381101561135d578181015183820152602001611345565b50506000910152565b6020815260008251806020840152611385816040850160208701611342565b601f01601f19169190910160400192915050565b6001600160a01b0381168114610a3357600080fd5b600080604083850312156113c157600080fd5b82356113cc81611399565b946020939093013593505050565b6000806000606084860312156113ef57600080fd5b83356113fa81611399565b9250602084013561140a81611399565b929592945050506040919091013590565b634e487b7160e01b600052604160045260246000fd5b600082601f83011261144257600080fd5b813567ffffffffffffffff8082111561145d5761145d61141b565b604051601f8301601f19908116603f011681019082821181831017156114855761148561141b565b8160405283815286602085880101111561149e57600080fd5b836020870160208301376000602085830101528094505050505092915050565b60008060008060008060c087890312156114d757600080fd5b86356114e281611399565b955060208701356114f281611399565b945060408701359350606087013560ff8116811461150f57600080fd5b9250608087013567ffffffffffffffff8082111561152c57600080fd5b6115388a838b01611431565b935060a089013591508082111561154e57600080fd5b5061155b89828a01611431565b9150509295509295509295565b8035801515811461157857600080fd5b919050565b60008060006060848603121561159257600080fd5b83359250602084013591506115a960408501611568565b90509250925092565b6000602082840312156115c457600080fd5b813561044681611399565b600080604083850312156115e257600080fd5b823591506115f260208401611568565b90509250929050565b6000806040838503121561160e57600080fd5b823561161981611399565b9150602083013561162981611399565b809150509250929050565b60008351611646818460208801611342565b6241c55b60e71b9083019081528351611666816004840160208801611342565b01600401949350505050565b8082018082111561040757634e487b7160e01b600052601160045260246000fd5b600181811c908216806116a757607f821691505b6020821081036116c757634e487b7160e01b600052602260045260246000fd5b50919050565b6020808252602b908201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960408201526a6e697469616c697a696e6760a81b606082015260800190565b60006020828403121561172a57600080fd5b815161044681611399565b601f821115610f8b57600081815260208120601f850160051c8101602086101561175c5750805b601f850160051c820191505b8181101561177b57828155600101611768565b505050505050565b815167ffffffffffffffff81111561179d5761179d61141b565b6117b1816117ab8454611693565b84611735565b602080601f8311600181146117e657600084156117ce5750858301515b600019600386901b1c1916600185901b17855561177b565b600085815260208120601f198616915b82811015611815578886015182559484019460019091019084016117f6565b50858210156118335787850151600019600388901b60f8161c191681555b5050505050600190811b0190555056feddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3efa2646970667358221220263570e5f6aad00cd73465157d1d2038ba0e55d481f9deb501998a5fc32f606364736f6c63430008140033a26469706673582212205e38ece0613387aa26f71c81ece84abd3f41ae813a8d5fffb5ffa1bc7caf343364736f6c63430008140033", + "balance": "0x0" + }, + "0x1000777700000000000000000000000000000002": { + "contractName": "ERC20VaultProxy", + "storage": { + "0x0000000000000000000000000000000000000000000000000000000000000000": "0x0000000000000000000000000000000000000000000000000000000000000001", + "0x0000000000000000000000000000000000000000000000000000000000000097": "0x0000000000000000000000000000000000000000000000000000000000000101", + "0x0000000000000000000000000000000000000000000000000000000000000033": "0x000000000000000000000000f39fd6e51aad88f6f4ce6ab8827279cfffb92266", + "0x0000000000000000000000000000000000000000000000000000000000000065": "0x0000000000000000000000001000777700000000000000000000000000000006", + "0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103": "0x70997970C51812dc3A010C7d01b50e0d17dc79C8", + "0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc": "0x0000777700000000000000000000000000000002" + }, + "code": "0x60806040526004361061004e5760003560e01c80633659cfe6146100655780634f1ef286146100855780635c60da1b146100985780638f283970146100c9578063f851a440146100e95761005d565b3661005d5761005b6100fe565b005b61005b6100fe565b34801561007157600080fd5b5061005b6100803660046106b3565b610118565b61005b6100933660046106ce565b610155565b3480156100a457600080fd5b506100ad6101bc565b6040516001600160a01b03909116815260200160405180910390f35b3480156100d557600080fd5b5061005b6100e43660046106b3565b6101ed565b3480156100f557600080fd5b506100ad61020d565b61010661022e565b6101166101116102c3565b6102cd565b565b6101206102f1565b6001600160a01b0316330361014d5761014a81604051806020016040528060008152506000610324565b50565b61014a6100fe565b61015d6102f1565b6001600160a01b031633036101b4576101af8383838080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525060019250610324915050565b505050565b6101af6100fe565b60006101c66102f1565b6001600160a01b031633036101e2576101dd6102c3565b905090565b6101ea6100fe565b90565b6101f56102f1565b6001600160a01b0316330361014d5761014a8161034f565b60006102176102f1565b6001600160a01b031633036101e2576101dd6102f1565b6102366102f1565b6001600160a01b031633036101165760405162461bcd60e51b815260206004820152604260248201527f5472616e73706172656e745570677261646561626c6550726f78793a2061646d60448201527f696e2063616e6e6f742066616c6c6261636b20746f2070726f78792074617267606482015261195d60f21b608482015260a4015b60405180910390fd5b60006101dd6103a3565b3660008037600080366000845af43d6000803e8080156102ec573d6000f35b3d6000fd5b60007fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035b546001600160a01b0316919050565b61032d836103cb565b60008251118061033a5750805b156101af57610349838361040b565b50505050565b7f7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f6103786102f1565b604080516001600160a01b03928316815291841660208301520160405180910390a161014a81610437565b60007f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc610315565b6103d4816104e0565b6040516001600160a01b038216907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b90600090a250565b606061043083836040518060600160405280602781526020016107c560279139610574565b9392505050565b6001600160a01b03811661049c5760405162461bcd60e51b815260206004820152602660248201527f455243313936373a206e65772061646d696e20697320746865207a65726f206160448201526564647265737360d01b60648201526084016102ba565b807fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035b80546001600160a01b0319166001600160a01b039290921691909117905550565b6001600160a01b0381163b61054d5760405162461bcd60e51b815260206004820152602d60248201527f455243313936373a206e657720696d706c656d656e746174696f6e206973206e60448201526c1bdd08184818dbdb9d1c9858dd609a1b60648201526084016102ba565b807f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc6104bf565b6060600080856001600160a01b0316856040516105919190610775565b600060405180830381855af49150503d80600081146105cc576040519150601f19603f3d011682016040523d82523d6000602084013e6105d1565b606091505b50915091506105e2868383876105ec565b9695505050505050565b6060831561065b578251600003610654576001600160a01b0385163b6106545760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e747261637400000060448201526064016102ba565b5081610665565b610665838361066d565b949350505050565b81511561067d5781518083602001fd5b8060405162461bcd60e51b81526004016102ba9190610791565b80356001600160a01b03811681146106ae57600080fd5b919050565b6000602082840312156106c557600080fd5b61043082610697565b6000806000604084860312156106e357600080fd5b6106ec84610697565b9250602084013567ffffffffffffffff8082111561070957600080fd5b818601915086601f83011261071d57600080fd5b81358181111561072c57600080fd5b87602082850101111561073e57600080fd5b6020830194508093505050509250925092565b60005b8381101561076c578181015183820152602001610754565b50506000910152565b60008251610787818460208701610751565b9190910192915050565b60208152600082518060208401526107b0816040850160208701610751565b601f01601f1916919091016040019291505056fe416464726573733a206c6f772d6c6576656c2064656c65676174652063616c6c206661696c6564a2646970667358221220e0c34caa93cb549737d2002fe0da3463bee0317add6c2f3da35498d4b65a974464736f6c63430008140033", + "balance": "0x0" + }, + "0x0000777700000000000000000000000000000008": { + "contractName": "ProxiedERC721Vault", + "storage": {}, + "code": "0x608060405260043610620001375760003560e01c80636c6563f611620000ad5780639aa8605c116200006c5780639aa8605c146200038f578063a86f9d9e14620003c6578063a9976baf14620003eb578063c287e5781462000402578063f2fde38b146200043657600080fd5b80636c6563f61462000303578063715018a614620003285780637333964314620003405780638456cb5914620003575780638da5cb5b146200036f57600080fd5b80633ab76e9f11620000fa5780633ab76e9f146200022b5780633f4ba83a146200026657806359f4a907146200027e5780635c975abb146200029b57806367090ccf14620002be57600080fd5b806301ffc9a7146200013c578063150b7a02146200018657806319ab453c14620001d05780632ca069a514620001f75780633005fb981462000214575b600080fd5b3480156200014957600080fd5b50620001716200015b366004620021db565b6001600160e01b031916630600bf7360e31b1490565b60405190151581526020015b60405180910390f35b3480156200019357600080fd5b50620001b6620001a53660046200221d565b630a85bd0160e11b95945050505050565b6040516001600160e01b031990911681526020016200017d565b348015620001dd57600080fd5b50620001f5620001ef366004620022c4565b6200045b565b005b3480156200020457600080fd5b50620001b6636cdb3d1360e11b81565b620001f562000225366004620022e4565b6200057b565b3480156200023857600080fd5b506065546200024d906001600160a01b031681565b6040516001600160a01b0390911681526020016200017d565b3480156200027357600080fd5b50620001f56200098e565b3480156200028b57600080fd5b50620001b66380ac58cd60e01b81565b348015620002a857600080fd5b5062000171609754610100900460ff1660021490565b348015620002cb57600080fd5b506200024d620002dd36600462002331565b60cb6020908152600092835260408084209091529082529020546001600160a01b031681565b3480156200031057600080fd5b506200024d6200032236600462002373565b62000a10565b3480156200033557600080fd5b50620001f562000a29565b620001f562000351366004620023af565b62000a41565b3480156200036457600080fd5b50620001f562000f5b565b3480156200037c57600080fd5b506033546001600160a01b03166200024d565b3480156200039c57600080fd5b50620003b4620003ae366004620022c4565b62000fd9565b6040516200017d949392919062002441565b348015620003d357600080fd5b506200024d620003e53660046200248c565b6200112c565b620001f5620003fc366004620025a6565b62001144565b3480156200040f57600080fd5b506200017162000421366004620022c4565b60c96020526000908152604090205460ff1681565b3480156200044357600080fd5b50620001f562000455366004620022c4565b620014a9565b600054610100900460ff16158080156200047c5750600054600160ff909116105b80620004985750303b15801562000498575060005460ff166001145b620005015760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b60648201526084015b60405180910390fd5b6000805460ff19166001179055801562000525576000805461ff0019166101001790555b620005308262001528565b801562000577576000805461ff0019169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b5050565b60975460ff1660011901620005a35760405163dfc60d8560e01b815260040160405180910390fd5b6097805460ff19166002179055620005c5609754610100900460ff1660021490565b15620005e45760405163bae6e2a960e01b815260040160405180910390fd5b6562726964676560d01b620005fb8160016200112c565b6001600160a01b0316336001600160a01b0316146200062d57604051630d85cccf60e11b815260040160405180910390fd5b60006200064160a0850160808601620022c4565b6001600160a01b031603620006695760405163016a294f60e41b815260040160405180910390fd5b468360400135146200068e57604051630a15fbb960e01b815260040160405180910390fd5b600080620006a161014086018662002644565b620006b191600490829062002694565b810190620006c09190620027fb565b6020840151939550935050506001600160a01b0316620006f3576040516303f8a7d360e01b815260040160405180910390fd5b6020808301516001600160a01b0316600090815260c9909152604090205460ff1615620007e25760005b8151811015620007db5760208301516001600160a01b03166340c10f196200074c60a0890160808a01620022c4565b8484815181106200076157620007616200284c565b60200260200101516040518363ffffffff1660e01b81526004016200079b9291906001600160a01b03929092168252602082015260400190565b600060405180830381600087803b158015620007b657600080fd5b505af1158015620007cb573d6000803e3d6000fd5b505050508060010190506200071d565b50620008ac565b60005b8151811015620008aa5760208301516001600160a01b03166342842e0e306200081560a08a0160808b01620022c4565b8585815181106200082a576200082a6200284c565b60209081029190910101516040516001600160e01b031960e086901b1681526001600160a01b0393841660048201529290911660248301526044820152606401600060405180830381600087803b1580156200088557600080fd5b505af11580156200089a573d6000803e3d6000fd5b50505050806001019050620007e5565b505b620008d760e0860135620008c760a0880160808901620022c4565b6001600160a01b0316906200154f565b620008e960a0860160808701620022c4565b6001600160a01b0316847fe8449897bd3c926a272780c39ba13e77bf7a2c823479a75bfbc13ef631183dfd84602001518460006001600160401b03811115620009365762000936620024b4565b60405190808252806020026020018201604052801562000960578160200160208202803683370190505b5060405162000972939291906200289f565b60405180910390a350506097805460ff19166001179055505050565b620009a3609754610100900460ff1660021490565b620009c15760405163bae6e2a960e01b815260040160405180910390fd5b620009cb620015f3565b6097805461ff0019166101001790556040513381527f5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa906020015b60405180910390a1565b600062000a1f8484846200164f565b90505b9392505050565b62000a33620015f3565b62000a3f600062001709565b565b60975460ff166001190162000a695760405163dfc60d8560e01b815260040160405180910390fd5b6097805460ff1916600217905562000a8b609754610100900460ff1660021490565b1562000aaa5760405163bae6e2a960e01b815260040160405180910390fd5b736B9cDdfFBee4D2c5a6001C8d5cAf6A940CaEDCEA63c0619cc262000ad36080840184620028e3565b62000ae26060860186620028e3565b60016040518663ffffffff1660e01b815260040162000b0695949392919062002962565b60006040518083038186803b15801562000b1f57600080fd5b505af415801562000b34573d6000803e3d6000fd5b50505050736B9cDdfFBee4D2c5a6001C8d5cAf6A940CaEDCEA6393522e3e62000b7383600001356b195c98cdcc8c57dd985d5b1d60a21b600062000a10565b62000b856040850160208601620022c4565b62000b976060860160408701620022c4565b60405160e085901b6001600160e01b03191681526001600160a01b0393841660048201529183166024830152909116604482015260640160006040518083038186803b15801562000be757600080fd5b505af415801562000bfc573d6000803e3d6000fd5b5062000c3192506380ac58cd60e01b915062000c2190506060840160408501620022c4565b6001600160a01b0316906200175b565b62000c4f57604051633ee915f560e11b815260040160405180910390fd5b600062000c606080830183620028e3565b80806020026020016040519081016040528093929190818152602001838360200280828437600092018290525093945062000ca6925050506060840160408501620022c4565b9050600062000cb96060850185620028e3565b80806020026020016040519081016040528093929190818152602001838360200280828437600092018290525060408051610180810182528281526020810183905290810182905260608082018390526080820183905260a0820183905260c0820183905260e082018390526101008201839052610120820192909252610140810182905261016081019190915293945062000d5492505050565b8435606082015262000d673386620017f0565b610140820152336080820152606081015162000d95906b195c98cdcc8c57dd985d5b1d60a21b600062000a10565b6001600160a01b031660a08083019190915285013561012082015262000dc060c086013534620029a2565b60e08083019190915260c08601356101008084019190915262000de991908701908701620022c4565b6001600160a01b031660c082015262000e0761010086018662002644565b8080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201829052506101608601949094525082915062000e5b90506562726964676560d01b826200112c565b6001600160a01b0316635fc34de734856040518363ffffffff1660e01b815260040162000e899190620029c4565b60006040518083038185885af115801562000ea8573d6000803e3d6000fd5b50505050506040513d6000823e601f3d908101601f1916820160405262000ed3919081019062002b36565b909250905062000eea6040880160208901620022c4565b6001600160a01b031681608001516001600160a01b0316837f5e54276405062454e6226625b28a6fea0a838d6b054e38955667234afb3345a3846060015189898c60405162000f3d949392919062002c75565b60405180910390a450506097805460ff191660011790555050505050565b62000f70609754610100900460ff1660021490565b1562000f8f5760405163bae6e2a960e01b815260040160405180910390fd5b62000f99620015f3565b6097805461ff0019166102001790556040513381527f62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a2589060200162000a06565b60ca6020526000908152604090208054600182015460028301805492936001600160a01b03909216926200100d9062002cb5565b80601f01602080910402602001604051908101604052809291908181526020018280546200103b9062002cb5565b80156200108c5780601f1062001060576101008083540402835291602001916200108c565b820191906000526020600020905b8154815290600101906020018083116200106e57829003601f168201915b505050505090806003018054620010a39062002cb5565b80601f0160208091040260200160405190810160405280929190818152602001828054620010d19062002cb5565b8015620011225780601f10620010f65761010080835404028352916020019162001122565b820191906000526020600020905b8154815290600101906020018083116200110457829003601f168201915b5050505050905084565b60006200113b4684846200164f565b90505b92915050565b60975460ff16600119016200116c5760405163dfc60d8560e01b815260040160405180910390fd5b6097805460ff191660021790556200118e609754610100900460ff1660021490565b15620011ad5760405163bae6e2a960e01b815260040160405180910390fd5b6562726964676560d01b620011c48160016200112c565b6001600160a01b0316336001600160a01b031614620011f657604051630d85cccf60e11b815260040160405180910390fd5b60405163881107d960e01b81526b195c98cdcc8c57dd985d5b1d60a21b6004820152306024820152600090736B9cDdfFBee4D2c5a6001C8d5cAf6A940CaEDCEA9063881107d990604401606060405180830381865af41580156200125e573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062001284919062002cf1565b90506000468735036200135f57620012a36040880160208901620022c4565b905060005b84518110156200135857816001600160a01b03166323b872dd3088888581518110620012d857620012d86200284c565b60209081029190910101516040516001600160e01b031960e086901b1681526001600160a01b0393841660048201529290911660248301526044820152606401600060405180830381600087803b1580156200133357600080fd5b505af115801562001348573d6000803e3d6000fd5b50505050806001019050620012a8565b506200141a565b6200136a8762001d1f565b905060005b84518110156200141857816001600160a01b03166340c10f19878784815181106200139e576200139e6200284c565b60200260200101516040518363ffffffff1660e01b8152600401620013d89291906001600160a01b03929092168252602082015260400190565b600060405180830381600087803b158015620013f357600080fd5b505af115801562001408573d6000803e3d6000fd5b505050508060010190506200136f565b505b6200142f6001600160a01b038616346200154f565b815160408301516001600160a01b0380881692908916917f0f60c37489e435ed8490c30b01c1fa57e62510e88b351b75796ad3d95babe6b1908589600060405190808252806020026020018201604052801562001496578160200160208202803683370190505b5060405162000f3d949392919062002c75565b620014b3620015f3565b6001600160a01b0381166200151a5760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b6064820152608401620004f8565b620015258162001709565b50565b6200153262001d88565b6200153d8162001e00565b506097805461ffff1916610101179055565b6001600160a01b0382166200157757604051634c67134d60e11b815260040160405180910390fd5b6000826001600160a01b03168260405160006040518083038185875af1925050503d8060008114620015c6576040519150601f19603f3d011682016040523d82523d6000602084013e620015cb565b606091505b5050905080620015ee57604051634c67134d60e11b815260040160405180910390fd5b505050565b6033546001600160a01b0316331462000a3f5760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401620004f8565b60655460405163195ac1a960e21b815260048101859052602481018490526000916001600160a01b03169063656b06a490604401602060405180830381865afa158015620016a1573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620016c7919062002d58565b905081158015620016df57506001600160a01b038116155b1562000a2257604051631467050360e21b81526004810185905260248101849052604401620004f8565b603380546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b60006001600160a01b0383163b62001776575060006200113e565b6040516301ffc9a760e01b81526001600160e01b0319831660048201526001600160a01b038416906301ffc9a790602401602060405180830381865afa925050508015620017e3575060408051601f3d908101601f19168201909252620017e09181019062002d78565b60015b156200113e579392505050565b6040805160808101825260008082526020820152606091810182905280820182905260c96000620018286060860160408701620022c4565b6001600160a01b0316815260208101919091526040016000205460ff161562001ab05760ca6000620018616060860160408701620022c4565b6001600160a01b0390811682526020808301939093526040918201600020825160808101845281548152600182015490921693820193909352600283018054919392840191620018b19062002cb5565b80601f0160208091040260200160405190810160405280929190818152602001828054620018df9062002cb5565b8015620019305780601f10620019045761010080835404028352916020019162001930565b820191906000526020600020905b8154815290600101906020018083116200191257829003601f168201915b505050505081526020016003820180546200194b9062002cb5565b80601f0160208091040260200160405190810160405280929190818152602001828054620019799062002cb5565b8015620019ca5780601f106200199e57610100808354040283529160200191620019ca565b820191906000526020600020905b815481529060010190602001808311620019ac57829003601f168201915b505050505081525050905060005b620019e76060850185620028e3565b905081101562001aa95762001a036060850160408601620022c4565b6001600160a01b0316639dc29fac8662001a216060880188620028e3565b8581811062001a345762001a346200284c565b6040516001600160e01b031960e087901b1681526001600160a01b0390941660048501526020029190910135602483015250604401600060405180830381600087803b15801562001a8457600080fd5b505af115801562001a99573d6000803e3d6000fd5b50505050806001019050620019d8565b5062001ca4565b600062001ac46060850160408601620022c4565b9050604051806080016040528046815260200185604001602081019062001aec9190620022c4565b6001600160a01b03168152602001826001600160a01b03166395d89b416040518163ffffffff1660e01b8152600401600060405180830381865afa15801562001b39573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405262001b63919081019062002d98565b8152602001826001600160a01b03166306fdde036040518163ffffffff1660e01b8152600401600060405180830381865afa15801562001ba7573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405262001bd1919081019062002d98565b9052915060005b62001be76060860186620028e3565b905081101562001ca1576001600160a01b0382166323b872dd873062001c1160608a018a620028e3565b8681811062001c245762001c246200284c565b6040516001600160e01b031960e088901b1681526001600160a01b03958616600482015294909316602485015250602090910201356044820152606401600060405180830381600087803b15801562001c7c57600080fd5b505af115801562001c91573d6000803e3d6000fd5b5050505080600101905062001bd8565b50505b63a9976baf60e01b818562001cc06040870160208801620022c4565b62001ccf6060880188620028e3565b60405160240162001ce595949392919062002e27565b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b031990931692909217909152949350505050565b8035600090815260cb6020908152604080832091839162001d4691908601908601620022c4565b6001600160a01b0390811682526020820192909252604001600020541690508062001d835762001d8062001d7a8362002e74565b62001e4a565b90505b919050565b600054610100900460ff1662001df55760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201526a6e697469616c697a696e6760a81b6064820152608401620004f8565b62000a3f3362001709565b6001600160a01b03811662001e2857604051638ed88b2560e01b815260040160405180910390fd5b606580546001600160a01b0319166001600160a01b0392909216919091179055565b60008062001ea760008460405160200162001e66919062002e82565b604051602081830303815290604052805190602001206040518060200162001e8e90620021cd565b601f1982820381018352601f90910116604052620020c3565b9050736B9cDdfFBee4D2c5a6001C8d5cAf6A940CaEDCEA6378adc0d68262001ed76033546001600160a01b031690565b60655460208089015189516040808c015160608d0151915163689ccd8d60e11b9662001f13966001600160a01b03909116959493910162002e97565b60408051601f198184030181529082905262001f33929160200162002ee0565b6040516020818303038152906040526040518463ffffffff1660e01b815260040162001f629392919062002f13565b602060405180830381865af415801562001f80573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062001fa6919062002d58565b6001600160a01b03818116600090815260c9602090815260408083208054600160ff19909116811790915560ca835292819020885181559188015192820180546001600160a01b03191693909416929092179092558501519193508491600282019062002014908262002f93565b50606082015160038201906200202b908262002f93565b50508351600090815260cb6020908152604080832082880180516001600160a01b039081168652919093529281902080546001600160a01b031916878516908117909155915187518289015160608a015193519496509190941693927f2da3c4d305298f6df3653c23d98b4c055f72f7e6f981b2c477ccbec92b1ee57992620020b592916200305f565b60405180910390a450919050565b600083471015620021175760405162461bcd60e51b815260206004820152601d60248201527f437265617465323a20696e73756666696369656e742062616c616e63650000006044820152606401620004f8565b81516000036200216a5760405162461bcd60e51b815260206004820181905260248201527f437265617465323a2062797465636f6465206c656e677468206973207a65726f6044820152606401620004f8565b8282516020840186f590506001600160a01b03811662000a225760405162461bcd60e51b815260206004820152601960248201527f437265617465323a204661696c6564206f6e206465706c6f79000000000000006044820152606401620004f8565b611f9b806200308983390190565b600060208284031215620021ee57600080fd5b81356001600160e01b0319811681146200113b57600080fd5b6001600160a01b03811681146200152557600080fd5b6000806000806000608086880312156200223657600080fd5b8535620022438162002207565b94506020860135620022558162002207565b93506040860135925060608601356001600160401b03808211156200227957600080fd5b818801915088601f8301126200228e57600080fd5b8135818111156200229e57600080fd5b896020828501011115620022b157600080fd5b9699959850939650602001949392505050565b600060208284031215620022d757600080fd5b81356200113b8162002207565b60008060408385031215620022f857600080fd5b82356001600160401b038111156200230f57600080fd5b830161018081860312156200232357600080fd5b946020939093013593505050565b600080604083850312156200234557600080fd5b823591506020830135620023598162002207565b809150509250929050565b80151581146200152557600080fd5b6000806000606084860312156200238957600080fd5b83359250602084013591506040840135620023a48162002364565b809150509250925092565b600060208284031215620023c257600080fd5b81356001600160401b03811115620023d957600080fd5b820161012081850312156200113b57600080fd5b60005b838110156200240a578181015183820152602001620023f0565b50506000910152565b600081518084526200242d816020860160208601620023ed565b601f01601f19169290920160200192915050565b8481526001600160a01b03841660208201526080604082018190526000906200246d9083018562002413565b828103606084015262002481818562002413565b979650505050505050565b60008060408385031215620024a057600080fd5b823591506020830135620023598162002364565b634e487b7160e01b600052604160045260246000fd5b60405161018081016001600160401b0381118282101715620024f057620024f0620024b4565b60405290565b604051601f8201601f191681016001600160401b0381118282101715620025215762002521620024b4565b604052919050565b600082601f8301126200253b57600080fd5b813560206001600160401b03821115620025595762002559620024b4565b8160051b6200256a828201620024f6565b92835284810182019282810190878511156200258557600080fd5b83870192505b8483101562002481578235825291830191908301906200258b565b60008060008060808587031215620025bd57600080fd5b84356001600160401b0380821115620025d557600080fd5b9086019060808289031215620025ea57600080fd5b909450602086013590620025fe8262002207565b909350604086013590620026128262002207565b909250606086013590808211156200262957600080fd5b50620026388782880162002529565b91505092959194509250565b6000808335601e198436030181126200265c57600080fd5b8301803591506001600160401b038211156200267757600080fd5b6020019150368190038213156200268d57600080fd5b9250929050565b60008085851115620026a557600080fd5b83861115620026b357600080fd5b5050820193919092039150565b60006001600160401b03821115620026dc57620026dc620024b4565b50601f01601f191660200190565b600082601f830112620026fc57600080fd5b8135620027136200270d82620026c0565b620024f6565b8181528460208386010111156200272957600080fd5b816020850160208301376000918101602001919091529392505050565b6000608082840312156200275957600080fd5b604051608081016001600160401b0382821081831117156200277f576200277f620024b4565b8160405282935084358352602085013591506200279c8262002207565b8160208401526040850135915080821115620027b757600080fd5b620027c586838701620026ea565b60408401526060850135915080821115620027df57600080fd5b50620027ee85828601620026ea565b6060830152505092915050565b600080600080608085870312156200281257600080fd5b84356001600160401b03808211156200282a57600080fd5b620028388883890162002746565b955060208701359150620025fe8262002207565b634e487b7160e01b600052603260045260246000fd5b600081518084526020808501945080840160005b83811015620028945781518752958201959082019060010162002876565b509495945050505050565b6001600160a01b0384168152606060208201819052600090620028c59083018562002862565b8281036040840152620028d9818562002862565b9695505050505050565b6000808335601e19843603018112620028fb57600080fd5b8301803591506001600160401b038211156200291657600080fd5b6020019150600581901b36038213156200268d57600080fd5b81835260006001600160fb1b038311156200294957600080fd5b8260051b80836020870137939093016020019392505050565b606081526000620029786060830187896200292f565b82810360208401526200298d8186886200292f565b91505082151560408301529695505050505050565b818103818111156200113e57634e487b7160e01b600052601160045260246000fd5b60208152620029df6020820183516001600160801b03169052565b60006020830151620029fc60408401826001600160a01b03169052565b506040830151606083015260608301516080830152608083015162002a2c60a08401826001600160a01b03169052565b5060a08301516001600160a01b03811660c08401525060c08301516001600160a01b03811660e08401525060e083015161010083810191909152830151610120808401919091528301516101408084019190915283015161018061016080850182905262002a9f6101a086018462002413565b90860151858203601f190183870152909250620028d9838262002413565b80516001600160801b038116811462001d8357600080fd5b805162001d838162002207565b600082601f83011262002af457600080fd5b815162002b056200270d82620026c0565b81815284602083860101111562002b1b57600080fd5b62002b2e826020830160208701620023ed565b949350505050565b6000806040838503121562002b4a57600080fd5b8251915060208301516001600160401b038082111562002b6957600080fd5b90840190610180828703121562002b7f57600080fd5b62002b89620024ca565b62002b948362002abd565b815262002ba46020840162002ad5565b6020820152604083015160408201526060830151606082015262002bcb6080840162002ad5565b608082015262002bde60a0840162002ad5565b60a082015262002bf160c0840162002ad5565b60c082015260e0838101519082015261010080840151908201526101208084015190820152610140808401518381111562002c2b57600080fd5b62002c398982870162002ae2565b828401525050610160808401518381111562002c5457600080fd5b62002c628982870162002ae2565b8284015250508093505050509250929050565b8481526001600160a01b038416602082015260806040820181905260009062002ca19083018562002862565b828103606084015262002481818562002862565b600181811c9082168062002cca57607f821691505b60208210810362002ceb57634e487b7160e01b600052602260045260246000fd5b50919050565b60006060828403121562002d0457600080fd5b604051606081018181106001600160401b038211171562002d295762002d29620024b4565b60405282518152602083015162002d408162002207565b60208201526040928301519281019290925250919050565b60006020828403121562002d6b57600080fd5b81516200113b8162002207565b60006020828403121562002d8b57600080fd5b81516200113b8162002364565b60006020828403121562002dab57600080fd5b81516001600160401b0381111562002dc257600080fd5b62002b2e8482850162002ae2565b8051825260018060a01b036020820151166020830152600060408201516080604085015262002e03608085018262002413565b90506060830151848203606086015262002e1e828262002413565b95945050505050565b60808152600062002e3c608083018862002dd0565b6001600160a01b03878116602085015286166040840152828103606084015262002e688185876200292f565b98975050505050505050565b600062001d80368362002746565b6020815260006200113b602083018462002dd0565b6001600160a01b038681168252851660208201526040810184905260a06060820181905260009062002ecc9083018562002413565b828103608084015262002e68818562002413565b6001600160e01b031983168152815160009062002f05816004850160208701620023ed565b919091016004019392505050565b6001600160a01b0384811682528316602082015260606040820181905260009062002e1e9083018462002413565b601f821115620015ee57600081815260208120601f850160051c8101602086101562002f6a5750805b601f850160051c820191505b8181101562002f8b5782815560010162002f76565b505050505050565b81516001600160401b0381111562002faf5762002faf620024b4565b62002fc78162002fc0845462002cb5565b8462002f41565b602080601f83116001811462002fff576000841562002fe65750858301515b600019600386901b1c1916600185901b17855562002f8b565b600085815260208120601f198616915b8281101562003030578886015182559484019460019091019084016200300f565b50858210156200304f5787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b60408152600062003074604083018562002413565b828103602084015262002e1e81856200241356fe608060405234801561001057600080fd5b5061001961001e565b6100de565b600054610100900460ff161561008a5760405162461bcd60e51b815260206004820152602760248201527f496e697469616c697a61626c653a20636f6e747261637420697320696e697469604482015266616c697a696e6760c81b606482015260840160405180910390fd5b60005460ff90811610156100dc576000805460ff191660ff9081179091556040519081527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b565b611eae806100ed6000396000f3fe608060405234801561001057600080fd5b50600436106101c45760003560e01c806370a08231116100f9578063a22cb46511610097578063c87b56dd11610071578063c87b56dd146103c0578063d1399b1a146103e1578063e985e9c5146103f4578063f2fde38b1461043157600080fd5b8063a22cb46514610387578063a86f9d9e1461039a578063b88d4fde146103ad57600080fd5b80638456cb59116100d35780638456cb59146103535780638da5cb5b1461035b57806395d89b411461036c5780639dc29fac1461037457600080fd5b806370a0823114610324578063715018a6146103375780637cf8ed0d1461033f57600080fd5b806340c10f19116101665780635c975abb116101405780635c975abb146102b25780636352211e146102c657806367e828bf146102d95780636c6563f61461031157600080fd5b806340c10f191461027457806342842e0e1461028757806349d126051461029a57600080fd5b8063095ea7b3116101a2578063095ea7b31461023157806323b872dd146102465780633ab76e9f146102595780633f4ba83a1461026c57600080fd5b806301ffc9a7146101c957806306fdde03146101f1578063081812fc14610206575b600080fd5b6101dc6101d7366004611762565b610444565b60405190151581526020015b60405180910390f35b6101f9610496565b6040516101e891906117cf565b6102196102143660046117e2565b6104d1565b6040516001600160a01b0390911681526020016101e8565b61024461023f366004611810565b6104f8565b005b61024461025436600461183c565b610612565b606554610219906001600160a01b031681565b610244610646565b610244610282366004611810565b6106c4565b61024461029536600461183c565b610745565b6102a461012e5481565b6040519081526020016101e8565b6101dc609754610100900460ff1660021490565b6102196102d43660046117e2565b610760565b6102f261012d5461012e546001600160a01b0390911691565b604080516001600160a01b0390931683526020830191909152016101e8565b61021961031f366004611892565b6107c0565b6102a46103323660046118c7565b6107d7565b61024461085d565b61012d54610219906001600160a01b031681565b610244610871565b6033546001600160a01b0316610219565b6101f96108ea565b610244610382366004611810565b61097c565b6102446103953660046118e4565b610a36565b6102196103a8366004611919565b610a45565b6102446103bb3660046119c8565b610a52565b6101f96103ce3660046117e2565b5060408051602081019091526000815290565b6102446103ef366004611a68565b610a8a565b6101dc610402366004611afb565b6001600160a01b0391821660009081526101006020908152604080832093909416825291909152205460ff1690565b61024461043f3660046118c7565b610c1d565b60006001600160e01b031982166380ac58cd60e01b148061047557506001600160e01b03198216635b5e139f60e01b145b8061049057506301ffc9a760e01b6001600160e01b03198316145b92915050565b60606104a0610c96565b6104ac61012e54610ca5565b6040516020016104bd929190611b34565b604051602081830303815290604052905090565b60006104dc82610d38565b50600090815260ff60205260409020546001600160a01b031690565b600061050382610760565b9050806001600160a01b0316836001600160a01b0316036105755760405162461bcd60e51b815260206004820152602160248201527f4552433732313a20617070726f76616c20746f2063757272656e74206f776e656044820152603960f91b60648201526084015b60405180910390fd5b336001600160a01b038216148061059157506105918133610402565b6106035760405162461bcd60e51b815260206004820152603d60248201527f4552433732313a20617070726f76652063616c6c6572206973206e6f7420746f60448201527f6b656e206f776e6572206f7220617070726f76656420666f7220616c6c000000606482015260840161056c565b61060d8383610d97565b505050565b306001600160a01b0383160361063b57604051636cfe544760e01b815260040160405180910390fd5b61060d838383610e05565b61065a609754610100900460ff1660021490565b6106775760405163bae6e2a960e01b815260040160405180910390fd5b61067f610e36565b6097805461ff0019166101001790556040513381527f5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa906020015b60405180910390a1565b6b195c98cdcc8c57dd985d5b1d60a21b6106df816001610a45565b6001600160a01b0316336001600160a01b03161461071057604051630d85cccf60e11b815260040160405180910390fd5b61071a8383610e90565b60405182906001600160a01b03851690600090600080516020611e59833981519152908290a4505050565b61060d83838360405180602001604052806000815250610a52565b600081815260fd60205260408120546001600160a01b0316806104905760405162461bcd60e51b8152602060048201526018602482015277115490cdcc8c4e881a5b9d985b1a59081d1bdad95b88125160421b604482015260640161056c565b60006107cd848484611009565b90505b9392505050565b60006001600160a01b0382166108415760405162461bcd60e51b815260206004820152602960248201527f4552433732313a2061646472657373207a65726f206973206e6f7420612076616044820152683634b21037bbb732b960b91b606482015260840161056c565b506001600160a01b0316600090815260fe602052604090205490565b610865610e36565b61086f60006110bd565b565b610885609754610100900460ff1660021490565b156108a35760405163bae6e2a960e01b815260040160405180910390fd5b6108ab610e36565b6097805461ff0019166102001790556040513381527f62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a258906020016106ba565b606060fc80546108f990611b72565b80601f016020809104026020016040519081016040528092919081815260200182805461092590611b72565b80156109725780601f1061094757610100808354040283529160200191610972565b820191906000526020600020905b81548152906001019060200180831161095557829003601f168201915b5050505050905090565b6b195c98cdcc8c57dd985d5b1d60a21b610997816001610a45565b6001600160a01b0316336001600160a01b0316146109c857604051630d85cccf60e11b815260040160405180910390fd5b826001600160a01b03166109db83610760565b6001600160a01b031614610a02576040516302dca79760e41b815260040160405180910390fd5b610a0b8261110f565b60405182906000906001600160a01b03861690600080516020611e59833981519152908390a4505050565b610a41338383611192565b5050565b60006107d0468484611009565b610a5c3383611261565b610a785760405162461bcd60e51b815260040161056c90611bac565b610a84848484846112e1565b50505050565b600054610100900460ff1615808015610aaa5750600054600160ff909116105b80610ac45750303b158015610ac4575060005460ff166001145b610b275760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b606482015260840161056c565b6000805460ff191660011790558015610b4a576000805461ff0019166101001790555b6001600160a01b0385161580610b5e575083155b80610b6857504684145b80610b7257508251155b80610b7c57508151155b15610b9a57604051635d061ab760e11b815260040160405180910390fd5b610ba386611314565b610bad8284611337565b61012d80546001600160a01b0319166001600160a01b03871617905561012e8490558015610c15576000805461ff0019169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b505050505050565b610c25610e36565b6001600160a01b038116610c8a5760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b606482015260840161056c565b610c93816110bd565b50565b606060fb80546108f990611b72565b60606000610cb283611368565b600101905060008167ffffffffffffffff811115610cd257610cd261193c565b6040519080825280601f01601f191660200182016040528015610cfc576020820181803683370190505b5090508181016020015b600019016f181899199a1a9b1b9c1cb0b131b232b360811b600a86061a8153600a8504945084610d0657509392505050565b600081815260fd60205260409020546001600160a01b0316610c935760405162461bcd60e51b8152602060048201526018602482015277115490cdcc8c4e881a5b9d985b1a59081d1bdad95b88125160421b604482015260640161056c565b600081815260ff6020526040902080546001600160a01b0319166001600160a01b0384169081179091558190610dcc82610760565b6001600160a01b03167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92560405160405180910390a45050565b610e0f3382611261565b610e2b5760405162461bcd60e51b815260040161056c90611bac565b61060d838383611440565b6033546001600160a01b0316331461086f5760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015260640161056c565b6001600160a01b038216610ee65760405162461bcd60e51b815260206004820181905260248201527f4552433732313a206d696e7420746f20746865207a65726f2061646472657373604482015260640161056c565b600081815260fd60205260409020546001600160a01b031615610f4b5760405162461bcd60e51b815260206004820152601c60248201527f4552433732313a20746f6b656e20616c7265616479206d696e74656400000000604482015260640161056c565b600081815260fd60205260409020546001600160a01b031615610fb05760405162461bcd60e51b815260206004820152601c60248201527f4552433732313a20746f6b656e20616c7265616479206d696e74656400000000604482015260640161056c565b6001600160a01b038216600081815260fe602090815260408083208054600101905584835260fd90915280822080546001600160a01b031916841790555183929190600080516020611e59833981519152908290a45050565b60655460405163195ac1a960e21b815260048101859052602481018490526000916001600160a01b03169063656b06a490604401602060405180830381865afa15801561105a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061107e9190611bf9565b90508115801561109557506001600160a01b038116155b156107d057604051631467050360e21b8152600481018590526024810184905260440161056c565b603380546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b600061111a82610760565b905061112582610760565b600083815260ff6020908152604080832080546001600160a01b03199081169091556001600160a01b03851680855260fe8452828520805460001901905587855260fd90935281842080549091169055519293508492600080516020611e59833981519152908390a45050565b816001600160a01b0316836001600160a01b0316036111f35760405162461bcd60e51b815260206004820152601960248201527f4552433732313a20617070726f766520746f2063616c6c657200000000000000604482015260640161056c565b6001600160a01b0383811660008181526101006020908152604080832094871680845294825291829020805460ff191686151590811790915591519182527f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c31910160405180910390a3505050565b60008061126d83610760565b9050806001600160a01b0316846001600160a01b031614806112b557506001600160a01b038082166000908152610100602090815260408083209388168352929052205460ff165b806112d95750836001600160a01b03166112ce846104d1565b6001600160a01b0316145b949350505050565b6112ec848484611440565b6112f884848484611592565b610a845760405162461bcd60e51b815260040161056c90611c16565b61131c611693565b611325816116c3565b506097805461ffff1916610101179055565b600054610100900460ff1661135e5760405162461bcd60e51b815260040161056c90611c68565b610a41828261170c565b60008072184f03e93ff9f4daa797ed6e38ed64bf6a1f0160401b83106113a75772184f03e93ff9f4daa797ed6e38ed64bf6a1f0160401b830492506040015b6d04ee2d6d415b85acef810000000083106113d3576d04ee2d6d415b85acef8100000000830492506020015b662386f26fc1000083106113f157662386f26fc10000830492506010015b6305f5e1008310611409576305f5e100830492506008015b612710831061141d57612710830492506004015b6064831061142f576064830492506002015b600a83106104905760010192915050565b826001600160a01b031661145382610760565b6001600160a01b0316146114795760405162461bcd60e51b815260040161056c90611cb3565b6001600160a01b0382166114db5760405162461bcd60e51b8152602060048201526024808201527f4552433732313a207472616e7366657220746f20746865207a65726f206164646044820152637265737360e01b606482015260840161056c565b826001600160a01b03166114ee82610760565b6001600160a01b0316146115145760405162461bcd60e51b815260040161056c90611cb3565b600081815260ff6020908152604080832080546001600160a01b03199081169091556001600160a01b0387811680865260fe855283862080546000190190559087168086528386208054600101905586865260fd9094528285208054909216841790915590518493600080516020611e5983398151915291a4505050565b60006001600160a01b0384163b1561168857604051630a85bd0160e11b81526001600160a01b0385169063150b7a02906115d6903390899088908890600401611cf8565b6020604051808303816000875af1925050508015611611575060408051601f3d908101601f1916820190925261160e91810190611d35565b60015b61166e573d80801561163f576040519150601f19603f3d011682016040523d82523d6000602084013e611644565b606091505b5080516000036116665760405162461bcd60e51b815260040161056c90611c16565b805181602001fd5b6001600160e01b031916630a85bd0160e11b1490506112d9565b506001949350505050565b600054610100900460ff166116ba5760405162461bcd60e51b815260040161056c90611c68565b61086f336110bd565b6001600160a01b0381166116ea57604051638ed88b2560e01b815260040160405180910390fd5b606580546001600160a01b0319166001600160a01b0392909216919091179055565b600054610100900460ff166117335760405162461bcd60e51b815260040161056c90611c68565b60fb61173f8382611d98565b5060fc61060d8282611d98565b6001600160e01b031981168114610c9357600080fd5b60006020828403121561177457600080fd5b81356107d08161174c565b60005b8381101561179a578181015183820152602001611782565b50506000910152565b600081518084526117bb81602086016020860161177f565b601f01601f19169290920160200192915050565b6020815260006107d060208301846117a3565b6000602082840312156117f457600080fd5b5035919050565b6001600160a01b0381168114610c9357600080fd5b6000806040838503121561182357600080fd5b823561182e816117fb565b946020939093013593505050565b60008060006060848603121561185157600080fd5b833561185c816117fb565b9250602084013561186c816117fb565b929592945050506040919091013590565b8035801515811461188d57600080fd5b919050565b6000806000606084860312156118a757600080fd5b83359250602084013591506118be6040850161187d565b90509250925092565b6000602082840312156118d957600080fd5b81356107d0816117fb565b600080604083850312156118f757600080fd5b8235611902816117fb565b91506119106020840161187d565b90509250929050565b6000806040838503121561192c57600080fd5b823591506119106020840161187d565b634e487b7160e01b600052604160045260246000fd5b600067ffffffffffffffff8084111561196d5761196d61193c565b604051601f8501601f19908116603f011681019082821181831017156119955761199561193c565b816040528093508581528686860111156119ae57600080fd5b858560208301376000602087830101525050509392505050565b600080600080608085870312156119de57600080fd5b84356119e9816117fb565b935060208501356119f9816117fb565b925060408501359150606085013567ffffffffffffffff811115611a1c57600080fd5b8501601f81018713611a2d57600080fd5b611a3c87823560208401611952565b91505092959194509250565b600082601f830112611a5957600080fd5b6107d083833560208501611952565b600080600080600060a08688031215611a8057600080fd5b8535611a8b816117fb565b94506020860135611a9b816117fb565b935060408601359250606086013567ffffffffffffffff80821115611abf57600080fd5b611acb89838a01611a48565b93506080880135915080821115611ae157600080fd5b50611aee88828901611a48565b9150509295509295909350565b60008060408385031215611b0e57600080fd5b8235611b19816117fb565b91506020830135611b29816117fb565b809150509250929050565b60008351611b4681846020880161177f565b6241c55b60e71b9083019081528351611b6681600484016020880161177f565b01600401949350505050565b600181811c90821680611b8657607f821691505b602082108103611ba657634e487b7160e01b600052602260045260246000fd5b50919050565b6020808252602d908201527f4552433732313a2063616c6c6572206973206e6f7420746f6b656e206f776e6560408201526c1c881bdc88185c1c1c9bdd9959609a1b606082015260800190565b600060208284031215611c0b57600080fd5b81516107d0816117fb565b60208082526032908201527f4552433732313a207472616e7366657220746f206e6f6e20455243373231526560408201527131b2b4bb32b91034b6b83632b6b2b73a32b960711b606082015260800190565b6020808252602b908201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960408201526a6e697469616c697a696e6760a81b606082015260800190565b60208082526025908201527f4552433732313a207472616e736665722066726f6d20696e636f72726563742060408201526437bbb732b960d91b606082015260800190565b6001600160a01b0385811682528416602082015260408101839052608060608201819052600090611d2b908301846117a3565b9695505050505050565b600060208284031215611d4757600080fd5b81516107d08161174c565b601f82111561060d57600081815260208120601f850160051c81016020861015611d795750805b601f850160051c820191505b81811015610c1557828155600101611d85565b815167ffffffffffffffff811115611db257611db261193c565b611dc681611dc08454611b72565b84611d52565b602080601f831160018114611dfb5760008415611de35750858301515b600019600386901b1c1916600185901b178555610c15565b600085815260208120601f198616915b82811015611e2a57888601518255948401946001909101908401611e0b565b5085821015611e485787850151600019600388901b60f8161c191681555b5050505050600190811b0190555056feddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3efa2646970667358221220bfa463938d2c1b37ce8bf2874f3ed7cf383a5e35c121b5812174a79b5309c84164736f6c63430008140033a2646970667358221220740f3cb9624e33bff8d4e691345bcea7689a5314f1271dcd508219d6f0cb765b64736f6c63430008140033", + "balance": "0x0" + }, + "0x1000777700000000000000000000000000000008": { + "contractName": "ERC721VaultProxy", + "storage": { + "0x0000000000000000000000000000000000000000000000000000000000000000": "0x0000000000000000000000000000000000000000000000000000000000000001", + "0x0000000000000000000000000000000000000000000000000000000000000097": "0x0000000000000000000000000000000000000000000000000000000000000101", + "0x0000000000000000000000000000000000000000000000000000000000000033": "0x000000000000000000000000f39fd6e51aad88f6f4ce6ab8827279cfffb92266", + "0x0000000000000000000000000000000000000000000000000000000000000065": "0x0000000000000000000000001000777700000000000000000000000000000006", + "0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103": "0x70997970C51812dc3A010C7d01b50e0d17dc79C8", + "0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc": "0x0000777700000000000000000000000000000008" + }, + "code": "0x60806040526004361061004e5760003560e01c80633659cfe6146100655780634f1ef286146100855780635c60da1b146100985780638f283970146100c9578063f851a440146100e95761005d565b3661005d5761005b6100fe565b005b61005b6100fe565b34801561007157600080fd5b5061005b6100803660046106b3565b610118565b61005b6100933660046106ce565b610155565b3480156100a457600080fd5b506100ad6101bc565b6040516001600160a01b03909116815260200160405180910390f35b3480156100d557600080fd5b5061005b6100e43660046106b3565b6101ed565b3480156100f557600080fd5b506100ad61020d565b61010661022e565b6101166101116102c3565b6102cd565b565b6101206102f1565b6001600160a01b0316330361014d5761014a81604051806020016040528060008152506000610324565b50565b61014a6100fe565b61015d6102f1565b6001600160a01b031633036101b4576101af8383838080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525060019250610324915050565b505050565b6101af6100fe565b60006101c66102f1565b6001600160a01b031633036101e2576101dd6102c3565b905090565b6101ea6100fe565b90565b6101f56102f1565b6001600160a01b0316330361014d5761014a8161034f565b60006102176102f1565b6001600160a01b031633036101e2576101dd6102f1565b6102366102f1565b6001600160a01b031633036101165760405162461bcd60e51b815260206004820152604260248201527f5472616e73706172656e745570677261646561626c6550726f78793a2061646d60448201527f696e2063616e6e6f742066616c6c6261636b20746f2070726f78792074617267606482015261195d60f21b608482015260a4015b60405180910390fd5b60006101dd6103a3565b3660008037600080366000845af43d6000803e8080156102ec573d6000f35b3d6000fd5b60007fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035b546001600160a01b0316919050565b61032d836103cb565b60008251118061033a5750805b156101af57610349838361040b565b50505050565b7f7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f6103786102f1565b604080516001600160a01b03928316815291841660208301520160405180910390a161014a81610437565b60007f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc610315565b6103d4816104e0565b6040516001600160a01b038216907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b90600090a250565b606061043083836040518060600160405280602781526020016107c560279139610574565b9392505050565b6001600160a01b03811661049c5760405162461bcd60e51b815260206004820152602660248201527f455243313936373a206e65772061646d696e20697320746865207a65726f206160448201526564647265737360d01b60648201526084016102ba565b807fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035b80546001600160a01b0319166001600160a01b039290921691909117905550565b6001600160a01b0381163b61054d5760405162461bcd60e51b815260206004820152602d60248201527f455243313936373a206e657720696d706c656d656e746174696f6e206973206e60448201526c1bdd08184818dbdb9d1c9858dd609a1b60648201526084016102ba565b807f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc6104bf565b6060600080856001600160a01b0316856040516105919190610775565b600060405180830381855af49150503d80600081146105cc576040519150601f19603f3d011682016040523d82523d6000602084013e6105d1565b606091505b50915091506105e2868383876105ec565b9695505050505050565b6060831561065b578251600003610654576001600160a01b0385163b6106545760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e747261637400000060448201526064016102ba565b5081610665565b610665838361066d565b949350505050565b81511561067d5781518083602001fd5b8060405162461bcd60e51b81526004016102ba9190610791565b80356001600160a01b03811681146106ae57600080fd5b919050565b6000602082840312156106c557600080fd5b61043082610697565b6000806000604084860312156106e357600080fd5b6106ec84610697565b9250602084013567ffffffffffffffff8082111561070957600080fd5b818601915086601f83011261071d57600080fd5b81358181111561072c57600080fd5b87602082850101111561073e57600080fd5b6020830194508093505050509250925092565b60005b8381101561076c578181015183820152602001610754565b50506000910152565b60008251610787818460208701610751565b9190910192915050565b60208152600082518060208401526107b0816040850160208701610751565b601f01601f1916919091016040019291505056fe416464726573733a206c6f772d6c6576656c2064656c65676174652063616c6c206661696c6564a2646970667358221220e0c34caa93cb549737d2002fe0da3463bee0317add6c2f3da35498d4b65a974464736f6c63430008140033", + "balance": "0x0" + }, + "0x0000777700000000000000000000000000000009": { + "contractName": "ProxiedERC1155Vault", + "storage": {}, + "code": "0x608060405260043610620001435760003560e01c80636c6563f611620000b95780639aa8605c11620000785780639aa8605c1462000372578063a86f9d9e14620003a9578063bc197c8114620003ce578063c287e5781462000401578063f23a6e611462000435578063f2fde38b146200046657600080fd5b80636c6563f614620002e6578063715018a6146200030b5780637333964314620003235780638456cb59146200033a5780638da5cb5b146200035257600080fd5b80633ab76e9f11620001065780633ab76e9f146200020e5780633f4ba83a146200024957806359f4a90714620002615780635c975abb146200027e57806367090ccf14620002a157600080fd5b806301ffc9a7146200014857806319ab453c146200018257806320b8155914620001a95780632ca069a514620001c05780633005fb9814620001f7575b600080fd5b3480156200015557600080fd5b506200016d62000167366004620020b6565b6200048b565b60405190151581526020015b60405180910390f35b3480156200018f57600080fd5b50620001a7620001a136600462002105565b620004d5565b005b620001a7620001ba36600462002248565b620005f5565b348015620001cd57600080fd5b50620001dd636cdb3d1360e11b81565b6040516001600160e01b0319909116815260200162000179565b620001a7620002083660046200230e565b62000986565b3480156200021b57600080fd5b5060655462000230906001600160a01b031681565b6040516001600160a01b03909116815260200162000179565b3480156200025657600080fd5b50620001a762000d1f565b3480156200026e57600080fd5b50620001dd6380ac58cd60e01b81565b3480156200028b57600080fd5b506200016d609754610100900460ff1660021490565b348015620002ae57600080fd5b5062000230620002c03660046200235b565b60cb6020908152600092835260408084209091529082529020546001600160a01b031681565b348015620002f357600080fd5b5062000230620003053660046200239d565b62000da1565b3480156200031857600080fd5b50620001a762000dba565b620001a7620003343660046200245f565b62000dd2565b3480156200034757600080fd5b50620001a7620011ba565b3480156200035f57600080fd5b506033546001600160a01b031662000230565b3480156200037f57600080fd5b50620003976200039136600462002105565b62001238565b604051620001799493929190620025d1565b348015620003b657600080fd5b5062000230620003c836600462002611565b6200138b565b348015620003db57600080fd5b50620001dd620003ed366004620026cb565b63bc197c8160e01b98975050505050505050565b3480156200040e57600080fd5b506200016d6200042036600462002105565b60c96020526000908152604090205460ff1681565b3480156200044257600080fd5b50620001dd6200045436600462002797565b63f23a6e6160e01b9695505050505050565b3480156200047357600080fd5b50620001a76200048536600462002105565b6200139a565b60006001600160e01b031982166301ffc9a760e01b1480620004bd57506001600160e01b03198216630600bf7360e31b145b80620004cf5750620004cf8262001419565b92915050565b600054610100900460ff1615808015620004f65750600054600160ff909116105b80620005125750303b15801562000512575060005460ff166001145b6200057b5760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b60648201526084015b60405180910390fd5b6000805460ff1916600117905580156200059f576000805461ff0019166101001790555b620005aa8262001450565b8015620005f1576000805461ff0019169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b5050565b60975460ff16600119016200061d5760405163dfc60d8560e01b815260040160405180910390fd5b6097805460ff191660021790556200063f609754610100900460ff1660021490565b156200065e5760405163bae6e2a960e01b815260040160405180910390fd5b6562726964676560d01b620006758160016200138b565b6001600160a01b0316336001600160a01b031614620006a757604051630d85cccf60e11b815260040160405180910390fd5b60405163881107d960e01b81526c195c98cc4c4d4d57dd985d5b1d609a1b6004820152306024820152600090736B9cDdfFBee4D2c5a6001C8d5cAf6A940CaEDCEA9063881107d990604401606060405180830381865af415801562000710573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062000736919062002827565b90506000468835036200081757620007556040890160208a0162002105565b905060005b85518110156200081057816001600160a01b031663f242432a30898985815181106200078a576200078a6200288e565b6020026020010151898681518110620007a757620007a76200288e565b60200260200101516040518563ffffffff1660e01b8152600401620007d09493929190620028a4565b600060405180830381600087803b158015620007eb57600080fd5b505af115801562000800573d6000803e3d6000fd5b505050508060010190506200075a565b50620008fe565b6200082c620008268962002991565b62001477565b905060005b8551811015620008fc57816001600160a01b031663156e29f6888884815181106200086057620008606200288e565b60200260200101518885815181106200087d576200087d6200288e565b60209081029190910101516040516001600160e01b031960e086901b1681526001600160a01b03909316600484015260248301919091526044820152606401600060405180830381600087803b158015620008d757600080fd5b505af1158015620008ec573d6000803e3d6000fd5b5050505080600101905062000831565b505b620009136001600160a01b03871634620014b8565b856001600160a01b0316876001600160a01b031683600001517f0f60c37489e435ed8490c30b01c1fa57e62510e88b351b75796ad3d95babe6b18560400151858a8a604051620009679493929190620029dc565b60405180910390a450506097805460ff19166001179055505050505050565b60975460ff1660011901620009ae5760405163dfc60d8560e01b815260040160405180910390fd5b6097805460ff19166002179055620009d0609754610100900460ff1660021490565b15620009ef5760405163bae6e2a960e01b815260040160405180910390fd5b6562726964676560d01b62000a068160016200138b565b6001600160a01b0316336001600160a01b03161462000a3857604051630d85cccf60e11b815260040160405180910390fd5b6000808062000a4c61014087018762002a1c565b62000a5c91600490829062002a65565b81019062000a6b919062002a91565b6020850151949750909550935050506001600160a01b031662000aa1576040516303f8a7d360e01b815260040160405180910390fd5b6020808401516001600160a01b0316600090815260c9909152604090205460ff161562000bb25760005b825181101562000bab5760208401516001600160a01b031663156e29f662000afa60a08a0160808b0162002105565b85848151811062000b0f5762000b0f6200288e565b602002602001015185858151811062000b2c5762000b2c6200288e565b60209081029190910101516040516001600160e01b031960e086901b1681526001600160a01b03909316600484015260248301919091526044820152606401600060405180830381600087803b15801562000b8657600080fd5b505af115801562000b9b573d6000803e3d6000fd5b5050505080600101905062000acb565b5062000c82565b60005b825181101562000c805760208401516001600160a01b031663f242432a3062000be560a08b0160808c0162002105565b86858151811062000bfa5762000bfa6200288e565b602002602001015186868151811062000c175762000c176200288e565b60200260200101516040518563ffffffff1660e01b815260040162000c409493929190620028a4565b600060405180830381600087803b15801562000c5b57600080fd5b505af115801562000c70573d6000803e3d6000fd5b5050505080600101905062000bb5565b505b62000cad60e087013562000c9d60a0890160808a0162002105565b6001600160a01b031690620014b8565b62000cbf60a087016080880162002105565b6001600160a01b0316857fe8449897bd3c926a272780c39ba13e77bf7a2c823479a75bfbc13ef631183dfd8560200151858560405162000d029392919062002ae4565b60405180910390a350506097805460ff1916600117905550505050565b62000d34609754610100900460ff1660021490565b62000d525760405163bae6e2a960e01b815260040160405180910390fd5b62000d5c6200155c565b6097805461ff0019166101001790556040513381527f5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa906020015b60405180910390a1565b600062000db0848484620015b8565b90505b9392505050565b62000dc46200155c565b62000dd0600062001672565b565b60975460ff166001190162000dfa5760405163dfc60d8560e01b815260040160405180910390fd5b6097805460ff1916600217905562000e1c609754610100900460ff1660021490565b1562000e3b5760405163bae6e2a960e01b815260040160405180910390fd5b60808101516060820151604051636030ce6160e11b8152736B9cDdfFBee4D2c5a6001C8d5cAf6A940CaEDCEA9263c0619cc29262000e7f9260009060040162002b28565b60006040518083038186803b15801562000e9857600080fd5b505af415801562000ead573d6000803e3d6000fd5b50505050736B9cDdfFBee4D2c5a6001C8d5cAf6A940CaEDCEA6393522e3e62000eed83600001516c195c98cc4c4d4d57dd985d5b1d609a1b600062000da1565b602084015160408086015190516001600160e01b031960e086901b1681526001600160a01b039384166004820152918316602483015291909116604482015260640160006040518083038186803b15801562000f4857600080fd5b505af415801562000f5d573d6000803e3d6000fd5b505050604082015162000f8291506001600160a01b0316636cdb3d1360e11b620016c4565b62000fa057604051633ee915f560e11b815260040160405180910390fd5b60808082015160408084015160608086015183516101808101855260008082526020820181905294810185905280830185905295860184905260a0860184905260c0860184905260e086018490526101008601849052610120860193909352610140850181905261016085015291928451606082015262001022338662001759565b610140820152336080820152606081015162001051906c195c98cc4c4d4d57dd985d5b1d609a1b600062000da1565b6001600160a01b031660a08083019190915285015161012082015260c08501516200107d903462002b64565b60e08083019190915260c08087015161010080850191909152918701516001600160a01b031690830152850151610160820152600080620010c86562726964676560d01b826200138b565b6001600160a01b0316635fc34de734856040518363ffffffff1660e01b8152600401620010f6919062002b86565b60006040518083038185885af115801562001115573d6000803e3d6000fd5b50505050506040513d6000823e601f3d908101601f1916820160405262001140919081019062002ceb565b9150915086602001516001600160a01b031681608001516001600160a01b0316837f5e54276405062454e6226625b28a6fea0a838d6b054e38955667234afb3345a3846060015189898c6040516200119c9493929190620029dc565b60405180910390a450506097805460ff191660011790555050505050565b620011cf609754610100900460ff1660021490565b15620011ee5760405163bae6e2a960e01b815260040160405180910390fd5b620011f86200155c565b6097805461ff0019166102001790556040513381527f62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a2589060200162000d97565b60ca6020526000908152604090208054600182015460028301805492936001600160a01b03909216926200126c9062002e2a565b80601f01602080910402602001604051908101604052809291908181526020018280546200129a9062002e2a565b8015620012eb5780601f10620012bf57610100808354040283529160200191620012eb565b820191906000526020600020905b815481529060010190602001808311620012cd57829003601f168201915b505050505090806003018054620013029062002e2a565b80601f0160208091040260200160405190810160405280929190818152602001828054620013309062002e2a565b8015620013815780601f10620013555761010080835404028352916020019162001381565b820191906000526020600020905b8154815290600101906020018083116200136357829003601f168201915b5050505050905084565b600062000db3468484620015b8565b620013a46200155c565b6001600160a01b0381166200140b5760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b606482015260840162000572565b620014168162001672565b50565b60006001600160e01b03198216630271189760e51b1480620004cf57506301ffc9a760e01b6001600160e01b0319831614620004cf565b6200145a62001c63565b620014658162001cdb565b506097805461ffff1916610101179055565b8051600090815260cb60209081526040808320828501516001600160a01b0390811685529252909120541680620014b357620004cf8262001d25565b919050565b6001600160a01b038216620014e057604051634c67134d60e11b815260040160405180910390fd5b6000826001600160a01b03168260405160006040518083038185875af1925050503d80600081146200152f576040519150601f19603f3d011682016040523d82523d6000602084013e62001534565b606091505b50509050806200155757604051634c67134d60e11b815260040160405180910390fd5b505050565b6033546001600160a01b0316331462000dd05760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015260640162000572565b60655460405163195ac1a960e21b815260048101859052602481018490526000916001600160a01b03169063656b06a490604401602060405180830381865afa1580156200160a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062001630919062002e66565b9050811580156200164857506001600160a01b038116155b1562000db357604051631467050360e21b8152600481018590526024810184905260440162000572565b603380546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b60006001600160a01b0383163b620016df57506000620004cf565b6040516301ffc9a760e01b81526001600160e01b0319831660048201526001600160a01b038416906301ffc9a790602401602060405180830381865afa9250505080156200174c575060408051601f3d908101601f19168201909252620017499181019062002e86565b60015b15620004cf579392505050565b604080516080810182526000808252602082015260609181018290528082018290526040808401516001600160a01b0316600090815260c9602052205460ff1615620019fd576040808401516001600160a01b03908116600090815260ca6020908152908390208351608081018552815481526001820154909316918301919091526002810180549293919291840191620017f49062002e2a565b80601f0160208091040260200160405190810160405280929190818152602001828054620018229062002e2a565b8015620018735780601f10620018475761010080835404028352916020019162001873565b820191906000526020600020905b8154815290600101906020018083116200185557829003601f168201915b505050505081526020016003820180546200188e9062002e2a565b80601f0160208091040260200160405190810160405280929190818152602001828054620018bc9062002e2a565b80156200190d5780601f10620018e1576101008083540402835291602001916200190d565b820191906000526020600020905b815481529060010190602001808311620018ef57829003601f168201915b505050505081525050905060005b836060015151811015620019f65783604001516001600160a01b031663f5298aca86866060015184815181106200195657620019566200288e565b6020026020010151876080015185815181106200197757620019776200288e565b60209081029190910101516040516001600160e01b031960e086901b1681526001600160a01b03909316600484015260248301919091526044820152606401600060405180830381600087803b158015620019d157600080fd5b505af1158015620019e6573d6000803e3d6000fd5b505050508060010190506200191b565b5062001bfc565b604051806080016040528046815260200184604001516001600160a01b03168152602001604051806020016040528060008152508152602001604051806020016040528060008152508152509050600083604001519050806001600160a01b03166306fdde036040518163ffffffff1660e01b8152600401600060405180830381865afa92505050801562001ab657506040513d6000823e601f3d908101601f1916820160405262001ab3919081019062002ea6565b60015b1562001ac25760608301525b806001600160a01b03166395d89b416040518163ffffffff1660e01b8152600401600060405180830381865afa92505050801562001b2457506040513d6000823e601f3d908101601f1916820160405262001b21919081019062002ea6565b60015b1562001b305760408301525b60005b84606001515181101562001bf95784604001516001600160a01b031663f242432a33308860600151858151811062001b6f5762001b6f6200288e565b60200260200101518960800151868151811062001b905762001b906200288e565b60200260200101516040518563ffffffff1660e01b815260040162001bb99493929190620028a4565b600060405180830381600087803b15801562001bd457600080fd5b505af115801562001be9573d6000803e3d6000fd5b5050505080600101905062001b33565b50505b6020830151606084015160808501516040516320b8155960e01b9362001c299386938a9360240162002f35565b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b031990931692909217909152949350505050565b600054610100900460ff1662001cd05760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201526a6e697469616c697a696e6760a81b606482015260840162000572565b62000dd03362001672565b6001600160a01b03811662001d0357604051638ed88b2560e01b815260040160405180910390fd5b606580546001600160a01b0319166001600160a01b0392909216919091179055565b60008062001d8260008460405160200162001d41919062002f97565b604051602081830303815290604052805190602001206040518060200162001d6990620020a8565b601f1982820381018352601f9091011660405262001f9e565b9050736B9cDdfFBee4D2c5a6001C8d5cAf6A940CaEDCEA6378adc0d68262001db26033546001600160a01b031690565b60655460208089015189516040808c015160608d0151915163689ccd8d60e11b9662001dee966001600160a01b03909116959493910162002fac565b60408051601f198184030181529082905262001e0e929160200162002ff5565b6040516020818303038152906040526040518463ffffffff1660e01b815260040162001e3d9392919062003028565b602060405180830381865af415801562001e5b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062001e81919062002e66565b6001600160a01b03818116600090815260c9602090815260408083208054600160ff19909116811790915560ca835292819020885181559188015192820180546001600160a01b03191693909416929092179092558501519193508491600282019062001eef9082620030a8565b506060820151600382019062001f069082620030a8565b50508351600090815260cb6020908152604080832082880180516001600160a01b039081168652919093529281902080546001600160a01b031916878516908117909155915187518289015160608a015193519496509190941693927f2da3c4d305298f6df3653c23d98b4c055f72f7e6f981b2c477ccbec92b1ee5799262001f90929162003174565b60405180910390a450919050565b60008347101562001ff25760405162461bcd60e51b815260206004820152601d60248201527f437265617465323a20696e73756666696369656e742062616c616e6365000000604482015260640162000572565b8151600003620020455760405162461bcd60e51b815260206004820181905260248201527f437265617465323a2062797465636f6465206c656e677468206973207a65726f604482015260640162000572565b8282516020840186f590506001600160a01b03811662000db35760405162461bcd60e51b815260206004820152601960248201527f437265617465323a204661696c6564206f6e206465706c6f7900000000000000604482015260640162000572565b612570806200319e83390190565b600060208284031215620020c957600080fd5b81356001600160e01b03198116811462000db357600080fd5b6001600160a01b03811681146200141657600080fd5b8035620014b381620020e2565b6000602082840312156200211857600080fd5b813562000db381620020e2565b634e487b7160e01b600052604160045260246000fd5b60405161012081016001600160401b038111828210171562002161576200216162002125565b60405290565b60405161018081016001600160401b038111828210171562002161576200216162002125565b604051601f8201601f191681016001600160401b0381118282101715620021b857620021b862002125565b604052919050565b600082601f830112620021d257600080fd5b813560206001600160401b03821115620021f057620021f062002125565b8160051b620022018282016200218d565b92835284810182019282810190878511156200221c57600080fd5b83870192505b848310156200223d5782358252918301919083019062002222565b979650505050505050565b600080600080600060a086880312156200226157600080fd5b85356001600160401b03808211156200227957600080fd5b908701906080828a0312156200228e57600080fd5b909550602087013590620022a282620020e2565b909450604087013590620022b682620020e2565b90935060608701359080821115620022cd57600080fd5b620022db89838a01620021c0565b93506080880135915080821115620022f257600080fd5b506200230188828901620021c0565b9150509295509295909350565b600080604083850312156200232257600080fd5b82356001600160401b038111156200233957600080fd5b830161018081860312156200234d57600080fd5b946020939093013593505050565b600080604083850312156200236f57600080fd5b8235915060208301356200238381620020e2565b809150509250929050565b80151581146200141657600080fd5b600080600060608486031215620023b357600080fd5b83359250602084013591506040840135620023ce816200238e565b809150509250925092565b60006001600160401b03821115620023f557620023f562002125565b50601f01601f191660200190565b600082601f8301126200241557600080fd5b81356200242c6200242682620023d9565b6200218d565b8181528460208386010111156200244257600080fd5b816020850160208301376000918101602001919091529392505050565b6000602082840312156200247257600080fd5b81356001600160401b03808211156200248a57600080fd5b908301906101208286031215620024a057600080fd5b620024aa6200213b565b82358152620024bc60208401620020f8565b6020820152620024cf60408401620020f8565b6040820152606083013582811115620024e757600080fd5b620024f587828601620021c0565b6060830152506080830135828111156200250e57600080fd5b6200251c87828601620021c0565b60808301525060a083013560a082015260c083013560c08201526200254460e08401620020f8565b60e082015261010080840135838111156200255e57600080fd5b6200256c8882870162002403565b918301919091525095945050505050565b60005b838110156200259a57818101518382015260200162002580565b50506000910152565b60008151808452620025bd8160208601602086016200257d565b601f01601f19169290920160200192915050565b8481526001600160a01b0384166020820152608060408201819052600090620025fd90830185620025a3565b82810360608401526200223d8185620025a3565b600080604083850312156200262557600080fd5b82359150602083013562002383816200238e565b60008083601f8401126200264c57600080fd5b5081356001600160401b038111156200266457600080fd5b6020830191508360208260051b85010111156200268057600080fd5b9250929050565b60008083601f8401126200269a57600080fd5b5081356001600160401b03811115620026b257600080fd5b6020830191508360208285010111156200268057600080fd5b60008060008060008060008060a0898b031215620026e857600080fd5b8835620026f581620020e2565b975060208901356200270781620020e2565b965060408901356001600160401b03808211156200272457600080fd5b620027328c838d0162002639565b909850965060608b01359150808211156200274c57600080fd5b6200275a8c838d0162002639565b909650945060808b01359150808211156200277457600080fd5b50620027838b828c0162002687565b999c989b5096995094979396929594505050565b60008060008060008060a08789031215620027b157600080fd5b8635620027be81620020e2565b95506020870135620027d081620020e2565b9450604087013593506060870135925060808701356001600160401b03811115620027fa57600080fd5b6200280889828a0162002687565b979a9699509497509295939492505050565b8051620014b381620020e2565b6000606082840312156200283a57600080fd5b604051606081018181106001600160401b03821117156200285f576200285f62002125565b6040528251815260208301516200287681620020e2565b60208201526040928301519281019290925250919050565b634e487b7160e01b600052603260045260246000fd5b6001600160a01b0394851681529290931660208301526040820152606081019190915260a06080820181905260009082015260c00190565b600060808284031215620028ef57600080fd5b604051608081016001600160401b03828210818311171562002915576200291562002125565b8160405282935084358352602085013591506200293282620020e2565b81602084015260408501359150808211156200294d57600080fd5b6200295b8683870162002403565b604084015260608501359150808211156200297557600080fd5b50620029848582860162002403565b6060830152505092915050565b6000620004cf3683620028dc565b600081518084526020808501945080840160005b83811015620029d157815187529582019590820190600101620029b3565b509495945050505050565b8481526001600160a01b038416602082015260806040820181905260009062002a08908301856200299f565b82810360608401526200223d81856200299f565b6000808335601e1984360301811262002a3457600080fd5b8301803591506001600160401b0382111562002a4f57600080fd5b6020019150368190038213156200268057600080fd5b6000808585111562002a7657600080fd5b8386111562002a8457600080fd5b5050820193919092039150565b600080600080600060a0868803121562002aaa57600080fd5b85356001600160401b038082111562002ac257600080fd5b62002ad089838a01620028dc565b965060208801359150620022a282620020e2565b6001600160a01b038416815260606020820181905260009062002b0a908301856200299f565b828103604084015262002b1e81856200299f565b9695505050505050565b60608152600062002b3d60608301866200299f565b828103602084015262002b5181866200299f565b9150508215156040830152949350505050565b81810381811115620004cf57634e487b7160e01b600052601160045260246000fd5b6020815262002ba16020820183516001600160801b03169052565b6000602083015162002bbe60408401826001600160a01b03169052565b506040830151606083015260608301516080830152608083015162002bee60a08401826001600160a01b03169052565b5060a08301516001600160a01b03811660c08401525060c08301516001600160a01b03811660e08401525060e083015161010083810191909152830151610120808401919091528301516101408084019190915283015161018061016080850182905262002c616101a0860184620025a3565b90860151858203601f19018387015290925062002b1e8382620025a3565b80516001600160801b0381168114620014b357600080fd5b600082601f83011262002ca957600080fd5b815162002cba6200242682620023d9565b81815284602083860101111562002cd057600080fd5b62002ce38260208301602087016200257d565b949350505050565b6000806040838503121562002cff57600080fd5b8251915060208301516001600160401b038082111562002d1e57600080fd5b90840190610180828703121562002d3457600080fd5b62002d3e62002167565b62002d498362002c7f565b815262002d59602084016200281a565b6020820152604083015160408201526060830151606082015262002d80608084016200281a565b608082015262002d9360a084016200281a565b60a082015262002da660c084016200281a565b60c082015260e0838101519082015261010080840151908201526101208084015190820152610140808401518381111562002de057600080fd5b62002dee8982870162002c97565b828401525050610160808401518381111562002e0957600080fd5b62002e178982870162002c97565b8284015250508093505050509250929050565b600181811c9082168062002e3f57607f821691505b60208210810362002e6057634e487b7160e01b600052602260045260246000fd5b50919050565b60006020828403121562002e7957600080fd5b815162000db381620020e2565b60006020828403121562002e9957600080fd5b815162000db3816200238e565b60006020828403121562002eb957600080fd5b81516001600160401b0381111562002ed057600080fd5b62002ce38482850162002c97565b8051825260018060a01b036020820151166020830152600060408201516080604085015262002f116080850182620025a3565b90506060830151848203606086015262002f2c8282620025a3565b95945050505050565b60a08152600062002f4a60a083018862002ede565b6001600160a01b03878116602085015286166040840152828103606084015262002f7581866200299f565b9050828103608084015262002f8b81856200299f565b98975050505050505050565b60208152600062000db3602083018462002ede565b6001600160a01b038681168252851660208201526040810184905260a06060820181905260009062002fe190830185620025a3565b828103608084015262002f8b8185620025a3565b6001600160e01b03198316815281516000906200301a8160048501602087016200257d565b919091016004019392505050565b6001600160a01b0384811682528316602082015260606040820181905260009062002f2c90830184620025a3565b601f8211156200155757600081815260208120601f850160051c810160208610156200307f5750805b601f850160051c820191505b81811015620030a0578281556001016200308b565b505050505050565b81516001600160401b03811115620030c457620030c462002125565b620030dc81620030d5845462002e2a565b8462003056565b602080601f831160018114620031145760008415620030fb5750858301515b600019600386901b1c1916600185901b178555620030a0565b600085815260208120601f198616915b82811015620031455788860151825594840194600190910190840162003124565b5085821015620031645787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b604081526000620031896040830185620025a3565b828103602084015262002f2c8185620025a356fe608060405234801561001057600080fd5b5061001961001e565b6100de565b600054610100900460ff161561008a5760405162461bcd60e51b815260206004820152602760248201527f496e697469616c697a61626c653a20636f6e747261637420697320696e697469604482015266616c697a696e6760c81b606482015260840160405180910390fd5b60005460ff90811610156100dc576000805460ff191660ff9081179091556040519081527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b565b61248280620000ee6000396000f3fe608060405234801561001057600080fd5b50600436106101575760003560e01c8063715018a6116100c3578063a86f9d9e1161007c578063a86f9d9e146102c9578063d1399b1a146102dc578063e985e9c5146102ef578063f242432a1461032b578063f2fde38b1461033e578063f5298aca1461035157600080fd5b8063715018a6146102795780637cf8ed0d146102815780638456cb59146102955780638da5cb5b1461029d57806395d89b41146102ae578063a22cb465146102b657600080fd5b80633ab76e9f116101155780633ab76e9f146101f55780633f4ba83a1461022057806349d12605146102285780634e1273f4146102325780635c975abb146102525780636c6563f61461026657600080fd5b8062fdd58e1461015c57806301ffc9a71461018257806306fdde03146101a55780630e89341c146101ba578063156e29f6146101cd5780632eb2c2d6146101e2575b600080fd5b61016f61016a36600461190f565b610364565b6040519081526020015b60405180910390f35b610195610190366004611951565b6103ff565b6040519015158152602001610179565b6101ad61044f565b60405161017991906119be565b6101ad6101c83660046119d1565b610485565b6101e06101db3660046119ea565b610519565b005b6101e06101f0366004611b6b565b6105cf565b606554610208906001600160a01b031681565b6040516001600160a01b039091168152602001610179565b6101e061061b565b61016f61012e5481565b610245610240366004611c19565b610699565b6040516101799190611d21565b610195609754610100900460ff1660021490565b610208610274366004611d49565b6107c3565b6101e06107da565b61012d54610208906001600160a01b031681565b6101e06107ee565b6033546001600160a01b0316610208565b6101ad610867565b6101e06102c4366004611d7e565b6108f6565b6102086102d7366004611db3565b610905565b6101e06102ea366004611dd6565b610912565b6101956102fd366004611e39565b6001600160a01b03918216600090815260fc6020908152604080832093909416825291909152205460ff1690565b6101e0610339366004611e72565b610abb565b6101e061034c366004611edb565b610af1565b6101e061035f3660046119ea565b610b6a565b60006001600160a01b0383166103d45760405162461bcd60e51b815260206004820152602a60248201527f455243313135353a2061646472657373207a65726f206973206e6f742061207660448201526930b634b21037bbb732b960b11b60648201526084015b60405180910390fd5b50600081815260fb602090815260408083206001600160a01b03861684529091529020545b92915050565b60006001600160e01b03198216636cdb3d1360e11b148061043057506001600160e01b031982166303a24d0760e21b145b806103f957506301ffc9a760e01b6001600160e01b03198316146103f9565b606061013061046061012e54610c06565b604051602001610471929190611f32565b604051602081830303815290604052905090565b606060fd805461049490611ef8565b80601f01602080910402602001604051908101604052809291908181526020018280546104c090611ef8565b801561050d5780601f106104e25761010080835404028352916020019161050d565b820191906000526020600020905b8154815290600101906020018083116104f057829003601f168201915b50505050509050919050565b6c195c98cc4c4d4d57dd985d5b1d609a1b610535816001610905565b6001600160a01b0316336001600160a01b03161461056657604051630d85cccf60e11b815260040160405180910390fd5b61058184848460405180602001604052806000815250610c99565b60408051848152602081018490526001600160a01b038616916000917f9ed053bb818ff08b8353cd46f78db1f0799f31c9e4458fdb425c10eccd2efc4491015b60405180910390a350505050565b6001600160a01b0385163314806105eb57506105eb85336102fd565b6106075760405162461bcd60e51b81526004016103cb90611fc8565b6106148585858585610daf565b5050505050565b61062f609754610100900460ff1660021490565b61064c5760405163bae6e2a960e01b815260040160405180910390fd5b610654610f87565b6097805461ff0019166101001790556040513381527f5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa906020015b60405180910390a1565b606081518351146106fe5760405162461bcd60e51b815260206004820152602960248201527f455243313135353a206163636f756e747320616e6420696473206c656e677468604482015268040dad2e6dac2e8c6d60bb1b60648201526084016103cb565b6000835167ffffffffffffffff81111561071a5761071a611a1f565b604051908082528060200260200182016040528015610743578160200160208202803683370190505b50905060005b84518110156107bb5761078e85828151811061076757610767612016565b602002602001015185838151811061078157610781612016565b6020026020010151610364565b8282815181106107a0576107a0612016565b60209081029190910101526107b481612042565b9050610749565b509392505050565b60006107d0848484610fe1565b90505b9392505050565b6107e2610f87565b6107ec6000611095565b565b610802609754610100900460ff1660021490565b156108205760405163bae6e2a960e01b815260040160405180910390fd5b610828610f87565b6097805461ff0019166102001790556040513381527f62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a2589060200161068f565b61012f805461087590611ef8565b80601f01602080910402602001604051908101604052809291908181526020018280546108a190611ef8565b80156108ee5780601f106108c3576101008083540402835291602001916108ee565b820191906000526020600020905b8154815290600101906020018083116108d157829003601f168201915b505050505081565b6109013383836110e7565b5050565b60006107d3468484610fe1565b600054610100900460ff16158080156109325750600054600160ff909116105b8061094c5750303b15801561094c575060005460ff166001145b6109af5760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b60648201526084016103cb565b6000805460ff1916600117905580156109d2576000805461ff0019166101001790555b6001600160a01b03851615806109e6575083155b806109f057504684145b15610a0e57604051635d061ab760e11b815260040160405180910390fd5b610a17866111c7565b610a2f604051806020016040528060008152506111ea565b61012d80546001600160a01b0319166001600160a01b03871617905561012e84905561012f610a5e84826120a6565b50610130610a6c83826120a6565b508015610ab3576000805461ff0019169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b505050505050565b306001600160a01b03851603610ae457604051636cfe544760e01b815260040160405180910390fd5b610614858585858561121a565b610af9610f87565b6001600160a01b038116610b5e5760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b60648201526084016103cb565b610b6781611095565b50565b6c195c98cc4c4d4d57dd985d5b1d609a1b610b86816001610905565b6001600160a01b0316336001600160a01b031614610bb757604051630d85cccf60e11b815260040160405180910390fd5b610bc284848461125f565b60408051848152602081018490526000916001600160a01b038716917f9ed053bb818ff08b8353cd46f78db1f0799f31c9e4458fdb425c10eccd2efc4491016105c1565b60606000610c13836113de565b600101905060008167ffffffffffffffff811115610c3357610c33611a1f565b6040519080825280601f01601f191660200182016040528015610c5d576020820181803683370190505b5090508181016020015b600019016f181899199a1a9b1b9c1cb0b131b232b360811b600a86061a8153600a8504945084610c6757509392505050565b6001600160a01b038416610cf95760405162461bcd60e51b815260206004820152602160248201527f455243313135353a206d696e7420746f20746865207a65726f206164647265736044820152607360f81b60648201526084016103cb565b336000610d05856114b6565b90506000610d12856114b6565b9050600086815260fb602090815260408083206001600160a01b038b16845290915281208054879290610d46908490612166565b909155505060408051878152602081018790526001600160a01b03808a1692600092918716917fc3d58168c5ae7397731d063d5bbf3d657854427343f4c083240f7aacaa2d0f62910160405180910390a4610da683600089898989611501565b50505050505050565b8151835114610e115760405162461bcd60e51b815260206004820152602860248201527f455243313135353a2069647320616e6420616d6f756e7473206c656e677468206044820152670dad2e6dac2e8c6d60c31b60648201526084016103cb565b6001600160a01b038416610e375760405162461bcd60e51b81526004016103cb90612179565b3360005b8451811015610f21576000858281518110610e5857610e58612016565b602002602001015190506000858381518110610e7657610e76612016565b602090810291909101810151600084815260fb835260408082206001600160a01b038e168352909352919091205490915081811015610ec75760405162461bcd60e51b81526004016103cb906121be565b600083815260fb602090815260408083206001600160a01b038e8116855292528083208585039055908b16825281208054849290610f06908490612166565b9250508190555050505080610f1a90612042565b9050610e3b565b50846001600160a01b0316866001600160a01b0316826001600160a01b03167f4a39dc06d4c0dbc64b70af90fd698a233a518aa5d07e595d983b8c0526c8f7fb8787604051610f71929190612208565b60405180910390a4610ab381878787878761165c565b6033546001600160a01b031633146107ec5760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657260448201526064016103cb565b60655460405163195ac1a960e21b815260048101859052602481018490526000916001600160a01b03169063656b06a490604401602060405180830381865afa158015611032573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110569190612236565b90508115801561106d57506001600160a01b038116155b156107d357604051631467050360e21b815260048101859052602481018490526044016103cb565b603380546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b816001600160a01b0316836001600160a01b03160361115a5760405162461bcd60e51b815260206004820152602960248201527f455243313135353a2073657474696e6720617070726f76616c20737461747573604482015268103337b91039b2b63360b91b60648201526084016103cb565b6001600160a01b03838116600081815260fc6020908152604080832094871680845294825291829020805460ff191686151590811790915591519182527f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c31910160405180910390a3505050565b6111cf611717565b6111d881611747565b506097805461ffff1916610101179055565b600054610100900460ff166112115760405162461bcd60e51b81526004016103cb90612253565b610b6781611790565b6001600160a01b038516331480611236575061123685336102fd565b6112525760405162461bcd60e51b81526004016103cb90611fc8565b61061485858585856117c0565b6001600160a01b0383166112c15760405162461bcd60e51b815260206004820152602360248201527f455243313135353a206275726e2066726f6d20746865207a65726f206164647260448201526265737360e81b60648201526084016103cb565b3360006112cd846114b6565b905060006112da846114b6565b604080516020808201835260009182905288825260fb81528282206001600160a01b038b16835290522054909150848110156113645760405162461bcd60e51b8152602060048201526024808201527f455243313135353a206275726e20616d6f756e7420657863656564732062616c604482015263616e636560e01b60648201526084016103cb565b600086815260fb602090815260408083206001600160a01b038b81168086529184528285208a8703905582518b81529384018a90529092908816917fc3d58168c5ae7397731d063d5bbf3d657854427343f4c083240f7aacaa2d0f62910160405180910390a4604080516020810190915260009052610da6565b60008072184f03e93ff9f4daa797ed6e38ed64bf6a1f0160401b831061141d5772184f03e93ff9f4daa797ed6e38ed64bf6a1f0160401b830492506040015b6d04ee2d6d415b85acef81000000008310611449576d04ee2d6d415b85acef8100000000830492506020015b662386f26fc10000831061146757662386f26fc10000830492506010015b6305f5e100831061147f576305f5e100830492506008015b612710831061149357612710830492506004015b606483106114a5576064830492506002015b600a83106103f95760010192915050565b604080516001808252818301909252606091600091906020808301908036833701905050905082816000815181106114f0576114f0612016565b602090810291909101015292915050565b6001600160a01b0384163b15610ab35760405163f23a6e6160e01b81526001600160a01b0385169063f23a6e6190611545908990899088908890889060040161229e565b6020604051808303816000875af1925050508015611580575060408051601f3d908101601f1916820190925261157d918101906122e3565b60015b61162c5761158c612300565b806308c379a0036115c557506115a061231c565b806115ab57506115c7565b8060405162461bcd60e51b81526004016103cb91906119be565b505b60405162461bcd60e51b815260206004820152603460248201527f455243313135353a207472616e7366657220746f206e6f6e2d455243313135356044820152732932b1b2b4bb32b91034b6b83632b6b2b73a32b960611b60648201526084016103cb565b6001600160e01b0319811663f23a6e6160e01b14610da65760405162461bcd60e51b81526004016103cb906123a6565b6001600160a01b0384163b15610ab35760405163bc197c8160e01b81526001600160a01b0385169063bc197c81906116a090899089908890889088906004016123ee565b6020604051808303816000875af19250505080156116db575060408051601f3d908101601f191682019092526116d8918101906122e3565b60015b6116e75761158c612300565b6001600160e01b0319811663bc197c8160e01b14610da65760405162461bcd60e51b81526004016103cb906123a6565b600054610100900460ff1661173e5760405162461bcd60e51b81526004016103cb90612253565b6107ec33611095565b6001600160a01b03811661176e57604051638ed88b2560e01b815260040160405180910390fd5b606580546001600160a01b0319166001600160a01b0392909216919091179055565b600054610100900460ff166117b75760405162461bcd60e51b81526004016103cb90612253565b610b67816118ee565b6001600160a01b0384166117e65760405162461bcd60e51b81526004016103cb90612179565b3360006117f2856114b6565b905060006117ff856114b6565b9050600086815260fb602090815260408083206001600160a01b038c168452909152902054858110156118445760405162461bcd60e51b81526004016103cb906121be565b600087815260fb602090815260408083206001600160a01b038d8116855292528083208985039055908a16825281208054889290611883908490612166565b909155505060408051888152602081018890526001600160a01b03808b16928c821692918816917fc3d58168c5ae7397731d063d5bbf3d657854427343f4c083240f7aacaa2d0f62910160405180910390a46118e3848a8a8a8a8a611501565b505050505050505050565b60fd61090182826120a6565b6001600160a01b0381168114610b6757600080fd5b6000806040838503121561192257600080fd5b823561192d816118fa565b946020939093013593505050565b6001600160e01b031981168114610b6757600080fd5b60006020828403121561196357600080fd5b81356107d38161193b565b60005b83811015611989578181015183820152602001611971565b50506000910152565b600081518084526119aa81602086016020860161196e565b601f01601f19169290920160200192915050565b6020815260006107d36020830184611992565b6000602082840312156119e357600080fd5b5035919050565b6000806000606084860312156119ff57600080fd5b8335611a0a816118fa565b95602085013595506040909401359392505050565b634e487b7160e01b600052604160045260246000fd5b601f8201601f1916810167ffffffffffffffff81118282101715611a5b57611a5b611a1f565b6040525050565b600067ffffffffffffffff821115611a7c57611a7c611a1f565b5060051b60200190565b600082601f830112611a9757600080fd5b81356020611aa482611a62565b604051611ab18282611a35565b83815260059390931b8501820192828101915086841115611ad157600080fd5b8286015b84811015611aec5780358352918301918301611ad5565b509695505050505050565b600082601f830112611b0857600080fd5b813567ffffffffffffffff811115611b2257611b22611a1f565b604051611b39601f8301601f191660200182611a35565b818152846020838601011115611b4e57600080fd5b816020850160208301376000918101602001919091529392505050565b600080600080600060a08688031215611b8357600080fd5b8535611b8e816118fa565b94506020860135611b9e816118fa565b9350604086013567ffffffffffffffff80821115611bbb57600080fd5b611bc789838a01611a86565b94506060880135915080821115611bdd57600080fd5b611be989838a01611a86565b93506080880135915080821115611bff57600080fd5b50611c0c88828901611af7565b9150509295509295909350565b60008060408385031215611c2c57600080fd5b823567ffffffffffffffff80821115611c4457600080fd5b818501915085601f830112611c5857600080fd5b81356020611c6582611a62565b604051611c728282611a35565b83815260059390931b8501820192828101915089841115611c9257600080fd5b948201945b83861015611cb9578535611caa816118fa565b82529482019490820190611c97565b96505086013592505080821115611ccf57600080fd5b50611cdc85828601611a86565b9150509250929050565b600081518084526020808501945080840160005b83811015611d1657815187529582019590820190600101611cfa565b509495945050505050565b6020815260006107d36020830184611ce6565b80358015158114611d4457600080fd5b919050565b600080600060608486031215611d5e57600080fd5b8335925060208401359150611d7560408501611d34565b90509250925092565b60008060408385031215611d9157600080fd5b8235611d9c816118fa565b9150611daa60208401611d34565b90509250929050565b60008060408385031215611dc657600080fd5b82359150611daa60208401611d34565b600080600080600060a08688031215611dee57600080fd5b8535611df9816118fa565b94506020860135611e09816118fa565b935060408601359250606086013567ffffffffffffffff80821115611e2d57600080fd5b611be989838a01611af7565b60008060408385031215611e4c57600080fd5b8235611e57816118fa565b91506020830135611e67816118fa565b809150509250929050565b600080600080600060a08688031215611e8a57600080fd5b8535611e95816118fa565b94506020860135611ea5816118fa565b93506040860135925060608601359150608086013567ffffffffffffffff811115611ecf57600080fd5b611c0c88828901611af7565b600060208284031215611eed57600080fd5b81356107d3816118fa565b600181811c90821680611f0c57607f821691505b602082108103611f2c57634e487b7160e01b600052602260045260246000fd5b50919050565b6000808454611f4081611ef8565b60018281168015611f585760018114611f6d57611f9c565b60ff1984168752821515830287019450611f9c565b8860005260208060002060005b85811015611f935781548a820152908401908201611f7a565b50505082870194505b50506241c55b60e71b835250508351611fbc81600484016020880161196e565b01600401949350505050565b6020808252602e908201527f455243313135353a2063616c6c6572206973206e6f7420746f6b656e206f776e60408201526d195c881bdc88185c1c1c9bdd995960921b606082015260800190565b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052601160045260246000fd5b6000600182016120545761205461202c565b5060010190565b601f8211156120a157600081815260208120601f850160051c810160208610156120825750805b601f850160051c820191505b81811015610ab35782815560010161208e565b505050565b815167ffffffffffffffff8111156120c0576120c0611a1f565b6120d4816120ce8454611ef8565b8461205b565b602080601f83116001811461210957600084156120f15750858301515b600019600386901b1c1916600185901b178555610ab3565b600085815260208120601f198616915b8281101561213857888601518255948401946001909101908401612119565b50858210156121565787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b808201808211156103f9576103f961202c565b60208082526025908201527f455243313135353a207472616e7366657220746f20746865207a65726f206164604082015264647265737360d81b606082015260800190565b6020808252602a908201527f455243313135353a20696e73756666696369656e742062616c616e636520666f60408201526939103a3930b739b332b960b11b606082015260800190565b60408152600061221b6040830185611ce6565b828103602084015261222d8185611ce6565b95945050505050565b60006020828403121561224857600080fd5b81516107d3816118fa565b6020808252602b908201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960408201526a6e697469616c697a696e6760a81b606082015260800190565b6001600160a01b03868116825285166020820152604081018490526060810183905260a0608082018190526000906122d890830184611992565b979650505050505050565b6000602082840312156122f557600080fd5b81516107d38161193b565b600060033d11156123195760046000803e5060005160e01c5b90565b600060443d101561232a5790565b6040516003193d81016004833e81513d67ffffffffffffffff816024840111818411171561235a57505050505090565b82850191508151818111156123725750505050505090565b843d870101602082850101111561238c5750505050505090565b61239b60208286010187611a35565b509095945050505050565b60208082526028908201527f455243313135353a204552433131353552656365697665722072656a656374656040820152676420746f6b656e7360c01b606082015260800190565b6001600160a01b0386811682528516602082015260a06040820181905260009061241a90830186611ce6565b828103606084015261242c8186611ce6565b905082810360808401526124408185611992565b9897505050505050505056fea264697066735822122024301b126fd789913dbc2205293d09b76b47f21d2d27ff492e762fd23eade43c64736f6c63430008140033a2646970667358221220dd4492ce9ce9743ae9f35d0eb864627d2ad5a0d8a5852fa377c3341d3072e60564736f6c63430008140033", + "balance": "0x0" + }, + "0x1000777700000000000000000000000000000009": { + "contractName": "ERC1155VaultProxy", + "storage": { + "0x0000000000000000000000000000000000000000000000000000000000000000": "0x0000000000000000000000000000000000000000000000000000000000000001", + "0x0000000000000000000000000000000000000000000000000000000000000097": "0x0000000000000000000000000000000000000000000000000000000000000101", + "0x0000000000000000000000000000000000000000000000000000000000000033": "0x000000000000000000000000f39fd6e51aad88f6f4ce6ab8827279cfffb92266", + "0x0000000000000000000000000000000000000000000000000000000000000065": "0x0000000000000000000000001000777700000000000000000000000000000006", + "0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103": "0x70997970C51812dc3A010C7d01b50e0d17dc79C8", + "0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc": "0x0000777700000000000000000000000000000009" + }, + "code": "0x60806040526004361061004e5760003560e01c80633659cfe6146100655780634f1ef286146100855780635c60da1b146100985780638f283970146100c9578063f851a440146100e95761005d565b3661005d5761005b6100fe565b005b61005b6100fe565b34801561007157600080fd5b5061005b6100803660046106b3565b610118565b61005b6100933660046106ce565b610155565b3480156100a457600080fd5b506100ad6101bc565b6040516001600160a01b03909116815260200160405180910390f35b3480156100d557600080fd5b5061005b6100e43660046106b3565b6101ed565b3480156100f557600080fd5b506100ad61020d565b61010661022e565b6101166101116102c3565b6102cd565b565b6101206102f1565b6001600160a01b0316330361014d5761014a81604051806020016040528060008152506000610324565b50565b61014a6100fe565b61015d6102f1565b6001600160a01b031633036101b4576101af8383838080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525060019250610324915050565b505050565b6101af6100fe565b60006101c66102f1565b6001600160a01b031633036101e2576101dd6102c3565b905090565b6101ea6100fe565b90565b6101f56102f1565b6001600160a01b0316330361014d5761014a8161034f565b60006102176102f1565b6001600160a01b031633036101e2576101dd6102f1565b6102366102f1565b6001600160a01b031633036101165760405162461bcd60e51b815260206004820152604260248201527f5472616e73706172656e745570677261646561626c6550726f78793a2061646d60448201527f696e2063616e6e6f742066616c6c6261636b20746f2070726f78792074617267606482015261195d60f21b608482015260a4015b60405180910390fd5b60006101dd6103a3565b3660008037600080366000845af43d6000803e8080156102ec573d6000f35b3d6000fd5b60007fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035b546001600160a01b0316919050565b61032d836103cb565b60008251118061033a5750805b156101af57610349838361040b565b50505050565b7f7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f6103786102f1565b604080516001600160a01b03928316815291841660208301520160405180910390a161014a81610437565b60007f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc610315565b6103d4816104e0565b6040516001600160a01b038216907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b90600090a250565b606061043083836040518060600160405280602781526020016107c560279139610574565b9392505050565b6001600160a01b03811661049c5760405162461bcd60e51b815260206004820152602660248201527f455243313936373a206e65772061646d696e20697320746865207a65726f206160448201526564647265737360d01b60648201526084016102ba565b807fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035b80546001600160a01b0319166001600160a01b039290921691909117905550565b6001600160a01b0381163b61054d5760405162461bcd60e51b815260206004820152602d60248201527f455243313936373a206e657720696d706c656d656e746174696f6e206973206e60448201526c1bdd08184818dbdb9d1c9858dd609a1b60648201526084016102ba565b807f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc6104bf565b6060600080856001600160a01b0316856040516105919190610775565b600060405180830381855af49150503d80600081146105cc576040519150601f19603f3d011682016040523d82523d6000602084013e6105d1565b606091505b50915091506105e2868383876105ec565b9695505050505050565b6060831561065b578251600003610654576001600160a01b0385163b6106545760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e747261637400000060448201526064016102ba565b5081610665565b610665838361066d565b949350505050565b81511561067d5781518083602001fd5b8060405162461bcd60e51b81526004016102ba9190610791565b80356001600160a01b03811681146106ae57600080fd5b919050565b6000602082840312156106c557600080fd5b61043082610697565b6000806000604084860312156106e357600080fd5b6106ec84610697565b9250602084013567ffffffffffffffff8082111561070957600080fd5b818601915086601f83011261071d57600080fd5b81358181111561072c57600080fd5b87602082850101111561073e57600080fd5b6020830194508093505050509250925092565b60005b8381101561076c578181015183820152602001610754565b50506000910152565b60008251610787818460208701610751565b9190910192915050565b60208152600082518060208401526107b0816040850160208701610751565b601f01601f1916919091016040019291505056fe416464726573733a206c6f772d6c6576656c2064656c65676174652063616c6c206661696c6564a2646970667358221220e0c34caa93cb549737d2002fe0da3463bee0317add6c2f3da35498d4b65a974464736f6c63430008140033", + "balance": "0x0" + }, + "0x0000777700000000000000000000000000000003": { + "contractName": "ProxiedEtherVault", + "storage": {}, + "code": "0x6080604052600436106100e15760003560e01c80638456cb591161007f578063ba0bbd9511610059578063ba0bbd951461023a578063d73bb3d01461025a578063f2fde38b1461027a578063fe9fbb801461029a57600080fd5b80638456cb59146101e75780638da5cb5b146101fc578063a86f9d9e1461021a57600080fd5b80633f4ba83a116100bb5780633f4ba83a1461016c5780635c975abb146101815780636c6563f6146101b2578063715018a6146101d257600080fd5b806319ab453c146100ed5780632d1fb3891461010f5780633ab76e9f1461012f57600080fd5b366100e857005b600080fd5b3480156100f957600080fd5b5061010d610108366004610b57565b6102ca565b005b34801561011b57600080fd5b5061010d61012a366004610b89565b6103e2565b34801561013b57600080fd5b5060655461014f906001600160a01b031681565b6040516001600160a01b0390911681526020015b60405180910390f35b34801561017857600080fd5b5061010d6104b1565b34801561018d57600080fd5b506101a2609754610100900460ff1660021490565b6040519015158152602001610163565b3480156101be57600080fd5b5061014f6101cd366004610bbe565b61052f565b3480156101de57600080fd5b5061010d610546565b3480156101f357600080fd5b5061010d61055a565b34801561020857600080fd5b506033546001600160a01b031661014f565b34801561022657600080fd5b5061014f610235366004610bf3565b6105d3565b34801561024657600080fd5b5061010d610255366004610c16565b6105e0565b34801561026657600080fd5b5061010d610275366004610c42565b610704565b34801561028657600080fd5b5061010d610295366004610b57565b6107e9565b3480156102a657600080fd5b506101a26102b5366004610b57565b60c96020526000908152604090205460ff1681565b600054610100900460ff16158080156102ea5750600054600160ff909116105b806103045750303b158015610304575060005460ff166001145b61036c5760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b60648201526084015b60405180910390fd5b6000805460ff19166001179055801561038f576000805461ff0019166101001790555b61039882610862565b80156103de576000805461ff0019169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b5050565b6103ea610885565b6001600160a01b03821661041157604051632f711bc960e11b815260040160405180910390fd5b6001600160a01b038216600090815260c9602052604090205481151560ff90911615150361045257604051632f711bc960e11b815260040160405180910390fd5b6001600160a01b038216600081815260c96020908152604091829020805460ff191685151590811790915591519182527f4c0079b9bcd37cd5d29a13938effd97c881798cbc6bd52a3026a29d94b27d1bf910160405180910390a25050565b6104c5609754610100900460ff1660021490565b6104e25760405163bae6e2a960e01b815260040160405180910390fd5b6104ea610885565b6097805461ff0019166101001790556040513381527f5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa906020015b60405180910390a1565b600061053c8484846108df565b90505b9392505050565b61054e610885565b6105586000610993565b565b61056e609754610100900460ff1660021490565b1561058c5760405163bae6e2a960e01b815260040160405180910390fd5b610594610885565b6097805461ff0019166102001790556040513381527f62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a25890602001610525565b600061053f4684846108df565b33600090815260c9602052604090205460ff1661061057604051632583296b60e01b815260040160405180910390fd5b60975460ff16600119016106375760405163dfc60d8560e01b815260040160405180910390fd5b6097805460ff19166002179055610658609754610100900460ff1660021490565b156106765760405163bae6e2a960e01b815260040160405180910390fd5b6001600160a01b03821661069d5760405163f355fa3360e01b815260040160405180910390fd5b6106b06001600160a01b038316826109e5565b816001600160a01b03167f7b9f77d35803cd201eac9c4ed739bc1fcd3f1be6ab8877d925d1e55517b6fd6e826040516106eb91815260200190565b60405180910390a250506097805460ff19166001179055565b33600090815260c9602052604090205460ff1661073457604051632583296b60e01b815260040160405180910390fd5b60975460ff166001190161075b5760405163dfc60d8560e01b815260040160405180910390fd5b6097805460ff1916600217905561077c609754610100900460ff1660021490565b1561079a5760405163bae6e2a960e01b815260040160405180910390fd5b6107a433826109e5565b60405181815233907f7b9f77d35803cd201eac9c4ed739bc1fcd3f1be6ab8877d925d1e55517b6fd6e9060200160405180910390a2506097805460ff19166001179055565b6107f1610885565b6001600160a01b0381166108565760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b6064820152608401610363565b61085f81610993565b50565b61086a610a85565b61087381610af9565b506097805461ffff1916610101179055565b6033546001600160a01b031633146105585760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610363565b60655460405163195ac1a960e21b815260048101859052602481018490526000916001600160a01b03169063656b06a490604401602060405180830381865afa158015610930573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906109549190610c5b565b90508115801561096b57506001600160a01b038116155b1561053f57604051631467050360e21b81526004810185905260248101849052604401610363565b603380546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b6001600160a01b038216610a0c57604051634c67134d60e11b815260040160405180910390fd5b6000826001600160a01b03168260405160006040518083038185875af1925050503d8060008114610a59576040519150601f19603f3d011682016040523d82523d6000602084013e610a5e565b606091505b5050905080610a8057604051634c67134d60e11b815260040160405180910390fd5b505050565b600054610100900460ff16610af05760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201526a6e697469616c697a696e6760a81b6064820152608401610363565b61055833610993565b6001600160a01b038116610b2057604051638ed88b2560e01b815260040160405180910390fd5b606580546001600160a01b0319166001600160a01b0392909216919091179055565b6001600160a01b038116811461085f57600080fd5b600060208284031215610b6957600080fd5b813561053f81610b42565b80358015158114610b8457600080fd5b919050565b60008060408385031215610b9c57600080fd5b8235610ba781610b42565b9150610bb560208401610b74565b90509250929050565b600080600060608486031215610bd357600080fd5b8335925060208401359150610bea60408501610b74565b90509250925092565b60008060408385031215610c0657600080fd5b82359150610bb560208401610b74565b60008060408385031215610c2957600080fd5b8235610c3481610b42565b946020939093013593505050565b600060208284031215610c5457600080fd5b5035919050565b600060208284031215610c6d57600080fd5b815161053f81610b4256fea264697066735822122074d45297cbd3fc5e6b85ef863c2df1e4227fb3dd97046550a739a4820b3fb61064736f6c63430008140033", + "balance": "0x0" + }, + "0x1000777700000000000000000000000000000003": { + "contractName": "EtherVaultProxy", + "storage": { + "0x0000000000000000000000000000000000000000000000000000000000000000": "0x0000000000000000000000000000000000000000000000000000000000000001", + "0x0000000000000000000000000000000000000000000000000000000000000097": "0x0000000000000000000000000000000000000000000000000000000000000101", + "0x0000000000000000000000000000000000000000000000000000000000000033": "0x000000000000000000000000f39fd6e51aad88f6f4ce6ab8827279cfffb92266", + "0x0000000000000000000000000000000000000000000000000000000000000065": "0x0000000000000000000000001000777700000000000000000000000000000006", + "0xa738d3397c1eb96f671d7e4bd29cabbfa1a9c9ebc0db4142aee17809c43ab720": "0x0000000000000000000000000000000000000000000000000000000000000001", + "0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103": "0x70997970C51812dc3A010C7d01b50e0d17dc79C8", + "0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc": "0x0000777700000000000000000000000000000003" + }, + "code": "0x60806040526004361061004e5760003560e01c80633659cfe6146100655780634f1ef286146100855780635c60da1b146100985780638f283970146100c9578063f851a440146100e95761005d565b3661005d5761005b6100fe565b005b61005b6100fe565b34801561007157600080fd5b5061005b6100803660046106b3565b610118565b61005b6100933660046106ce565b610155565b3480156100a457600080fd5b506100ad6101bc565b6040516001600160a01b03909116815260200160405180910390f35b3480156100d557600080fd5b5061005b6100e43660046106b3565b6101ed565b3480156100f557600080fd5b506100ad61020d565b61010661022e565b6101166101116102c3565b6102cd565b565b6101206102f1565b6001600160a01b0316330361014d5761014a81604051806020016040528060008152506000610324565b50565b61014a6100fe565b61015d6102f1565b6001600160a01b031633036101b4576101af8383838080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525060019250610324915050565b505050565b6101af6100fe565b60006101c66102f1565b6001600160a01b031633036101e2576101dd6102c3565b905090565b6101ea6100fe565b90565b6101f56102f1565b6001600160a01b0316330361014d5761014a8161034f565b60006102176102f1565b6001600160a01b031633036101e2576101dd6102f1565b6102366102f1565b6001600160a01b031633036101165760405162461bcd60e51b815260206004820152604260248201527f5472616e73706172656e745570677261646561626c6550726f78793a2061646d60448201527f696e2063616e6e6f742066616c6c6261636b20746f2070726f78792074617267606482015261195d60f21b608482015260a4015b60405180910390fd5b60006101dd6103a3565b3660008037600080366000845af43d6000803e8080156102ec573d6000f35b3d6000fd5b60007fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035b546001600160a01b0316919050565b61032d836103cb565b60008251118061033a5750805b156101af57610349838361040b565b50505050565b7f7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f6103786102f1565b604080516001600160a01b03928316815291841660208301520160405180910390a161014a81610437565b60007f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc610315565b6103d4816104e0565b6040516001600160a01b038216907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b90600090a250565b606061043083836040518060600160405280602781526020016107c560279139610574565b9392505050565b6001600160a01b03811661049c5760405162461bcd60e51b815260206004820152602660248201527f455243313936373a206e65772061646d696e20697320746865207a65726f206160448201526564647265737360d01b60648201526084016102ba565b807fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035b80546001600160a01b0319166001600160a01b039290921691909117905550565b6001600160a01b0381163b61054d5760405162461bcd60e51b815260206004820152602d60248201527f455243313936373a206e657720696d706c656d656e746174696f6e206973206e60448201526c1bdd08184818dbdb9d1c9858dd609a1b60648201526084016102ba565b807f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc6104bf565b6060600080856001600160a01b0316856040516105919190610775565b600060405180830381855af49150503d80600081146105cc576040519150601f19603f3d011682016040523d82523d6000602084013e6105d1565b606091505b50915091506105e2868383876105ec565b9695505050505050565b6060831561065b578251600003610654576001600160a01b0385163b6106545760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e747261637400000060448201526064016102ba565b5081610665565b610665838361066d565b949350505050565b81511561067d5781518083602001fd5b8060405162461bcd60e51b81526004016102ba9190610791565b80356001600160a01b03811681146106ae57600080fd5b919050565b6000602082840312156106c557600080fd5b61043082610697565b6000806000604084860312156106e357600080fd5b6106ec84610697565b9250602084013567ffffffffffffffff8082111561070957600080fd5b818601915086601f83011261071d57600080fd5b81358181111561072c57600080fd5b87602082850101111561073e57600080fd5b6020830194508093505050509250925092565b60005b8381101561076c578181015183820152602001610754565b50506000910152565b60008251610787818460208701610751565b9190910192915050565b60208152600082518060208401526107b0816040850160208701610751565b601f01601f1916919091016040019291505056fe416464726573733a206c6f772d6c6576656c2064656c65676174652063616c6c206661696c6564a2646970667358221220e0c34caa93cb549737d2002fe0da3463bee0317add6c2f3da35498d4b65a974464736f6c63430008140033", + "balance": "0xfffffffffffffba9c6e7dbb0bfffffff" + }, + "0x0000777700000000000000000000000000000007": { + "contractName": "ProxiedSignalService", + "storage": {}, + "code": "0x608060405234801561001057600080fd5b50600436106100f55760003560e01c8063715018a61161009757806392824e901161006657806392824e90146101e6578063a86f9d9e146101f9578063cbb3ddf31461020c578063f2fde38b1461021357600080fd5b8063715018a6146101b25780638456cb59146101ba578063850fd955146101c25780638da5cb5b146101d557600080fd5b80633f4ba83a116100d35780633f4ba83a146101625780635c975abb1461016a57806366ca2bc01461017e5780636c6563f61461019f57600080fd5b806319ab453c146100fa57806332676bc61461010f5780633ab76e9f14610137575b600080fd5b61010d610108366004611c31565b610226565b005b61012261011d366004611c4e565b61033e565b60405190151581526020015b60405180910390f35b60655461014a906001600160a01b031681565b6040516001600160a01b03909116815260200161012e565b61010d6103a6565b610122609754610100900460ff1660021490565b61019161018c366004611c7a565b610424565b60405190815260200161012e565b61014a6101ad366004611ca8565b61045d565b61010d610474565b61010d610488565b6101916101d0366004611cdd565b610501565b6033546001600160a01b031661014a565b6101226101f4366004611d15565b61055f565b61014a610207366004611dab565b610823565b6000610122565b61010d610221366004611c31565b610839565b600054610100900460ff16158080156102465750600054600160ff909116105b806102605750303b158015610260575060005460ff166001145b6102c85760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b60648201526084015b60405180910390fd5b6000805460ff1916600117905580156102eb576000805461ff0019166101001790555b6102f4826108b2565b801561033a576000805461ff0019169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b5050565b6000826001600160a01b0381166103685760405163985389db60e01b815260040160405180910390fd5b82600081900361038b5760405163c7b4b9bf60e01b815260040160405180910390fd5b6000610398468787610501565b546001149695505050505050565b6103ba609754610100900460ff1660021490565b6103d75760405163bae6e2a960e01b815260040160405180910390fd5b6103df6108d5565b6097805461ff0019166101001790556040513381527f5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa906020015b60405180910390a1565b6000818082036104475760405163c7b4b9bf60e01b815260040160405180910390fd5b610452463385610501565b600181559392505050565b600061046a84848461092f565b90505b9392505050565b61047c6108d5565b61048660006109e3565b565b61049c609754610100900460ff1660021490565b156104ba5760405163bae6e2a960e01b815260040160405180910390fd5b6104c26108d5565b6097805461ff0019166102001790556040513381527f62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a2589060200161041a565b6040516514d251d3905360d21b6020820152602681018490526bffffffffffffffffffffffff19606084901b166046820152605a8101829052600090607a016040516020818303038152906040528051906020012090509392505050565b60006001600160a01b0385161580610575575083155b8061057e575085155b8061058857504686145b156105955750600061081a565b60006105a383850185611eb7565b90508060200151516000036105bc57600091505061081a565b60005b81604001515181101561064757816040015181815181106105e2576105e261202b565b6020026020010151602001516000801b036106025760009250505061081a565b816040015181815181106106185761061861202b565b602002602001015160400151516000036106375760009250505061081a565b61064081612057565b90506105bf565b50600061065d647461696b6f60d81b6000610823565b8251604051638cfb045960e01b815267ffffffffffffffff90911660048201526001600160a01b039190911690638cfb0459906024016040805180830381865afa1580156106af573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906106d39190612070565b60200151905060008190036106ed5760009250505061081a565b60005b8260400151518110156107c0576000836040015182815181106107155761071561202b565b60200260200101519050600061074b82600001516107418460000151647461696b6f60d81b600061045d565b8460200151610501565b905060006107928260405160200161076591815260200190565b60408051601f19818403018152828201825260018352600160f81b60208401529086015190919088610a35565b9050806107a8576000965050505050505061081a565b50506020015191506107b981612057565b90506106f0565b506108156107cf898989610501565b6040516020016107e191815260200190565b604051602081830303815290604052604051806040016040528060018152602001600160f81b815250846020015184610a35565b925050505b95945050505050565b600061083046848461092f565b90505b92915050565b6108416108d5565b6001600160a01b0381166108a65760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b60648201526084016102bf565b6108af816109e3565b50565b6108ba610a59565b6108c381610acd565b506097805461ffff1916610101179055565b6033546001600160a01b031633146104865760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657260448201526064016102bf565b60655460405163195ac1a960e21b815260048101859052602481018490526000916001600160a01b03169063656b06a490604401602060405180830381865afa158015610980573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906109a491906120bf565b9050811580156109bb57506001600160a01b038116155b1561046d57604051631467050360e21b815260048101859052602481018490526044016102bf565b603380546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b600080610a4186610b16565b9050610a4f81868686610b48565b9695505050505050565b600054610100900460ff16610ac45760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201526a6e697469616c697a696e6760a81b60648201526084016102bf565b610486336109e3565b6001600160a01b038116610af457604051638ed88b2560e01b815260040160405180910390fd5b606580546001600160a01b0319166001600160a01b0392909216919091179055565b60608180519060200120604051602001610b3291815260200190565b6040516020818303038152906040529050919050565b6000806000610b58878686610b85565b91509150818015610b7a57508051602080830191909120875191880191909120145b979650505050505050565b600060606000610b9485610c60565b90506000806000610ba6848a89610d59565b81519295509093509150158080610bba5750815b610c065760405162461bcd60e51b815260206004820152601a60248201527f50726f76696465642070726f6f6620697320696e76616c69642e00000000000060448201526064016102bf565b600081610c225760405180602001604052806000815250610c4e565b610c4e86610c316001886120dc565b81518110610c4157610c4161202b565b6020026020010151611179565b919b919a509098505050505050505050565b60606000610c6d836111a0565b90506000815167ffffffffffffffff811115610c8b57610c8b611dd7565b604051908082528060200260200182016040528015610cd057816020015b6040805180820190915260608082526020820152815260200190600190039081610ca95790505b50905060005b8251811015610d51576000610d03848381518110610cf657610cf661202b565b60200260200101516111d3565b90506040518060400160405280610d19836111a0565b815260200182815250838381518110610d3457610d3461202b565b60200260200101819052505080610d4a90612057565b9050610cd6565b509392505050565b600060606000806000610d6b8761125a565b90506000869050600080610d92604051806040016040528060608152602001606081525090565b60005b8c51811015611151578c8181518110610db057610db061202b565b602002602001015191508284610dc691906120ef565b9350610dd36001886120ef565b965083600003610e30578482602001518051906020012014610e2b5760405162461bcd60e51b8152602060048201526011602482015270092dcecc2d8d2c840e4dedee840d0c2e6d607b1b60448201526064016102bf565b610ef2565b602082602001515110610e97578482602001518051906020012014610e2b5760405162461bcd60e51b815260206004820152601b60248201527f496e76616c6964206c6172676520696e7465726e616c2068617368000000000060448201526064016102bf565b84610ea58360200151611393565b14610ef25760405162461bcd60e51b815260206004820152601a60248201527f496e76616c696420696e7465726e616c206e6f6465206861736800000000000060448201526064016102bf565b610efe60106001612102565b60ff1682600001515103610f6c5785518414611151576000868581518110610f2857610f2861202b565b01602001518351805160f89290921c925060009183908110610f4c57610f4c61202b565b60200260200101519050610f5f816113bb565b9650600194505050611141565b815151600119016110f9576000610f82836113f1565b9050600081600081518110610f9957610f9961202b565b016020015160f81c90506000610fb060028361211b565b610fbb90600261214b565b90506000610fcc848360ff16611415565b90506000610fda8b8a611415565b90506000610fe8838361144b565b905060ff851660021480610fff575060ff85166003145b15611039578083511480156110145750808251145b1561102657611023818b6120ef565b99505b50600160ff1b9950611151945050505050565b60ff8516158061104c575060ff85166001145b156110a2578251811461106c5750600160ff1b9950611151945050505050565b61109388600001516001815181106110865761108661202b565b60200260200101516113bb565b9a509750611141945050505050565b60405162461bcd60e51b815260206004820152602660248201527f52656365697665642061206e6f6465207769746820616e20756e6b6e6f776e206044820152650e0e4caccd2f60d31b60648201526084016102bf565b60405162461bcd60e51b815260206004820152601d60248201527f526563656976656420616e20756e706172736561626c65206e6f64652e00000060448201526064016102bf565b61114a81612057565b9050610d95565b50600160ff1b8414866111648786611415565b909e909d50909b509950505050505050505050565b8051805160609161083391611190906001906120dc565b81518110610cf657610cf661202b565b604080518082018252600080825260209182015281518083019092528251825280830190820152606090610833906114c5565b606060008060006111e3856116b1565b9194509250905060008160018111156111fe576111fe612164565b1461124b5760405162461bcd60e51b815260206004820152601860248201527f496e76616c696420524c502062797465732076616c75652e000000000000000060448201526064016102bf565b61081a856020015184846119fb565b606060008251600261126c919061217a565b67ffffffffffffffff81111561128457611284611dd7565b6040519080825280601f01601f1916602001820160405280156112ae576020820181803683370190505b50905060005b835181101561138c5760048482815181106112d1576112d161202b565b01602001516001600160f81b031916901c826112ee83600261217a565b815181106112fe576112fe61202b565b60200101906001600160f81b031916908160001a90535060108482815181106113295761132961202b565b016020015161133b919060f81c61211b565b60f81b8261134a83600261217a565b6113559060016120ef565b815181106113655761136561202b565b60200101906001600160f81b031916908160001a90535061138581612057565b90506112b4565b5092915050565b60006020825110156113a757506020015190565b818060200190518101906108339190612191565b600060606020836000015110156113dc576113d583611aa4565b90506113e8565b6113e5836111d3565b90505b61046d81611393565b60606108336114108360000151600081518110610cf657610cf661202b565b61125a565b6060825182106114345750604080516020810190915260008152610833565b610830838384865161144691906120dc565b611aaf565b6000805b80845111801561145f5750808351115b80156114b057508281815181106114785761147861202b565b602001015160f81c60f81b6001600160f81b03191684828151811061149f5761149f61202b565b01602001516001600160f81b031916145b15610830576114be81612057565b905061144f565b60606000806114d3846116b1565b919350909150600190508160018111156114ef576114ef612164565b1461153c5760405162461bcd60e51b815260206004820152601760248201527f496e76616c696420524c50206c6973742076616c75652e00000000000000000060448201526064016102bf565b6040805160208082526104208201909252600091816020015b60408051808201909152600080825260208201528152602001906001900390816115555790505090506000835b86518110156116a657602082106115ee5760405162461bcd60e51b815260206004820152602a60248201527f50726f766964656420524c50206c6973742065786365656473206d6178206c6960448201526939ba103632b733ba341760b11b60648201526084016102bf565b60008061162b6040518060400160405280858c6000015161160f91906120dc565b8152602001858c6020015161162491906120ef565b90526116b1565b50915091506040518060400160405280838361164791906120ef565b8152602001848b6020015161165c91906120ef565b8152508585815181106116715761167161202b565b60209081029190910101526116876001856120ef565b935061169381836120ef565b61169d90846120ef565b92505050611582565b508152949350505050565b6000806000808460000151116117095760405162461bcd60e51b815260206004820152601860248201527f524c50206974656d2063616e6e6f74206265206e756c6c2e000000000000000060448201526064016102bf565b6020840151805160001a607f811161172e5760006001600094509450945050506119f4565b60b781116117aa5760006117436080836120dc565b9050808760000151116117985760405162461bcd60e51b815260206004820152601960248201527f496e76616c696420524c502073686f727420737472696e672e0000000000000060448201526064016102bf565b600195509350600092506119f4915050565b60bf81116118995760006117bf60b7836120dc565b9050808760000151116118145760405162461bcd60e51b815260206004820152601f60248201527f496e76616c696420524c50206c6f6e6720737472696e67206c656e6774682e0060448201526064016102bf565b600183015160208290036101000a900461182e81836120ef565b88511161187d5760405162461bcd60e51b815260206004820152601860248201527f496e76616c696420524c50206c6f6e6720737472696e672e000000000000000060448201526064016102bf565b6118888260016120ef565b96509450600093506119f492505050565b60f781116119145760006118ae60c0836120dc565b9050808760000151116119035760405162461bcd60e51b815260206004820152601760248201527f496e76616c696420524c502073686f7274206c6973742e00000000000000000060448201526064016102bf565b6001955093508492506119f4915050565b600061192160f7836120dc565b9050808760000151116119765760405162461bcd60e51b815260206004820152601d60248201527f496e76616c696420524c50206c6f6e67206c697374206c656e6774682e00000060448201526064016102bf565b600183015160208290036101000a900461199081836120ef565b8851116119d85760405162461bcd60e51b815260206004820152601660248201527524b73b30b634b210292628103637b733903634b9ba1760511b60448201526064016102bf565b6119e38260016120ef565b96509450600193506119f492505050565b9193909250565b606060008267ffffffffffffffff811115611a1857611a18611dd7565b6040519080825280601f01601f191660200182016040528015611a42576020820181803683370190505b5090508051600003611a5557905061046d565b8484016020820160005b85811015611a77578281015182820152602001611a5f565b5060006001602087066020036101000a039050808251168119845116178252839450505050509392505050565b606061083382611c06565b606081611abd81601f6120ef565b1015611afc5760405162461bcd60e51b815260206004820152600e60248201526d736c6963655f6f766572666c6f7760901b60448201526064016102bf565b82611b0783826120ef565b1015611b465760405162461bcd60e51b815260206004820152600e60248201526d736c6963655f6f766572666c6f7760901b60448201526064016102bf565b611b5082846120ef565b84511015611b945760405162461bcd60e51b8152602060048201526011602482015270736c6963655f6f75744f66426f756e647360781b60448201526064016102bf565b606082158015611bb35760405191506000825260208201604052611bfd565b6040519150601f8416801560200281840101858101878315602002848b0101015b81831015611bec578051835260209283019201611bd4565b5050858452601f01601f1916604052505b50949350505050565b60606108338260200151600084600001516119fb565b6001600160a01b03811681146108af57600080fd5b600060208284031215611c4357600080fd5b813561083081611c1c565b60008060408385031215611c6157600080fd5b8235611c6c81611c1c565b946020939093013593505050565b600060208284031215611c8c57600080fd5b5035919050565b80358015158114611ca357600080fd5b919050565b600080600060608486031215611cbd57600080fd5b8335925060208401359150611cd460408501611c93565b90509250925092565b600080600060608486031215611cf257600080fd5b833592506020840135611d0481611c1c565b929592945050506040919091013590565b600080600080600060808688031215611d2d57600080fd5b853594506020860135611d3f81611c1c565b935060408601359250606086013567ffffffffffffffff80821115611d6357600080fd5b818801915088601f830112611d7757600080fd5b813581811115611d8657600080fd5b896020828501011115611d9857600080fd5b9699959850939650602001949392505050565b60008060408385031215611dbe57600080fd5b82359150611dce60208401611c93565b90509250929050565b634e487b7160e01b600052604160045260246000fd5b6040516060810167ffffffffffffffff81118282101715611e1057611e10611dd7565b60405290565b604051601f8201601f1916810167ffffffffffffffff81118282101715611e3f57611e3f611dd7565b604052919050565b600082601f830112611e5857600080fd5b813567ffffffffffffffff811115611e7257611e72611dd7565b611e85601f8201601f1916602001611e16565b818152846020838601011115611e9a57600080fd5b816020850160208301376000918101602001919091529392505050565b60006020808385031215611eca57600080fd5b823567ffffffffffffffff80821115611ee257600080fd5b9084019060608287031215611ef657600080fd5b611efe611ded565b82358281168114611f0e57600080fd5b81528284013582811115611f2157600080fd5b611f2d88828601611e47565b858301525060408084013583811115611f4557600080fd5b80850194505087601f850112611f5a57600080fd5b833583811115611f6c57611f6c611dd7565b8060051b611f7b878201611e16565b918252858101870191878101908b841115611f9557600080fd5b88880192505b8383101561201657823587811115611fb35760008081fd5b88016060818e03601f19011215611fca5760008081fd5b611fd2611ded565b8a8201358152868201358b820152606082013589811115611ff35760008081fd5b6120018f8d83860101611e47565b82890152508352509188019190880190611f9b565b93850193909352509198975050505050505050565b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052601160045260246000fd5b60006001820161206957612069612041565b5060010190565b60006040828403121561208257600080fd5b6040516040810181811067ffffffffffffffff821117156120a5576120a5611dd7565b604052825181526020928301519281019290925250919050565b6000602082840312156120d157600080fd5b815161083081611c1c565b8181038181111561083357610833612041565b8082018082111561083357610833612041565b60ff818116838216019081111561083357610833612041565b600060ff83168061213c57634e487b7160e01b600052601260045260246000fd5b8060ff84160691505092915050565b60ff828116828216039081111561083357610833612041565b634e487b7160e01b600052602160045260246000fd5b808202811582820484141761083357610833612041565b6000602082840312156121a357600080fd5b505191905056fea26469706673582212203757b44de254a7e528a4a9476f4ed102ede625b5f584178f2beec729aa1781c464736f6c63430008140033", + "balance": "0x0" + }, + "0x1000777700000000000000000000000000000007": { + "contractName": "SignalServiceProxy", + "storage": { + "0x0000000000000000000000000000000000000000000000000000000000000000": "0x0000000000000000000000000000000000000000000000000000000000000001", + "0x0000000000000000000000000000000000000000000000000000000000000097": "0x0000000000000000000000000000000000000000000000000000000000000101", + "0x0000000000000000000000000000000000000000000000000000000000000033": "0x000000000000000000000000f39fd6e51aad88f6f4ce6ab8827279cfffb92266", + "0x0000000000000000000000000000000000000000000000000000000000000065": "0x0000000000000000000000001000777700000000000000000000000000000006", + "0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103": "0x70997970C51812dc3A010C7d01b50e0d17dc79C8", + "0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc": "0x0000777700000000000000000000000000000007" + }, + "code": "0x60806040526004361061004e5760003560e01c80633659cfe6146100655780634f1ef286146100855780635c60da1b146100985780638f283970146100c9578063f851a440146100e95761005d565b3661005d5761005b6100fe565b005b61005b6100fe565b34801561007157600080fd5b5061005b6100803660046106b3565b610118565b61005b6100933660046106ce565b610155565b3480156100a457600080fd5b506100ad6101bc565b6040516001600160a01b03909116815260200160405180910390f35b3480156100d557600080fd5b5061005b6100e43660046106b3565b6101ed565b3480156100f557600080fd5b506100ad61020d565b61010661022e565b6101166101116102c3565b6102cd565b565b6101206102f1565b6001600160a01b0316330361014d5761014a81604051806020016040528060008152506000610324565b50565b61014a6100fe565b61015d6102f1565b6001600160a01b031633036101b4576101af8383838080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525060019250610324915050565b505050565b6101af6100fe565b60006101c66102f1565b6001600160a01b031633036101e2576101dd6102c3565b905090565b6101ea6100fe565b90565b6101f56102f1565b6001600160a01b0316330361014d5761014a8161034f565b60006102176102f1565b6001600160a01b031633036101e2576101dd6102f1565b6102366102f1565b6001600160a01b031633036101165760405162461bcd60e51b815260206004820152604260248201527f5472616e73706172656e745570677261646561626c6550726f78793a2061646d60448201527f696e2063616e6e6f742066616c6c6261636b20746f2070726f78792074617267606482015261195d60f21b608482015260a4015b60405180910390fd5b60006101dd6103a3565b3660008037600080366000845af43d6000803e8080156102ec573d6000f35b3d6000fd5b60007fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035b546001600160a01b0316919050565b61032d836103cb565b60008251118061033a5750805b156101af57610349838361040b565b50505050565b7f7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f6103786102f1565b604080516001600160a01b03928316815291841660208301520160405180910390a161014a81610437565b60007f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc610315565b6103d4816104e0565b6040516001600160a01b038216907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b90600090a250565b606061043083836040518060600160405280602781526020016107c560279139610574565b9392505050565b6001600160a01b03811661049c5760405162461bcd60e51b815260206004820152602660248201527f455243313936373a206e65772061646d696e20697320746865207a65726f206160448201526564647265737360d01b60648201526084016102ba565b807fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035b80546001600160a01b0319166001600160a01b039290921691909117905550565b6001600160a01b0381163b61054d5760405162461bcd60e51b815260206004820152602d60248201527f455243313936373a206e657720696d706c656d656e746174696f6e206973206e60448201526c1bdd08184818dbdb9d1c9858dd609a1b60648201526084016102ba565b807f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc6104bf565b6060600080856001600160a01b0316856040516105919190610775565b600060405180830381855af49150503d80600081146105cc576040519150601f19603f3d011682016040523d82523d6000602084013e6105d1565b606091505b50915091506105e2868383876105ec565b9695505050505050565b6060831561065b578251600003610654576001600160a01b0385163b6106545760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e747261637400000060448201526064016102ba565b5081610665565b610665838361066d565b949350505050565b81511561067d5781518083602001fd5b8060405162461bcd60e51b81526004016102ba9190610791565b80356001600160a01b03811681146106ae57600080fd5b919050565b6000602082840312156106c557600080fd5b61043082610697565b6000806000604084860312156106e357600080fd5b6106ec84610697565b9250602084013567ffffffffffffffff8082111561070957600080fd5b818601915086601f83011261071d57600080fd5b81358181111561072c57600080fd5b87602082850101111561073e57600080fd5b6020830194508093505050509250925092565b60005b8381101561076c578181015183820152602001610754565b50506000910152565b60008251610787818460208701610751565b9190910192915050565b60208152600082518060208401526107b0816040850160208701610751565b601f01601f1916919091016040019291505056fe416464726573733a206c6f772d6c6576656c2064656c65676174652063616c6c206661696c6564a2646970667358221220e0c34caa93cb549737d2002fe0da3463bee0317add6c2f3da35498d4b65a974464736f6c63430008140033", + "balance": "0x0" + }, + "0x0000777700000000000000000000000000000005": { + "contractName": "RegularERC20", + "storage": { + "0x0000000000000000000000000000000000000000000000000000000000000003": "0x526567756c617245524332300000000000000000000000000000000000000018", + "0x0000000000000000000000000000000000000000000000000000000000000004": "0x52474c0000000000000000000000000000000000000000000000000000000006", + "0x0000000000000000000000000000000000000000000000000000000000000002": "0x0000000000000000000000000000000000000000000000000000000001388000", + "0x723077b8a1b173adc35e5f0e7e3662fd1208212cb629f9c128551ea7168da722": "0x00000000000000000000000000000000000000000000000000000000000fa000", + "0x14e04a66bf74771820a7400ff6cf065175b3d7eb25805a5bd1633b161af5d101": "0x00000000000000000000000000000000000000000000000000000000000fa000", + "0x215be5d23550ceb1beff54fb579a765903ba2ccc85b6f79bcf9bda4e8cb86034": "0x00000000000000000000000000000000000000000000000000000000000fa000", + "0x6d1035fce6503985ab075a4ff3f7ce2e57cd5a9c5e6a0589dccacfea7bcb0af4": "0x00000000000000000000000000000000000000000000000000000000000fa000", + "0x2a95ee547cef07a2fff0a68144824a0d9ded35ed87da118a53e1cda4aca8b944": "0x00000000000000000000000000000000000000000000000000000000000fa000", + "0x7fcecd2a720442e9bc0cf1a8a6976f9fbddf6b996dc0d78af7e94dadf360d579": "0x00000000000000000000000000000000000000000000000000000000000fa000", + "0x18bbf5fcf8fe870ecff419c4677497c08b2e6a5431bb94541d06c9da3f308e55": "0x00000000000000000000000000000000000000000000000000000000000fa000", + "0x6e3431b4e42570cb9e3d926eb26f9e54de2df536ae0741ae16350d17a6c16ddc": "0x00000000000000000000000000000000000000000000000000000000000fa000", + "0xdb302bf24b1ad5f23949da8e6b05747dc699499a995361a7bf40ec7204696d6f": "0x00000000000000000000000000000000000000000000000000000000000fa000", + "0xa1d47ef1a6916dfbe65888f77739da164feb3a9a6afc95ee57e8b3e85ea5e955": "0x00000000000000000000000000000000000000000000000000000000000fa000", + "0x454340b1295f9ff1c0fb9192166d0215d33f84dc5f2dc3f3e5732a4b557186bf": "0x00000000000000000000000000000000000000000000000000000000000fa000", + "0x6a3bb1dada7c82a99b4a02d16da3fda07cb31d8887b9b99ec829ab67fd7a817e": "0x00000000000000000000000000000000000000000000000000000000000fa000", + "0x2fe2844d12634f5dce1e2be5be96b2ea1c573f8f25171997e2f4bd943dd32f92": "0x00000000000000000000000000000000000000000000000000000000000fa000", + "0x3836a017087644fbf6925ae1aca14201ce898a35434d9dea9ebd03cea44e049a": "0x00000000000000000000000000000000000000000000000000000000000fa000", + "0x1c7a29f5a750951acb14fdf82a876085914eb17f15a162b054a3d2f8c92e2451": "0x00000000000000000000000000000000000000000000000000000000000fa000", + "0x271927a243b678b7a071f19b4051ef93b16e397066e3fdef5bba26527e34a1a1": "0x00000000000000000000000000000000000000000000000000000000000fa000", + "0x4663d660b5d810c9ab2f6dc64af7ff84ebae28a72342391622649a7fe87c93d4": "0x00000000000000000000000000000000000000000000000000000000000fa000", + "0x352c3281a58937f04ef7cc7b88f3456b6ffd47f52a321c253dc083fb53a3a114": "0x00000000000000000000000000000000000000000000000000000000000fa000", + "0x6d5faa5f4e671e6fe47b0eab51c62f8cebf354e21e8fdccf8cdfc0293dd341a3": "0x00000000000000000000000000000000000000000000000000000000000fa000", + "0x673de83553dc3a2c0f59aa7193de392a4530feb73b9d6cd4fcef68802b8195c1": "0x00000000000000000000000000000000000000000000000000000000000fa000" + }, + "code": "0x608060405234801561001057600080fd5b50600436106100a95760003560e01c80633950935111610071578063395093511461012357806370a082311461013657806395d89b411461015f578063a457c2d714610167578063a9059cbb1461017a578063dd62ed3e1461018d57600080fd5b806306fdde03146100ae578063095ea7b3146100cc57806318160ddd146100ef57806323b872dd14610101578063313ce56714610114575b600080fd5b6100b66101a0565b6040516100c3919061069c565b60405180910390f35b6100df6100da366004610706565b610232565b60405190151581526020016100c3565b6002545b6040519081526020016100c3565b6100df61010f366004610730565b61024c565b604051601281526020016100c3565b6100df610131366004610706565b610270565b6100f361014436600461076c565b6001600160a01b031660009081526020819052604090205490565b6100b6610292565b6100df610175366004610706565b6102a1565b6100df610188366004610706565b610321565b6100f361019b36600461078e565b61032f565b6060600380546101af906107c1565b80601f01602080910402602001604051908101604052809291908181526020018280546101db906107c1565b80156102285780601f106101fd57610100808354040283529160200191610228565b820191906000526020600020905b81548152906001019060200180831161020b57829003601f168201915b5050505050905090565b60003361024081858561035a565b60019150505b92915050565b60003361025a85828561047e565b6102658585856104f8565b506001949350505050565b600033610240818585610283838361032f565b61028d91906107fb565b61035a565b6060600480546101af906107c1565b600033816102af828661032f565b9050838110156103145760405162461bcd60e51b815260206004820152602560248201527f45524332303a2064656372656173656420616c6c6f77616e63652062656c6f77604482015264207a65726f60d81b60648201526084015b60405180910390fd5b610265828686840361035a565b6000336102408185856104f8565b6001600160a01b03918216600090815260016020908152604080832093909416825291909152205490565b6001600160a01b0383166103bc5760405162461bcd60e51b8152602060048201526024808201527f45524332303a20617070726f76652066726f6d20746865207a65726f206164646044820152637265737360e01b606482015260840161030b565b6001600160a01b03821661041d5760405162461bcd60e51b815260206004820152602260248201527f45524332303a20617070726f766520746f20746865207a65726f206164647265604482015261737360f01b606482015260840161030b565b6001600160a01b0383811660008181526001602090815260408083209487168084529482529182902085905590518481527f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925910160405180910390a3505050565b600061048a848461032f565b905060001981146104f257818110156104e55760405162461bcd60e51b815260206004820152601d60248201527f45524332303a20696e73756666696369656e7420616c6c6f77616e6365000000604482015260640161030b565b6104f2848484840361035a565b50505050565b6001600160a01b03831661055c5760405162461bcd60e51b815260206004820152602560248201527f45524332303a207472616e736665722066726f6d20746865207a65726f206164604482015264647265737360d81b606482015260840161030b565b6001600160a01b0382166105be5760405162461bcd60e51b815260206004820152602360248201527f45524332303a207472616e7366657220746f20746865207a65726f206164647260448201526265737360e81b606482015260840161030b565b6001600160a01b038316600090815260208190526040902054818110156106365760405162461bcd60e51b815260206004820152602660248201527f45524332303a207472616e7366657220616d6f756e7420657863656564732062604482015265616c616e636560d01b606482015260840161030b565b6001600160a01b03848116600081815260208181526040808320878703905593871680835291849020805487019055925185815290927fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef910160405180910390a36104f2565b600060208083528351808285015260005b818110156106c9578581018301518582016040015282016106ad565b506000604082860101526040601f19601f8301168501019250505092915050565b80356001600160a01b038116811461070157600080fd5b919050565b6000806040838503121561071957600080fd5b610722836106ea565b946020939093013593505050565b60008060006060848603121561074557600080fd5b61074e846106ea565b925061075c602085016106ea565b9150604084013590509250925092565b60006020828403121561077e57600080fd5b610787826106ea565b9392505050565b600080604083850312156107a157600080fd5b6107aa836106ea565b91506107b8602084016106ea565b90509250929050565b600181811c908216806107d557607f821691505b6020821081036107f557634e487b7160e01b600052602260045260246000fd5b50919050565b8082018082111561024657634e487b7160e01b600052601160045260246000fdfea264697066735822122055389869d93aea00eadfbfb381b9a03a1b06411c851d9e0166c4d6547c456d8664736f6c63430008140033", + "balance": "0x0" + } +}
diff --git ethereum/go-ethereum/core/taiko_genesis/internal_l3.json taikoxyz/taiko-geth/core/taiko_genesis/internal_l3.json new file mode 100644 index 0000000000000000000000000000000000000000..40a4300e4b806bee786aa90f303f1b2e81169456 --- /dev/null +++ taikoxyz/taiko-geth/core/taiko_genesis/internal_l3.json @@ -0,0 +1,251 @@ +{ + "0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266": { + "balance": "0x3782dace9d90000000" + }, + "0x70997970C51812dc3A010C7d01b50e0d17dc79C8": { + "balance": "0x3782dace9d90000000" + }, + "0x3C44CdDdB6a900fa2b585dd299e03d12FA4293BC": { + "balance": "0x3782dace9d90000000" + }, + "0x90F79bf6EB2c4f870365E785982E1f101E93b906": { + "balance": "0x3782dace9d90000000" + }, + "0x15d34AAf54267DB7D7c367839AAf71A00a2C6A65": { + "balance": "0x3782dace9d90000000" + }, + "0x9965507D1a55bcC2695C58ba16FB37d819B0A4dc": { + "balance": "0x3782dace9d90000000" + }, + "0x976EA74026E726554dB657fA54763abd0C3a0aa9": { + "balance": "0x3782dace9d90000000" + }, + "0x14dC79964da2C08b23698B3D3cc7Ca32193d9955": { + "balance": "0x3782dace9d90000000" + }, + "0x23618e81E3f5cdF7f54C3d65f7FBc0aBf5B21E8f": { + "balance": "0x3782dace9d90000000" + }, + "0xa0Ee7A142d267C1f36714E4a8F75612F20a79720": { + "balance": "0x3782dace9d90000000" + }, + "0xBcd4042DE499D14e55001CcbB24a551F3b954096": { + "balance": "0x3782dace9d90000000" + }, + "0x71bE63f3384f5fb98995898A86B02Fb2426c5788": { + "balance": "0x3782dace9d90000000" + }, + "0xFABB0ac9d68B0B445fB7357272Ff202C5651694a": { + "balance": "0x3782dace9d90000000" + }, + "0x1CBd3b2770909D4e10f157cABC84C7264073C9Ec": { + "balance": "0x3782dace9d90000000" + }, + "0xdF3e18d64BC6A983f673Ab319CCaE4f1a57C7097": { + "balance": "0x3782dace9d90000000" + }, + "0xcd3B766CCDd6AE721141F452C550Ca635964ce71": { + "balance": "0x3782dace9d90000000" + }, + "0x2546BcD3c84621e976D8185a91A922aE77ECEc30": { + "balance": "0x3782dace9d90000000" + }, + "0xbDA5747bFD65F08deb54cb465eB87D40e51B197E": { + "balance": "0x3782dace9d90000000" + }, + "0xdD2FD4581271e230360230F9337D5c0430Bf44C0": { + "balance": "0x3782dace9d90000000" + }, + "0x8626f6940E2eb28930eFb4CeF49B2d1F2C9C1199": { + "balance": "0x3782dace9d90000000" + }, + "0x0000777700000000000000000000000000000006": { + "contractName": "ProxiedAddressManager", + "storage": {}, + "code": "0x608060405234801561001057600080fd5b50600436106100625760003560e01c8063656b06a414610067578063715018a6146100b75780638da5cb5b146100c1578063decd8e39146100d2578063e1c7392a146100e5578063f2fde38b146100ed575b600080fd5b61009b610075366004610428565b60009182526065602090815260408084209284529190529020546001600160a01b031690565b6040516001600160a01b03909116815260200160405180910390f35b6100bf610100565b005b6033546001600160a01b031661009b565b6100bf6100e0366004610466565b610114565b6100bf610196565b6100bf6100fb36600461049b565b6102ac565b610108610322565b610112600061037c565b565b61011c610322565b600083815260656020908152604080832085845282529182902080546001600160a01b038581166001600160a01b0319831681179093558451928352169181018290529091849186917fe41a6e8584d6e19a0dfc5f9331be4ebe61b5f025d45da164c9ca6ee9b837cea9910160405180910390a350505050565b600054610100900460ff16158080156101b65750600054600160ff909116105b806101d05750303b1580156101d0575060005460ff166001145b6102385760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b60648201526084015b60405180910390fd5b6000805460ff19166001179055801561025b576000805461ff0019166101001790555b6102636103ce565b80156102a9576000805461ff0019169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b50565b6102b4610322565b6001600160a01b0381166103195760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b606482015260840161022f565b6102a98161037c565b6033546001600160a01b031633146101125760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015260640161022f565b603380546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b600054610100900460ff166103f55760405162461bcd60e51b815260040161022f906104bd565b610112600054610100900460ff1661041f5760405162461bcd60e51b815260040161022f906104bd565b6101123361037c565b6000806040838503121561043b57600080fd5b50508035926020909101359150565b80356001600160a01b038116811461046157600080fd5b919050565b60008060006060848603121561047b57600080fd5b83359250602084013591506104926040850161044a565b90509250925092565b6000602082840312156104ad57600080fd5b6104b68261044a565b9392505050565b6020808252602b908201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960408201526a6e697469616c697a696e6760a81b60608201526080019056fea26469706673582212201bde2ef0e6b00897cd2f3d30bc5c6844d34e123c3113dc0529e54f445274212064736f6c63430008140033", + "balance": "0x0" + }, + "0x1000777700000000000000000000000000000006": { + "contractName": "AddressManagerProxy", + "storage": { + "0x0000000000000000000000000000000000000000000000000000000000000000": "0x0000000000000000000000000000000000000000000000000000000000000001", + "0x0000000000000000000000000000000000000000000000000000000000000033": "0x000000000000000000000000f39fd6e51aad88f6f4ce6ab8827279cfffb92266", + "0xff8959e8c71db849773cf97c3b9d85b4a718b66a9dd50782caaf354b57db3d6b": "0x0000000000000000000000001000777700000000000000000000000000000001", + "0x99058c93124480b002badc5d0110ed1acb6b27cdc34775dc56d6fed405dc8136": "0x0000000000000000000000001000777700000000000000000000000000000004", + "0xc1988a2b2382b3e0c971e65b2d2a310b3ef0066b56157529f8be7100312a0110": "0x0000000000000000000000001000777700000000000000000000000000000002", + "0x28e5f95e0b28f5e8eff2ad0cf10e2257df753576fdd11a2049fe5980bb764c93": "0x0000000000000000000000001000777700000000000000000000000000000008", + "0x1bd1360fa36c01e6696e23e183c6ff9a991d80bbd5bc3937f43f6b80d21550bb": "0x0000000000000000000000001000777700000000000000000000000000000009", + "0x4e5812bcbdde873c5fe239352366ed228c76696457942c5015c492f11c9b7da2": "0x0000000000000000000000001000777700000000000000000000000000000003", + "0x3735f25b8e8f7ccb1ab37444024f5f04c1a1168bf4782d75a02bf365a9bce56f": "0x0000000000000000000000001000777700000000000000000000000000000007", + "0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103": "0x70997970C51812dc3A010C7d01b50e0d17dc79C8", + "0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc": "0x0000777700000000000000000000000000000006" + }, + "code": "0x60806040526004361061004e5760003560e01c80633659cfe6146100655780634f1ef286146100855780635c60da1b146100985780638f283970146100c9578063f851a440146100e95761005d565b3661005d5761005b6100fe565b005b61005b6100fe565b34801561007157600080fd5b5061005b6100803660046106b3565b610118565b61005b6100933660046106ce565b610155565b3480156100a457600080fd5b506100ad6101bc565b6040516001600160a01b03909116815260200160405180910390f35b3480156100d557600080fd5b5061005b6100e43660046106b3565b6101ed565b3480156100f557600080fd5b506100ad61020d565b61010661022e565b6101166101116102c3565b6102cd565b565b6101206102f1565b6001600160a01b0316330361014d5761014a81604051806020016040528060008152506000610324565b50565b61014a6100fe565b61015d6102f1565b6001600160a01b031633036101b4576101af8383838080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525060019250610324915050565b505050565b6101af6100fe565b60006101c66102f1565b6001600160a01b031633036101e2576101dd6102c3565b905090565b6101ea6100fe565b90565b6101f56102f1565b6001600160a01b0316330361014d5761014a8161034f565b60006102176102f1565b6001600160a01b031633036101e2576101dd6102f1565b6102366102f1565b6001600160a01b031633036101165760405162461bcd60e51b815260206004820152604260248201527f5472616e73706172656e745570677261646561626c6550726f78793a2061646d60448201527f696e2063616e6e6f742066616c6c6261636b20746f2070726f78792074617267606482015261195d60f21b608482015260a4015b60405180910390fd5b60006101dd6103a3565b3660008037600080366000845af43d6000803e8080156102ec573d6000f35b3d6000fd5b60007fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035b546001600160a01b0316919050565b61032d836103cb565b60008251118061033a5750805b156101af57610349838361040b565b50505050565b7f7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f6103786102f1565b604080516001600160a01b03928316815291841660208301520160405180910390a161014a81610437565b60007f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc610315565b6103d4816104e0565b6040516001600160a01b038216907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b90600090a250565b606061043083836040518060600160405280602781526020016107c560279139610574565b9392505050565b6001600160a01b03811661049c5760405162461bcd60e51b815260206004820152602660248201527f455243313936373a206e65772061646d696e20697320746865207a65726f206160448201526564647265737360d01b60648201526084016102ba565b807fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035b80546001600160a01b0319166001600160a01b039290921691909117905550565b6001600160a01b0381163b61054d5760405162461bcd60e51b815260206004820152602d60248201527f455243313936373a206e657720696d706c656d656e746174696f6e206973206e60448201526c1bdd08184818dbdb9d1c9858dd609a1b60648201526084016102ba565b807f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc6104bf565b6060600080856001600160a01b0316856040516105919190610775565b600060405180830381855af49150503d80600081146105cc576040519150601f19603f3d011682016040523d82523d6000602084013e6105d1565b606091505b50915091506105e2868383876105ec565b9695505050505050565b6060831561065b578251600003610654576001600160a01b0385163b6106545760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e747261637400000060448201526064016102ba565b5081610665565b610665838361066d565b949350505050565b81511561067d5781518083602001fd5b8060405162461bcd60e51b81526004016102ba9190610791565b80356001600160a01b03811681146106ae57600080fd5b919050565b6000602082840312156106c557600080fd5b61043082610697565b6000806000604084860312156106e357600080fd5b6106ec84610697565b9250602084013567ffffffffffffffff8082111561070957600080fd5b818601915086601f83011261071d57600080fd5b81358181111561072c57600080fd5b87602082850101111561073e57600080fd5b6020830194508093505050509250925092565b60005b8381101561076c578181015183820152602001610754565b50506000910152565b60008251610787818460208701610751565b9190910192915050565b60208152600082518060208401526107b0816040850160208701610751565b601f01601f1916919091016040019291505056fe416464726573733a206c6f772d6c6576656c2064656c65676174652063616c6c206661696c6564a2646970667358221220e0c34caa93cb549737d2002fe0da3463bee0317add6c2f3da35498d4b65a974464736f6c63430008140033", + "balance": "0x0" + }, + "0x0000777700000000000000000000000000000001": { + "contractName": "ProxiedTaikoL2", + "storage": {}, + "code": "0x608060405234801561001057600080fd5b50600436106101585760003560e01c80638da5cb5b116100c3578063cce03bf31161007c578063cce03bf314610359578063da69d3db1461036c578063dac5df781461037f578063e8e2c5fb14610388578063f2fde38b146103c4578063f535bd56146103d757600080fd5b80638da5cb5b146102a95780639ee512f2146102ba578063a7e022d1146102d3578063a86f9d9e146102e6578063c3f909d4146102f9578063c7b969081461032757600080fd5b80635c975abb116101155780635c975abb146102245780636c6563f614610238578063715018a61461024b5780638456cb59146102535780638551f41e1461025b5780638cfb04591461027b57600080fd5b806310da37381461015d57806323ac7136146101975780632f980473146101aa5780633ab76e9f146101bd5780633f4ba83a146101e8578063591aad8a146101f2575b600080fd5b6101847f92954368afd3caa1f3ce3ead0069c1af414054aefe1ef9aeacc1bf426222ce3881565b6040519081526020015b60405180910390f35b6101846101a536600461147d565b610402565b60005b604051901515815260200161018e565b6065546101d0906001600160a01b031681565b6040516001600160a01b03909116815260200161018e565b6101f0610461565b005b610205610200366004611498565b6104df565b6040805160ff909416845260208401929092529082015260600161018e565b6101ad609754610100900460ff1660021490565b6101d06102463660046114de565b61071a565b6101f0610731565b6101f0610745565b610184610269366004611513565b60c96020526000908152604090205481565b61028e61028936600461147d565b6107be565b6040805182518152602092830151928101929092520161018e565b6033546001600160a01b03166101d0565b6101d071777735367b36bc9b61c50022d9d0700db4ec81565b6101846102e1366004611540565b610833565b6101d06102f4366004611573565b610865565b604080518082018252630393870080825260086020928301908152835191825251918101919091520161018e565b60cc5461034190600160801b90046001600160401b031681565b6040516001600160401b03909116815260200161018e565b6101f06103673660046115ab565b61087b565b6101f061037a3660046115e5565b610a3a565b61018460cb5481565b6103af610396366004611513565b60ca602052600090815260409020805460019091015482565b6040805192835260208301919091520161018e565b6101f06103d236600461162b565b610cf9565b60cc546103ea906001600160801b031681565b6040516001600160801b03909116815260200161018e565b600043826001600160401b03161061041c57506000919050565b6104286101004361165e565b826001600160401b03161061044557506001600160401b03164090565b506001600160401b0316600090815260c9602052604090205490565b610475609754610100900460ff1660021490565b6104925760405163bae6e2a960e01b815260040160405180910390fd5b61049a610d72565b6097805461ff0019166101001790556040513381527f5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa906020015b60405180910390a1565b60008060008360ff166001141580156104fc57508360ff16600214155b1561051a5760405163bcd2d90d60e01b815260040160405180910390fd5b8360ff1660011461054b577fc6047f9441ed7d6d3045406e95c07cd85c778e4b8cef3ca7abac09b95c709ee561056d565b7f79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f817985b915060008460ff166001146105a2577fad77eceea844778cb4376153fc8f06f12f1695df4585bf75bfb17ec19ce908186105c4565b7fb4a95509ce05fe8d45987859a067780d16a367c0e2cacf79cd301b93fb7179405b905060008560ff166001146105f9577f71620584f61c57e688bbd3fd7a39a036e588d962c4c830f3dacbc15c917e02f261061b565b7f45b59254b0320fd853f3f38ac574999e91bd75fd5e6cab9c22c5e71fc6d276e45b82880192831001905060ff86166001036106555761064e8282600170014551231950b75fc4402da1732fc9bebe19610dcc565b92506106c4565b61069d7f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a16106988484600170014551231950b75fc4402da1732fc9bebe19610dcc565b610e1b565b90925090506106c18282600170014551231950b75fc4402da1732fc9bebe19610dcc565b92505b7f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a0831115610711576107088370014551231950b75fc4402da1732fc9bebe1961165e565b92506001851894505b50509250925092565b6000610727848484610e3a565b90505b9392505050565b610739610d72565b6107436000610eee565b565b610759609754610100900460ff1660021490565b156107775760405163bae6e2a960e01b815260040160405180910390fd5b61077f610d72565b6097805461ff0019166102001790556040513381527f62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a258906020016104d5565b604080518082019091526000808252602082015260006001600160401b038316156107e957826107fd565b60cc54600160801b90046001600160401b03165b6001600160401b0316600090815260ca602090815260409182902082518084019093528054835260010154908201529392505050565b600061085d61085660408051808201909152630393870081526008602082015290565b8484610f40565b509392505050565b6000610872468484610e3a565b90505b92915050565b600054610100900460ff161580801561089b5750600054600160ff909116105b806108b55750303b1580156108b5575060005460ff166001145b61091d5760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b60648201526084015b60405180910390fd5b6000805460ff191660011790558015610940576000805461ff0019166101001790555b61094983611093565b60014611158061096057506001600160401b034610155b1561097e576040516306cffa2760e01b815260040160405180910390fd5b60014311156109a057604051635a0f9e4160e11b815260040160405180910390fd5b43156109c75760006109b360014361165e565b600081815260c96020526040902090409055505b60cc80546001600160801b0319166001600160801b0384161790556109eb436110b6565b5060cb558015610a35576000805461ff0019169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b505050565b831580610a45575082155b80610a5757506001600160401b038216155b80610a72575043600114158015610a72575063ffffffff8116155b15610a905760405163053fd54760e01b815260040160405180910390fd5b3371777735367b36bc9b61c50022d9d0700db4ec14610ac257604051636494e9f760e01b815260040160405180910390fd5b6000194301600080610ad3836110b6565b915091508160cb5414610af95760405163d719258d60e01b815260040160405180910390fd5b6000610b1960408051808201909152630393870081526008602082015290565b90506000610b28828888610f40565b60cc80546001600160801b0319166001600160801b03929092169190911790559050488114610b6a576040516336d54d4f60e11b815260040160405180910390fd5b610b866d7369676e616c5f7365727669636560901b6000610865565b6001600160a01b03166366ca2bc0896040518263ffffffff1660e01b8152600401610bb391815260200190565b6020604051808303816000875af1158015610bd2573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610bf69190611671565b50604080518a8152602081018a90526001600160401b038916917e4ce985b8852a486571d0545799251fd671adcf33b7854a5f0f6a6a2431a555910160405180910390a2600085815260c960209081526040808320884090819055815180830183528d81528084018d81526001600160401b038d1680875260ca865295849020915182555160019091015560cb87905560cc8054600160801b90950267ffffffffffffffff60801b198616811790915582519182526001600160801b03908116941693909317918301919091527fb01a20e23471fa4d881340e2b742c2f84cb2f7a714b34ba370b815478ae4aae0910160405180910390a1505050505050505050565b610d01610d72565b6001600160a01b038116610d665760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b6064820152608401610914565b610d6f81610eee565b50565b6033546001600160a01b031633146107435760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610914565b600060405160408152602080820152602060408201528460608201528560808201528360a08201528260c082015260208160e08360056107d05a03fa610e1157600080fd5b5195945050505050565b6000806000198385098385029250828110838203039150509250929050565b60655460405163195ac1a960e21b815260048101859052602481018490526000916001600160a01b03169063656b06a490604401602060405180830381865afa158015610e8b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610eaf919061168a565b905081158015610ec657506001600160a01b038116155b1561072a57604051631467050360e21b81526004810185905260248101849052604401610914565b603380546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b60cc5460009081906001600160801b03161561107e5760cc54600090610f769063ffffffff8616906001600160801b03166116a7565b60cc54909150600090600160801b90046001600160401b031615801590610fb2575060cc546001600160401b03600160801b9091048116908716115b15610fe05760cc54610fd490600160801b90046001600160401b0316876116ba565b6001600160401b031690505b6001600160801b03811615611037578651600090611007906001600160401b0316836116e1565b9050806001600160801b03168311611020576001611033565b6110336001600160801b0382168461165e565b9250505b611048826001600160801b03611149565b9250611079836001600160801b031688600001516001600160401b03168960200151611074919061170c565b61115e565b935050505b8160000361108b57600191505b935093915050565b61109b6111a9565b6110a48161121d565b506097805461ffff1916610101179055565b6000806110c1611441565b60005b60ff811080156110d75750806001018510155b15611109576000198186030180408360ff830661010081106110fb576110fb611739565b6020020152506001016110c4565b5046611fe08201526120008120925083408161112660ff8761174f565b610100811061113757611137611739565b60200201526120009020919391925050565b60008183116111585782610872565b50919050565b60008160000361118157604051636296f1b960e11b815260040160405180910390fd5b81670de0b6b3a76400006111958585611266565b61119f9190611763565b6108729190611763565b600054610100900460ff166112145760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201526a6e697469616c697a696e6760a81b6064820152608401610914565b61074333610eee565b6001600160a01b03811661124457604051638ed88b2560e01b815260040160405180910390fd5b606580546001600160a01b0319166001600160a01b0392909216919091179055565b6000808261127c670de0b6b3a76400008661170c565b6112869190611763565b9050680755bf798b4a1bf1e48111156112a55750680755bf798b4a1bf1e45b6112ae816112b6565b949350505050565b6000680248ce36a70cb26b3e1982136112d157506000919050565b680755bf798b4a1bf1e582126112fa57604051631a93c68960e11b815260040160405180910390fd5b6503782dace9d9604e83901b059150600060606bb17217f7d1cf79abc9e3b39884821b056001605f1b01901d6bb17217f7d1cf79abc9e3b39881029093036c240c330e9fb2d9cbaf0fd5aafb1981018102606090811d6d0277594991cfc85f6e2461837cd9018202811d6d1a521255e34f6a5061b25ef1c9c319018202811d6db1bbb201f443cf962f1a1d3db4a5018202811d6e02c72388d9f74f51a9331fed693f1419018202811d6e05180bb14799ab47a8a8cb2a527d57016d02d16720577bd19bf614176fe9ea6c10fe68e7fd37d0007b713f765084018402831d9081019084016d01d3967ed30fc4f89c02bab5708119010290911d6e0587f503bb6ea29d25fcb740196450019091026d360d7aeea093263ecc6e0ecb291760621b010574029d9dc38563c32e5c2f6dc192ee70ef65f9978af30260c3939093039290921c92915050565b604051806120000160405280610100906020820280368337509192915050565b80356001600160401b038116811461147857600080fd5b919050565b60006020828403121561148f57600080fd5b61087282611461565b600080604083850312156114ab57600080fd5b82359150602083013560ff811681146114c357600080fd5b809150509250929050565b8035801515811461147857600080fd5b6000806000606084860312156114f357600080fd5b833592506020840135915061150a604085016114ce565b90509250925092565b60006020828403121561152557600080fd5b5035919050565b803563ffffffff8116811461147857600080fd5b6000806040838503121561155357600080fd5b61155c83611461565b915061156a6020840161152c565b90509250929050565b6000806040838503121561158657600080fd5b8235915061156a602084016114ce565b6001600160a01b0381168114610d6f57600080fd5b600080604083850312156115be57600080fd5b82356115c981611596565b915060208301356001600160801b03811681146114c357600080fd5b600080600080608085870312156115fb57600080fd5b843593506020850135925061161260408601611461565b91506116206060860161152c565b905092959194509250565b60006020828403121561163d57600080fd5b813561072a81611596565b634e487b7160e01b600052601160045260246000fd5b8181038181111561087557610875611648565b60006020828403121561168357600080fd5b5051919050565b60006020828403121561169c57600080fd5b815161072a81611596565b8082018082111561087557610875611648565b6001600160401b038281168282160390808211156116da576116da611648565b5092915050565b6001600160801b0381811683821602808216919082811461170457611704611648565b505092915050565b808202811582820484141761087557610875611648565b634e487b7160e01b600052601260045260246000fd5b634e487b7160e01b600052603260045260246000fd5b60008261175e5761175e611723565b500690565b60008261177257611772611723565b50049056fea264697066735822122067c761821b434d92eb46ff2854c0c72a1806271bfe35071900eb95aefcd53b4264736f6c63430008140033", + "balance": "0x0" + }, + "0x1000777700000000000000000000000000000001": { + "contractName": "TaikoL2Proxy", + "storage": { + "0x0000000000000000000000000000000000000000000000000000000000000033": "0x000000000000000000000000f39fd6e51aad88f6f4ce6ab8827279cfffb92266", + "0x0000000000000000000000000000000000000000000000000000000000000097": "0x0000000000000000000000000000000000000000000000000000000000000101", + "0x00000000000000000000000000000000000000000000000000000000000000cb": "0xb1cdc1a3b51cd0ae1113eb88f95dfd26aab10c50b39e31811e63cffc250b0da2", + "0x00000000000000000000000000000000000000000000000000000000000000cc": "0x0000000000000000000000000000000000000000000000000000000000000001", + "0x0000000000000000000000000000000000000000000000000000000000000065": "0x0000000000000000000000001000777700000000000000000000000000000006", + "0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103": "0x70997970C51812dc3A010C7d01b50e0d17dc79C8", + "0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc": "0x0000777700000000000000000000000000000001" + }, + "code": "0x60806040526004361061004e5760003560e01c80633659cfe6146100655780634f1ef286146100855780635c60da1b146100985780638f283970146100c9578063f851a440146100e95761005d565b3661005d5761005b6100fe565b005b61005b6100fe565b34801561007157600080fd5b5061005b6100803660046106b3565b610118565b61005b6100933660046106ce565b610155565b3480156100a457600080fd5b506100ad6101bc565b6040516001600160a01b03909116815260200160405180910390f35b3480156100d557600080fd5b5061005b6100e43660046106b3565b6101ed565b3480156100f557600080fd5b506100ad61020d565b61010661022e565b6101166101116102c3565b6102cd565b565b6101206102f1565b6001600160a01b0316330361014d5761014a81604051806020016040528060008152506000610324565b50565b61014a6100fe565b61015d6102f1565b6001600160a01b031633036101b4576101af8383838080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525060019250610324915050565b505050565b6101af6100fe565b60006101c66102f1565b6001600160a01b031633036101e2576101dd6102c3565b905090565b6101ea6100fe565b90565b6101f56102f1565b6001600160a01b0316330361014d5761014a8161034f565b60006102176102f1565b6001600160a01b031633036101e2576101dd6102f1565b6102366102f1565b6001600160a01b031633036101165760405162461bcd60e51b815260206004820152604260248201527f5472616e73706172656e745570677261646561626c6550726f78793a2061646d60448201527f696e2063616e6e6f742066616c6c6261636b20746f2070726f78792074617267606482015261195d60f21b608482015260a4015b60405180910390fd5b60006101dd6103a3565b3660008037600080366000845af43d6000803e8080156102ec573d6000f35b3d6000fd5b60007fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035b546001600160a01b0316919050565b61032d836103cb565b60008251118061033a5750805b156101af57610349838361040b565b50505050565b7f7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f6103786102f1565b604080516001600160a01b03928316815291841660208301520160405180910390a161014a81610437565b60007f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc610315565b6103d4816104e0565b6040516001600160a01b038216907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b90600090a250565b606061043083836040518060600160405280602781526020016107c560279139610574565b9392505050565b6001600160a01b03811661049c5760405162461bcd60e51b815260206004820152602660248201527f455243313936373a206e65772061646d696e20697320746865207a65726f206160448201526564647265737360d01b60648201526084016102ba565b807fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035b80546001600160a01b0319166001600160a01b039290921691909117905550565b6001600160a01b0381163b61054d5760405162461bcd60e51b815260206004820152602d60248201527f455243313936373a206e657720696d706c656d656e746174696f6e206973206e60448201526c1bdd08184818dbdb9d1c9858dd609a1b60648201526084016102ba565b807f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc6104bf565b6060600080856001600160a01b0316856040516105919190610775565b600060405180830381855af49150503d80600081146105cc576040519150601f19603f3d011682016040523d82523d6000602084013e6105d1565b606091505b50915091506105e2868383876105ec565b9695505050505050565b6060831561065b578251600003610654576001600160a01b0385163b6106545760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e747261637400000060448201526064016102ba565b5081610665565b610665838361066d565b949350505050565b81511561067d5781518083602001fd5b8060405162461bcd60e51b81526004016102ba9190610791565b80356001600160a01b03811681146106ae57600080fd5b919050565b6000602082840312156106c557600080fd5b61043082610697565b6000806000604084860312156106e357600080fd5b6106ec84610697565b9250602084013567ffffffffffffffff8082111561070957600080fd5b818601915086601f83011261071d57600080fd5b81358181111561072c57600080fd5b87602082850101111561073e57600080fd5b6020830194508093505050509250925092565b60005b8381101561076c578181015183820152602001610754565b50506000910152565b60008251610787818460208701610751565b9190910192915050565b60208152600082518060208401526107b0816040850160208701610751565b601f01601f1916919091016040019291505056fe416464726573733a206c6f772d6c6576656c2064656c65676174652063616c6c206661696c6564a2646970667358221220e0c34caa93cb549737d2002fe0da3463bee0317add6c2f3da35498d4b65a974464736f6c63430008140033", + "balance": "0x0" + }, + "0x0000777700000000000000000000000000000004": { + "contractName": "ProxiedBridge", + "storage": {}, + "code": "0x6080604052600436106101395760003560e01c80635fc34de7116100ab578063a665077e1161006f578063a665077e1461039f578063a86f9d9e146103bf578063aedf6cd3146103df578063d0496d6a146103ff578063eefbf17e1461043f578063f2fde38b1461047757600080fd5b80635fc34de7146103165780636c6563f614610337578063715018a6146103575780638456cb591461036c5780638da5cb5b1461038157600080fd5b80633c6cf473116100fd5780633c6cf473146102145780633f4ba83a1461025157806340d0ff96146102665780634f5f9772146102865780635c975abb146102b65780635d0bd986146102d757600080fd5b80630be0b938146101455780631136c0501461016757806319ab453c146101875780631b5fd0ab146101a75780633ab76e9f146101dc57600080fd5b3661014057005b600080fd5b34801561015157600080fd5b50610165610160366004611c78565b610497565b005b34801561017357600080fd5b50610165610182366004611cca565b6106be565b34801561019357600080fd5b506101656101a2366004611d86565b610a6a565b3480156101b357600080fd5b506101c76101c2366004611cca565b610b82565b60405190151581526020015b60405180910390f35b3480156101e857600080fd5b506065546101fc906001600160a01b031681565b6040516001600160a01b0390911681526020016101d3565b34801561022057600080fd5b5061024461022f366004611da3565b60cb6020526000908152604090205460ff1681565b6040516101d39190611dd2565b34801561025d57600080fd5b50610165610be0565b34801561027257600080fd5b50610165610281366004611cca565b610c5e565b34801561029257600080fd5b506101c76102a1366004611da3565b60ca6020526000908152604090205460ff1681565b3480156102c257600080fd5b506101c7609754610100900460ff1660021490565b3480156102e357600080fd5b506102f76102f2366004611da3565b610f29565b6040805192151583526001600160a01b039091166020830152016101d3565b610329610324366004611dfa565b610f56565b6040516101d3929190611f6f565b34801561034357600080fd5b506101fc610352366004611f88565b6112d7565b34801561036357600080fd5b506101656112e4565b34801561037857600080fd5b506101656112f8565b34801561038d57600080fd5b506033546001600160a01b03166101fc565b3480156103ab57600080fd5b506101c76103ba366004611cca565b611371565b3480156103cb57600080fd5b506101fc6103da366004611fc1565b6113bc565b3480156103eb57600080fd5b506101c76103fa366004611dfa565b6113d2565b34801561040b57600080fd5b506104146114ab565b60408051825181526020808401516001600160a01b03169082015291810151908201526060016101d3565b34801561044b57600080fd5b5060c95461045f906001600160801b031681565b6040516001600160801b0390911681526020016101d3565b34801561048357600080fd5b50610165610492366004611d86565b611525565b60975460ff16600119016104be5760405163dfc60d8560e01b815260040160405180910390fd5b6097805460ff191660021790556104df609754610100900460ff1660021490565b156104fd5760405163bae6e2a960e01b815260040160405180910390fd5b816060013546811461052257604051631c6c777560e31b815260040160405180910390fd5b61012083013515806105315750815b156105775761054660a0840160808501611d86565b6001600160a01b0316336001600160a01b031614610577576040516372b6e1c360e11b815260040160405180910390fd5b60008360405160200161058a9190612182565b60408051601f19818403018152919052805160209091012090506001600082815260cb602052604090205460ff1660038111156105c9576105c9611dbc565b146105e757604051636e10a9f360e01b815260040160405180910390fd5b60006106026a195d1a195c97dd985d5b1d60aa1b60006113bc565b60405163ba0bbd9560e01b815230600482015260e087013560248201529091506001600160a01b0382169063ba0bbd9590604401600060405180830381600087803b15801561065057600080fd5b505af1158015610664573d6000803e3d6000fd5b5050505061067385835a61159e565b15610688576106838260026116e5565b6106aa565b6106938260036116e5565b6106aa6001600160a01b03821660e0870135611838565b50506097805460ff19166001179055505050565b60975460ff16600119016106e55760405163dfc60d8560e01b815260040160405180910390fd5b6097805460ff19166002179055610706609754610100900460ff1660021490565b156107245760405163bae6e2a960e01b815260040160405180910390fd5b826060013546811461074957604051631c6c777560e31b815260040160405180910390fd5b61012084013515801561077d575061076760a0850160808601611d86565b6001600160a01b0316336001600160a01b031614155b1561079b576040516372b6e1c360e11b815260040160405180910390fd5b6000846040516020016107ae9190612182565b60408051601f198184030181529190528051602090910120905060008082815260cb602052604090205460ff1660038111156107ec576107ec611dbc565b1461080a57604051630cfafbf960e01b815260040160405180910390fd5b600061081c82876040013587876118d3565b90508061083c57604051635ea5ecc760e01b815260040160405180910390fd5b60006108576a195d1a195c97dd985d5b1d60aa1b60006113bc565b90506001600160a01b03811663ba0bbd953061087c6101008b013560e08c01356121ab565b6040516001600160e01b031960e085901b1681526001600160a01b0390921660048301526024820152604401600060405180830381600087803b1580156108c257600080fd5b505af11580156108d6573d6000803e3d6000fd5b50600092508291503090506108f160c08b0160a08c01611d86565b6001600160a01b0316148061091e5750600061091360c08b0160a08c01611d86565b6001600160a01b0316145b1561093257506002905060e08801356109a1565b600061094460a08b0160808c01611d86565b6001600160a01b0316336001600160a01b03161461096757896101200135610969565b5a5b90506109768a878361159e565b15610984576002925061099f565b6001925061099f6001600160a01b03851660e08c0135611838565b505b6109ab85836116e5565b6000806109be60e08c0160c08d01611d86565b6001600160a01b0316146109e1576109dc60e08b0160c08c01611d86565b6109f1565b6109f160a08b0160808c01611d86565b90506001600160a01b0381163303610a2f576000610a14836101008d01356121ab565b9050610a296001600160a01b03831682611838565b50610a51565b610a3e336101008c0135611838565b610a516001600160a01b03821683611838565b50506097805460ff191660011790555050505050505050565b600054610100900460ff1615808015610a8a5750600054600160ff909116105b80610aa45750303b158015610aa4575060005460ff166001145b610b0c5760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b60648201526084015b60405180910390fd5b6000805460ff191660011790558015610b2f576000805461ff0019166101001790555b610b3882611982565b8015610b7e576000805461ff0019169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b5050565b600046846040013514610b9757506000610bd9565b610bd6610bca85604051602001610bae9190612182565b6040516020818303038152906040528051906020012060031890565b856060013585856118d3565b90505b9392505050565b610bf4609754610100900460ff1660021490565b610c115760405163bae6e2a960e01b815260040160405180910390fd5b610c196119a5565b6097805461ff0019166101001790556040513381527f5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa906020015b60405180910390a1565b60975460ff1660011901610c855760405163dfc60d8560e01b815260040160405180910390fd5b6097805460ff19166002179055610ca6609754610100900460ff1660021490565b15610cc45760405163bae6e2a960e01b815260040160405180910390fd5b8260400135468114610ce957604051631c6c777560e31b815260040160405180910390fd5b600084604051602001610cfc9190612182565b60408051601f198184030181529181528151602092830120600081815260ca90935291205490915060ff1615610d4557604051638759835d60e01b815260040160405180910390fd5b6000610d5a60038318876060013587876118d3565b905080610d7a5760405163f149234f60e01b815260040160405180910390fd5b600082815260ca60205260408120805460ff19166001179055610dac906a195d1a195c97dd985d5b1d60aa1b906113bc565b60405163ba0bbd9560e01b815230600482015260e088013560248201526001600160a01b03919091169063ba0bbd9590604401600060405180830381600087803b158015610df957600080fd5b505af1158015610e0d573d6000803e3d6000fd5b505050506000610e40630600bf7360e31b886020016020810190610e319190611d86565b6001600160a01b0316906119ff565b90508015610ec157610e586040880160208901611d86565b6001600160a01b0316633005fb988860e0013589866040518463ffffffff1660e01b8152600401610e8a9291906121be565b6000604051808303818588803b158015610ea357600080fd5b505af1158015610eb7573d6000803e3d6000fd5b5050505050610ee8565b610ee860e0880135610ed960a08a0160808b01611d86565b6001600160a01b031690611838565b60405183907fc6fbc1fa0145a394c9c414b2ae7bd634eb50dd888938bcd75692ae427b680fa290600090a250506097805460ff191660011790555050505050565b600080610f41836562726964676560d01b60016112d7565b6001600160a01b038116151594909350915050565b604080516101808101825260008082526020820181905291810182905260608082018390526080820183905260a0820183905260c0820183905260e0820183905261010082018390526101208201839052610140820181905261016082015260975460ff1660011901610fdc5760405163dfc60d8560e01b815260040160405180910390fd5b6097805460ff19166002179055610ffd609754610100900460ff1660021490565b1561101b5760405163bae6e2a960e01b815260040160405180910390fd5b600061102d60a0850160808601611d86565b6001600160a01b03160361105457604051633c4f94dd60e11b815260040160405180910390fd5b6000806110648560600135610f29565b915091508161108657604051631c6c777560e31b815260040160405180910390fd5b468560600135036110aa57604051631c6c777560e31b815260040160405180910390fd5b60006110bc60c0870160a08801611d86565b6001600160a01b0316036110e357604051636401c93560e11b815260040160405180910390fd5b6001600160a01b0381166110fd60c0870160a08801611d86565b6001600160a01b03160361112457604051636401c93560e11b815260040160405180910390fd5b600061113961010087013560e08801356121ab565b905034811461115b57604051634ac2abdf60e11b815260040160405180910390fd5b61117881610ed96a195d1a195c97dd985d5b1d60aa1b60006113bc565b611181866122ad565b60c980549195506001600160801b0390911690600061119f836123ab565b82546101009290920a6001600160801b038181021990931691831602179091551684523360208086019190915246604080870191909152516111e3918691016123d1565b6040516020818303038152906040528051906020012094506112176d7369676e616c5f7365727669636560901b60006113bc565b6001600160a01b03166366ca2bc0866040518263ffffffff1660e01b815260040161124491815260200190565b6020604051808303816000875af1158015611263573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061128791906123e4565b50847f769685e0f49529ee2429cb28b4b48bd962ff754c08a2849804458ad716d75dcf856040516112b891906123d1565b60405180910390a250506097805460ff19166001179055509092909150565b6000610bd6848484611a8e565b6112ec6119a5565b6112f66000611b42565b565b61130c609754610100900460ff1660021490565b1561132a5760405163bae6e2a960e01b815260040160405180910390fd5b6113326119a5565b6097805461ff0019166102001790556040513381527f62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a25890602001610c54565b60004684606001351461138657506000610bd9565b610bd68460405160200161139a9190612182565b60405160208183030381529060405280519060200120856040013585856118d3565b60006113c9468484611a8e565b90505b92915050565b6000468260400135146113e757506000919050565b6114036d7369676e616c5f7365727669636560901b60006113bc565b6001600160a01b03166332676bc630846040516020016114239190612182565b604051602081830303815290604052805190602001206040518363ffffffff1660e01b815260040161146a9291906001600160a01b03929092168252602082015260400190565b602060405180830381865afa158015611487573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906113cc91906123fd565b604080516060810182526000808252602082018190529181019190915260cc5415806114d9575060cc546001145b156114f757604051635ceed17360e01b815260040160405180910390fd5b506040805160608101825260cc54815260cd546001600160a01b0316602082015260ce549181019190915290565b61152d6119a5565b6001600160a01b0381166115925760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b6064820152608401610b03565b61159b81611b42565b50565b6000816000036115c1576040516308c2ad5360e01b815260040160405180910390fd5b60405180606001604052808481526020018560200160208101906115e59190611d86565b6001600160a01b039081168252604087810135602093840152835160cc559183015160cd80546001600160a01b03191691909216179055015160ce5561163160c0850160a08601611d86565b6001600160a01b03168260e086013561164e61014088018861241a565b60405161165c929190612461565b600060405180830381858888f193505050503d806000811461169a576040519150601f19603f3d011682016040523d82523d6000602084013e61169f565b606091505b5050604080516060810182526001808252602082018190526000199190920181905260cc82905560cd80546001600160a01b03191690921790915560ce55949350505050565b8060038111156116f7576116f7611dbc565b600083815260cb602052604090205460ff16600381111561171a5761171a611dbc565b03611723575050565b600082815260cb60205260409020805482919060ff1916600183600381111561174e5761174e611dbc565b0217905550817f6c51882bc2ed67617f77a1e9b9a25d2caad8448647ecb093b357a603b2575634826040516117839190611dd2565b60405180910390a2600381600381111561179f5761179f611dbc565b146117a8575050565b6117c46d7369676e616c5f7365727669636560901b60006113bc565b60405163019b28af60e61b81526003841860048201526001600160a01b0391909116906366ca2bc0906024016020604051808303816000875af115801561180f573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061183391906123e4565b505050565b6001600160a01b03821661185f57604051634c67134d60e11b815260040160405180910390fd5b6000826001600160a01b03168260405160006040518083038185875af1925050503d80600081146118ac576040519150601f19603f3d011682016040523d82523d6000602084013e6118b1565b606091505b505090508061183357604051634c67134d60e11b815260040160405180910390fd5b60006118f16d7369676e616c5f7365727669636560901b60006113bc565b6001600160a01b03166392824e9085611915876562726964676560d01b60006112d7565b8887876040518663ffffffff1660e01b8152600401611938959493929190612471565b602060405180830381865afa158015611955573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061197991906123fd565b95945050505050565b61198a611b94565b61199381611c08565b506097805461ffff1916610101179055565b6033546001600160a01b031633146112f65760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610b03565b60006001600160a01b0383163b611a18575060006113cc565b6040516301ffc9a760e01b81526001600160e01b0319831660048201526001600160a01b038416906301ffc9a790602401602060405180830381865afa925050508015611a82575060408051601f3d908101601f19168201909252611a7f918101906123fd565b60015b156113cc579392505050565b60655460405163195ac1a960e21b815260048101859052602481018490526000916001600160a01b03169063656b06a490604401602060405180830381865afa158015611adf573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611b03919061249f565b905081158015611b1a57506001600160a01b038116155b15610bd957604051631467050360e21b81526004810185905260248101849052604401610b03565b603380546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b600054610100900460ff16611bff5760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201526a6e697469616c697a696e6760a81b6064820152608401610b03565b6112f633611b42565b6001600160a01b038116611c2f57604051638ed88b2560e01b815260040160405180910390fd5b606580546001600160a01b0319166001600160a01b0392909216919091179055565b60006101808284031215611c6457600080fd5b50919050565b801515811461159b57600080fd5b60008060408385031215611c8b57600080fd5b823567ffffffffffffffff811115611ca257600080fd5b611cae85828601611c51565b9250506020830135611cbf81611c6a565b809150509250929050565b600080600060408486031215611cdf57600080fd5b833567ffffffffffffffff80821115611cf757600080fd5b611d0387838801611c51565b94506020860135915080821115611d1957600080fd5b818601915086601f830112611d2d57600080fd5b813581811115611d3c57600080fd5b876020828501011115611d4e57600080fd5b6020830194508093505050509250925092565b6001600160a01b038116811461159b57600080fd5b8035611d8181611d61565b919050565b600060208284031215611d9857600080fd5b81356113c981611d61565b600060208284031215611db557600080fd5b5035919050565b634e487b7160e01b600052602160045260246000fd5b6020810160048310611df457634e487b7160e01b600052602160045260246000fd5b91905290565b600060208284031215611e0c57600080fd5b813567ffffffffffffffff811115611e2357600080fd5b611e2f84828501611c51565b949350505050565b6000815180845260005b81811015611e5d57602081850181015186830182015201611e41565b506000602082860101526020601f19601f83011685010191505092915050565b80516001600160801b0316825260006101806020830151611ea960208601826001600160a01b03169052565b5060408301516040850152606083015160608501526080830151611ed860808601826001600160a01b03169052565b5060a0830151611ef360a08601826001600160a01b03169052565b5060c0830151611f0e60c08601826001600160a01b03169052565b5060e083015160e0850152610100808401518186015250610120808401518186015250610140808401518282870152611f4983870182611e37565b925050506101608084015185830382870152611f658382611e37565b9695505050505050565b828152604060208201526000610bd66040830184611e7d565b600080600060608486031215611f9d57600080fd5b83359250602084013591506040840135611fb681611c6a565b809150509250925092565b60008060408385031215611fd457600080fd5b823591506020830135611cbf81611c6a565b80356001600160801b0381168114611d8157600080fd5b6000808335601e1984360301811261201457600080fd5b830160208101925035905067ffffffffffffffff81111561203457600080fd5b80360382131561204357600080fd5b9250929050565b81835281816020850137506000828201602090810191909152601f909101601f19169091010190565b60006101806120928461208585611fe6565b6001600160801b03169052565b61209e60208401611d76565b6001600160a01b03811660208601525060408301356040850152606083013560608501526120ce60808401611d76565b6001600160a01b031660808501526120e860a08401611d76565b6001600160a01b031660a085015261210260c08401611d76565b6001600160a01b031660c085015260e083810135908501526101008084013590850152610120808401359085015261014061213f81850185611ffd565b8383880152612151848801828461204a565b935050505061016061216581850185611ffd565b8684038388015261217784828461204a565b979650505050505050565b6020815260006113c96020830184612073565b634e487b7160e01b600052601160045260246000fd5b808201808211156113cc576113cc612195565b6040815260006121d16040830185612073565b90508260208301529392505050565b634e487b7160e01b600052604160045260246000fd5b604051610180810167ffffffffffffffff8111828210171561221a5761221a6121e0565b60405290565b600082601f83011261223157600080fd5b813567ffffffffffffffff8082111561224c5761224c6121e0565b604051601f8301601f19908116603f01168101908282118183101715612274576122746121e0565b8160405283815286602085880101111561228d57600080fd5b836020870160208301376000602085830101528094505050505092915050565b600061018082360312156122c057600080fd5b6122c86121f6565b6122d183611fe6565b81526122df60208401611d76565b6020820152604083013560408201526060830135606082015261230460808401611d76565b608082015261231560a08401611d76565b60a082015261232660c08401611d76565b60c082015260e08381013590820152610100808401359082015261012080840135908201526101408084013567ffffffffffffffff8082111561236857600080fd5b61237436838801612220565b8385015261016092508286013591508082111561239057600080fd5b5061239d36828701612220565b918301919091525092915050565b60006001600160801b038083168181036123c7576123c7612195565b6001019392505050565b6020815260006113c96020830184611e7d565b6000602082840312156123f657600080fd5b5051919050565b60006020828403121561240f57600080fd5b81516113c981611c6a565b6000808335601e1984360301811261243157600080fd5b83018035915067ffffffffffffffff82111561244c57600080fd5b60200191503681900382131561204357600080fd5b8183823760009101908152919050565b85815260018060a01b038516602082015283604082015260806060820152600061217760808301848661204a565b6000602082840312156124b157600080fd5b81516113c981611d6156fea2646970667358221220bdf6e4c607be4929a07ffb57e3f5adbfaa96fc291580488d4c42c69696cb0c1264736f6c63430008140033", + "balance": "0x0" + }, + "0x1000777700000000000000000000000000000004": { + "contractName": "BridgeProxy", + "storage": { + "0x0000000000000000000000000000000000000000000000000000000000000000": "0x0000000000000000000000000000000000000000000000000000000000000001", + "0x0000000000000000000000000000000000000000000000000000000000000097": "0x0000000000000000000000000000000000000000000000000000000000000101", + "0x0000000000000000000000000000000000000000000000000000000000000033": "0x000000000000000000000000f39fd6e51aad88f6f4ce6ab8827279cfffb92266", + "0x0000000000000000000000000000000000000000000000000000000000000065": "0x0000000000000000000000001000777700000000000000000000000000000006", + "0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103": "0x70997970C51812dc3A010C7d01b50e0d17dc79C8", + "0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc": "0x0000777700000000000000000000000000000004" + }, + "code": "0x60806040526004361061004e5760003560e01c80633659cfe6146100655780634f1ef286146100855780635c60da1b146100985780638f283970146100c9578063f851a440146100e95761005d565b3661005d5761005b6100fe565b005b61005b6100fe565b34801561007157600080fd5b5061005b6100803660046106b3565b610118565b61005b6100933660046106ce565b610155565b3480156100a457600080fd5b506100ad6101bc565b6040516001600160a01b03909116815260200160405180910390f35b3480156100d557600080fd5b5061005b6100e43660046106b3565b6101ed565b3480156100f557600080fd5b506100ad61020d565b61010661022e565b6101166101116102c3565b6102cd565b565b6101206102f1565b6001600160a01b0316330361014d5761014a81604051806020016040528060008152506000610324565b50565b61014a6100fe565b61015d6102f1565b6001600160a01b031633036101b4576101af8383838080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525060019250610324915050565b505050565b6101af6100fe565b60006101c66102f1565b6001600160a01b031633036101e2576101dd6102c3565b905090565b6101ea6100fe565b90565b6101f56102f1565b6001600160a01b0316330361014d5761014a8161034f565b60006102176102f1565b6001600160a01b031633036101e2576101dd6102f1565b6102366102f1565b6001600160a01b031633036101165760405162461bcd60e51b815260206004820152604260248201527f5472616e73706172656e745570677261646561626c6550726f78793a2061646d60448201527f696e2063616e6e6f742066616c6c6261636b20746f2070726f78792074617267606482015261195d60f21b608482015260a4015b60405180910390fd5b60006101dd6103a3565b3660008037600080366000845af43d6000803e8080156102ec573d6000f35b3d6000fd5b60007fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035b546001600160a01b0316919050565b61032d836103cb565b60008251118061033a5750805b156101af57610349838361040b565b50505050565b7f7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f6103786102f1565b604080516001600160a01b03928316815291841660208301520160405180910390a161014a81610437565b60007f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc610315565b6103d4816104e0565b6040516001600160a01b038216907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b90600090a250565b606061043083836040518060600160405280602781526020016107c560279139610574565b9392505050565b6001600160a01b03811661049c5760405162461bcd60e51b815260206004820152602660248201527f455243313936373a206e65772061646d696e20697320746865207a65726f206160448201526564647265737360d01b60648201526084016102ba565b807fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035b80546001600160a01b0319166001600160a01b039290921691909117905550565b6001600160a01b0381163b61054d5760405162461bcd60e51b815260206004820152602d60248201527f455243313936373a206e657720696d706c656d656e746174696f6e206973206e60448201526c1bdd08184818dbdb9d1c9858dd609a1b60648201526084016102ba565b807f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc6104bf565b6060600080856001600160a01b0316856040516105919190610775565b600060405180830381855af49150503d80600081146105cc576040519150601f19603f3d011682016040523d82523d6000602084013e6105d1565b606091505b50915091506105e2868383876105ec565b9695505050505050565b6060831561065b578251600003610654576001600160a01b0385163b6106545760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e747261637400000060448201526064016102ba565b5081610665565b610665838361066d565b949350505050565b81511561067d5781518083602001fd5b8060405162461bcd60e51b81526004016102ba9190610791565b80356001600160a01b03811681146106ae57600080fd5b919050565b6000602082840312156106c557600080fd5b61043082610697565b6000806000604084860312156106e357600080fd5b6106ec84610697565b9250602084013567ffffffffffffffff8082111561070957600080fd5b818601915086601f83011261071d57600080fd5b81358181111561072c57600080fd5b87602082850101111561073e57600080fd5b6020830194508093505050509250925092565b60005b8381101561076c578181015183820152602001610754565b50506000910152565b60008251610787818460208701610751565b9190910192915050565b60208152600082518060208401526107b0816040850160208701610751565b601f01601f1916919091016040019291505056fe416464726573733a206c6f772d6c6576656c2064656c65676174652063616c6c206661696c6564a2646970667358221220e0c34caa93cb549737d2002fe0da3463bee0317add6c2f3da35498d4b65a974464736f6c63430008140033", + "balance": "0x0" + }, + "0x0000777700000000000000000000000000000002": { + "contractName": "ProxiedERC20Vault", + "storage": {}, + "code": "0x608060405260043610620001135760003560e01c8063715018a611620000a1578063a86f9d9e116200006c578063a86f9d9e1462000308578063c287e578146200032d578063cb03d23c1462000361578063e2dc90331462000378578063f2fde38b146200038f57600080fd5b8063715018a614620002805780638456cb5914620002985780638da5cb5b14620002b05780639aa8605c14620002d057600080fd5b80633f4ba83a11620000e25780633f4ba83a14620001db5780635c975abb14620001f357806367090ccf14620002165780636c6563f6146200025b57600080fd5b806301ffc9a7146200011857806319ab453c14620001625780633005fb9814620001895780633ab76e9f14620001a0575b600080fd5b3480156200012557600080fd5b506200014d6200013736600462002097565b6001600160e01b031916630600bf7360e31b1490565b60405190151581526020015b60405180910390f35b3480156200016f57600080fd5b506200018762000181366004620020d9565b620003b4565b005b620001876200019a366004620020f9565b620004d4565b348015620001ad57600080fd5b50606554620001c2906001600160a01b031681565b6040516001600160a01b03909116815260200162000159565b348015620001e857600080fd5b50620001876200074b565b3480156200020057600080fd5b506200014d609754610100900460ff1660021490565b3480156200022357600080fd5b50620001c26200023536600462002146565b60cb6020908152600092835260408084209091529082529020546001600160a01b031681565b3480156200026857600080fd5b50620001c26200027a36600462002188565b620007cd565b3480156200028d57600080fd5b5062000187620007e6565b348015620002a557600080fd5b5062000187620007fe565b348015620002bd57600080fd5b506033546001600160a01b0316620001c2565b348015620002dd57600080fd5b50620002f5620002ef366004620020d9565b6200087c565b6040516200015995949392919062002218565b3480156200031557600080fd5b50620001c2620003273660046200226d565b620009dd565b3480156200033a57600080fd5b506200014d6200034c366004620020d9565b60c96020526000908152604090205460ff1681565b620001876200037236600462002295565b620009f5565b62000187620003893660046200230a565b62000c69565b3480156200039c57600080fd5b5062000187620003ae366004620020d9565b62001056565b600054610100900460ff1615808015620003d55750600054600160ff909116105b80620003f15750303b158015620003f1575060005460ff166001145b6200045a5760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b60648201526084015b60405180910390fd5b6000805460ff1916600117905580156200047e576000805461ff0019166101001790555b6200048982620010d5565b8015620004d0576000805461ff0019169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b5050565b60975460ff1660011901620004fc5760405163dfc60d8560e01b815260040160405180910390fd5b6097805460ff191660021790556200051e609754610100900460ff1660021490565b156200053d5760405163bae6e2a960e01b815260040160405180910390fd5b6562726964676560d01b62000554816001620009dd565b6001600160a01b0316336001600160a01b0316146200058657604051630d85cccf60e11b815260040160405180910390fd5b6000806200059961014086018662002348565b620005a991600490829062002398565b810190620005b8919062002501565b919450909250506001600160a01b0383169050620005e9576040516303f8a7d360e01b815260040160405180910390fd5b8015620006a2576001600160a01b038216600090815260c9602052604090205460ff16156200067a57604051632770a7eb60e21b8152306004820152602481018290526001600160a01b03831690639dc29fac90604401600060405180830381600087803b1580156200065b57600080fd5b505af115801562000670573d6000803e3d6000fd5b50505050620006a2565b620006a26200069060a0870160808801620020d9565b6001600160a01b0384169083620010fc565b620006cd60e0860135620006bd60a0880160808901620020d9565b6001600160a01b03169062001155565b620006df60a0860160808701620020d9565b6001600160a01b0316847f75c5fedbd5fff6123ad9b70827e9742ea1eee996583d6e14249f1429fc4fd99384846040516200072f9291906001600160a01b03929092168252602082015260400190565b60405180910390a350506097805460ff19166001179055505050565b62000760609754610100900460ff1660021490565b6200077e5760405163bae6e2a960e01b815260040160405180910390fd5b62000788620011f4565b6097805461ff0019166101001790556040513381527f5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa906020015b60405180910390a1565b6000620007dc84848462001250565b90505b9392505050565b620007f0620011f4565b620007fc60006200130a565b565b62000813609754610100900460ff1660021490565b15620008325760405163bae6e2a960e01b815260040160405180910390fd5b6200083c620011f4565b6097805461ff0019166102001790556040513381527f62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a25890602001620007c3565b60ca6020526000908152604090208054600182015460028301805492936001600160a01b03831693600160a01b90930460ff1692909190620008be90620025ee565b80601f0160208091040260200160405190810160405280929190818152602001828054620008ec90620025ee565b80156200093d5780601f1062000911576101008083540402835291602001916200093d565b820191906000526020600020905b8154815290600101906020018083116200091f57829003601f168201915b5050505050908060030180546200095490620025ee565b80601f01602080910402602001604051908101604052809291908181526020018280546200098290620025ee565b8015620009d35780601f10620009a757610100808354040283529160200191620009d3565b820191906000526020600020905b815481529060010190602001808311620009b557829003601f168201915b5050505050905085565b6000620009ec46848462001250565b90505b92915050565b60975460ff166001190162000a1d5760405163dfc60d8560e01b815260040160405180910390fd5b6097805460ff1916600217905562000a3f609754610100900460ff1660021490565b1562000a5e5760405163bae6e2a960e01b815260040160405180910390fd5b6562726964676560d01b62000a75816001620009dd565b6001600160a01b0316336001600160a01b03161462000aa757604051630d85cccf60e11b815260040160405180910390fd5b60405163881107d960e01b81526a195c98cc8c17dd985d5b1d60aa1b600482015230602482015260009073502cF119B821a241E25F3acd19548C0Bd825DD759063881107d990604401606060405180830381865af415801562000b0e573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062000b34919062002637565b905060004687350362000b715762000b536040880160208901620020d9565b905062000b6b6001600160a01b0382168686620010fc565b62000be5565b62000b7c876200135c565b6040516340c10f1960e01b81526001600160a01b03878116600483015260248201879052919250908216906340c10f1990604401600060405180830381600087803b15801562000bcb57600080fd5b505af115801562000be0573d6000803e3d6000fd5b505050505b62000bfa6001600160a01b0386163462001155565b815160408084015181519081526001600160a01b0384811660208301529181018790528188169291891691907f883b72735ca0ee2cdd2a462a393658b1a0b36ebd8756e4c22b7509a92ff86a029060600160405180910390a450506097805460ff191660011790555050505050565b60975460ff166001190162000c915760405163dfc60d8560e01b815260040160405180910390fd5b6097805460ff1916600217905562000cb3609754610100900460ff1660021490565b1562000cd25760405163bae6e2a960e01b815260040160405180910390fd5b80356a195c98cc8c17dd985d5b1d60aa1b62000cf56040840160208501620020d9565b62000d076060850160408601620020d9565b6001600160a01b038216158062000d3c575062000d2784846000620007cd565b6001600160a01b0316826001600160a01b0316145b1562000d5b5760405163def9481360e01b815260040160405180910390fd5b6001600160a01b03811662000d83576040516303f8a7d360e01b815260040160405180910390fd5b846060013560000362000da957604051634299323b60e11b815260040160405180910390fd5b604080516101808101825260008082526020820181905291810182905260608082018390526080820183905260a0820183905260c0820183905260e0820183905261010082018390526101208201839052610140820181905261016082015262000e3c3362000e1f60608a0160408b01620020d9565b62000e3160408b0160208c01620020d9565b8a60600135620013bb565b61014083019190915287356060830181905233608084015290925062000e73906a195c98cc8c17dd985d5b1d60aa1b6000620007cd565b6001600160a01b031660a080830191909152608088013561012083015262000e9f90880135346200269e565b60e08083019190915260a088013561010083015262000ec490880160c08901620020d9565b6001600160a01b031660c082015262000ee160e088018862002348565b8080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201829052506101608601949094525082915062000f3590506562726964676560d01b82620009dd565b6001600160a01b0316635fc34de734856040518363ffffffff1660e01b815260040162000f639190620026c0565b60006040518083038185885af115801562000f82573d6000803e3d6000fd5b50505050506040513d6000823e601f3d908101601f1916820160405262000fad919081019062002827565b909250905062000fc460408a0160208b01620020d9565b6001600160a01b031681608001516001600160a01b0316837f91462591aed3d13dcadac8ed73fdc175ec6e79b798ca205822e7ec33dc019e888c600001358d6040016020810190620010179190620020d9565b604080519283526001600160a01b039091166020830152810189905260600160405180910390a450506097805460ff1916600117905550505050505050565b62001060620011f4565b6001600160a01b038116620010c75760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b606482015260840162000451565b620010d2816200130a565b50565b620010df6200196b565b620010ea81620019e3565b506097805461ffff1916610101179055565b604080516001600160a01b038416602482015260448082018490528251808303909101815260649091019091526020810180516001600160e01b031663a9059cbb60e01b1790526200115090849062001a2d565b505050565b6001600160a01b0382166200117d57604051634c67134d60e11b815260040160405180910390fd5b6000826001600160a01b03168260405160006040518083038185875af1925050503d8060008114620011cc576040519150601f19603f3d011682016040523d82523d6000602084013e620011d1565b606091505b50509050806200115057604051634c67134d60e11b815260040160405180910390fd5b6033546001600160a01b03163314620007fc5760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015260640162000451565b60655460405163195ac1a960e21b815260048101859052602481018490526000916001600160a01b03169063656b06a490604401602060405180830381865afa158015620012a2573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620012c8919062002966565b905081158015620012e057506001600160a01b038116155b15620007df57604051631467050360e21b8152600481018590526024810184905260440162000451565b603380546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b8035600090815260cb602090815260408083209183916200138391908601908601620020d9565b6001600160a01b03908116825260208201929092526040016000205416905080620013b657620013b38262001b06565b90505b919050565b60606000620013fe6040518060a001604052806000815260200160006001600160a01b03168152602001600060ff16815260200160608152602001606081525090565b6001600160a01b038616600090815260c9602052604090205460ff161562001632576001600160a01b03868116600090815260ca6020908152604091829020825160a08101845281548152600182015494851692810192909252600160a01b90930460ff16918101919091526002820180549192916060840191906200148490620025ee565b80601f0160208091040260200160405190810160405280929190818152602001828054620014b290620025ee565b8015620015035780601f10620014d75761010080835404028352916020019162001503565b820191906000526020600020905b815481529060010190602001808311620014e557829003601f168201915b505050505081526020016003820180546200151e90620025ee565b80601f01602080910402602001604051908101604052809291908181526020018280546200154c90620025ee565b80156200159d5780601f1062001571576101008083540402835291602001916200159d565b820191906000526020600020905b8154815290600101906020018083116200157f57829003601f168201915b5050509190925250505060208101519091506001600160a01b0316620015c757620015c762002986565b604051632770a7eb60e21b8152336004820152602481018590526001600160a01b03871690639dc29fac90604401600060405180830381600087803b1580156200161057600080fd5b505af115801562001625573d6000803e3d6000fd5b505050508391506200190a565b60008690506040518060a00160405280468152602001886001600160a01b03168152602001826001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa15801562001696573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620016bc91906200299c565b60ff168152602001826001600160a01b03166395d89b416040518163ffffffff1660e01b8152600401600060405180830381865afa15801562001703573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526200172d9190810190620029bc565b8152602001826001600160a01b03166306fdde036040518163ffffffff1660e01b8152600401600060405180830381865afa15801562001771573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526200179b9190810190620029bc565b90526040516370a0823160e01b81523060048201529092506000906001600160a01b038316906370a0823190602401602060405180830381865afa158015620017e8573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200180e9190620029f4565b6040516323b872dd60e01b8152336004820152306024820152604481018890529091506001600160a01b038316906323b872dd906064016020604051808303816000875af115801562001865573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200188b919062002a0e565b506040516370a0823160e01b815230600482015281906001600160a01b038416906370a0823190602401602060405180830381865afa158015620018d3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620018f99190620029f4565b6200190591906200269e565b935050505b6040516332c0f48f60e21b906200192c9083908a908990879060240162002a2e565b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b0319909316929092179091529791965090945050505050565b600054610100900460ff16620019d85760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201526a6e697469616c697a696e6760a81b606482015260840162000451565b620007fc336200130a565b6001600160a01b03811662001a0b57604051638ed88b2560e01b815260040160405180910390fd5b606580546001600160a01b0319166001600160a01b0392909216919091179055565b600062001a84826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b031662001de29092919063ffffffff16565b80519091501562001150578080602001905181019062001aa5919062002a0e565b620011505760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6044820152691bdd081cdd58d8d9595960b21b606482015260840162000451565b60008062001b6360008460405160200162001b22919062002b3c565b604051602081830303815290604052805190602001206040518060200162001b4a9062002089565b601f1982820381018352601f9091011660405262001df3565b905073502cF119B821a241E25F3acd19548C0Bd825DD756378adc0d68262001b936033546001600160a01b031690565b606554636c0db62b60e01b906001600160a01b031662001bba60408a0160208b01620020d9565b893562001bce60608c0160408d0162002bd4565b62001bdd60608d018d62002348565b62001bec60808f018f62002348565b60405160200162001c0598979695949392919062002bf4565b60408051601f198184030181529082905262001c25929160200162002c57565b6040516020818303038152906040526040518463ffffffff1660e01b815260040162001c549392919062002c8a565b602060405180830381865af415801562001c72573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062001c98919062002966565b6001600160a01b038116600090815260c960209081526040808320805460ff1916600117905560ca9091529020909250839062001cd6828262002de0565b50508235600090815260cb6020908152604080832085939092909162001d0291908801908801620020d9565b6001600160a01b03166001600160a01b0316815260200190815260200160002060006101000a8154816001600160a01b0302191690836001600160a01b03160217905550816001600160a01b031683602001602081019062001d659190620020d9565b6001600160a01b031684357fb6b427556e8cb0ebf9175da4bc48c64c4f56e44cfaf8c3ab5ebf8e2ea130907962001da0606088018862002348565b62001daf60808a018a62002348565b62001dc160608c0160408d0162002bd4565b60405162001dd495949392919062002e79565b60405180910390a450919050565b6060620007dc848460008562001efd565b60008347101562001e475760405162461bcd60e51b815260206004820152601d60248201527f437265617465323a20696e73756666696369656e742062616c616e6365000000604482015260640162000451565b815160000362001e9a5760405162461bcd60e51b815260206004820181905260248201527f437265617465323a2062797465636f6465206c656e677468206973207a65726f604482015260640162000451565b8282516020840186f590506001600160a01b038116620007df5760405162461bcd60e51b815260206004820152601960248201527f437265617465323a204661696c6564206f6e206465706c6f7900000000000000604482015260640162000451565b60608247101562001f605760405162461bcd60e51b815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f6044820152651c8818d85b1b60d21b606482015260840162000451565b600080866001600160a01b0316858760405162001f7e919062002eba565b60006040518083038185875af1925050503d806000811462001fbd576040519150601f19603f3d011682016040523d82523d6000602084013e62001fc2565b606091505b509150915062001fd58783838762001fe2565b925050505b949350505050565b60608315620020565782516000036200204e576001600160a01b0385163b6200204e5760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e7472616374000000604482015260640162000451565b508162001fda565b62001fda83838151156200206d5781518083602001fd5b8060405162461bcd60e51b815260040162000451919062002ed8565b6119868062002eee83390190565b600060208284031215620020aa57600080fd5b81356001600160e01b031981168114620007df57600080fd5b6001600160a01b0381168114620010d257600080fd5b600060208284031215620020ec57600080fd5b8135620007df81620020c3565b600080604083850312156200210d57600080fd5b82356001600160401b038111156200212457600080fd5b830161018081860312156200213857600080fd5b946020939093013593505050565b600080604083850312156200215a57600080fd5b8235915060208301356200216e81620020c3565b809150509250929050565b8015158114620010d257600080fd5b6000806000606084860312156200219e57600080fd5b83359250602084013591506040840135620021b98162002179565b809150509250925092565b60005b83811015620021e1578181015183820152602001620021c7565b50506000910152565b6000815180845262002204816020860160208601620021c4565b601f01601f19169290920160200192915050565b8581526001600160a01b038516602082015260ff8416604082015260a0606082018190526000906200224d90830185620021ea565b8281036080840152620022618185620021ea565b98975050505050505050565b600080604083850312156200228157600080fd5b8235915060208301356200216e8162002179565b60008060008060808587031215620022ac57600080fd5b84356001600160401b03811115620022c357600080fd5b850160a08188031215620022d657600080fd5b93506020850135620022e881620020c3565b92506040850135620022fa81620020c3565b9396929550929360600135925050565b6000602082840312156200231d57600080fd5b81356001600160401b038111156200233457600080fd5b82016101008185031215620007df57600080fd5b6000808335601e198436030181126200236057600080fd5b8301803591506001600160401b038211156200237b57600080fd5b6020019150368190038213156200239157600080fd5b9250929050565b60008085851115620023a957600080fd5b83861115620023b757600080fd5b5050820193919092039150565b634e487b7160e01b600052604160045260246000fd5b60405160a081016001600160401b0381118282101715620023ff57620023ff620023c4565b60405290565b60405161018081016001600160401b0381118282101715620023ff57620023ff620023c4565b604051601f8201601f191681016001600160401b0381118282101715620024565762002456620023c4565b604052919050565b60ff81168114620010d257600080fd5b60006001600160401b038211156200248a576200248a620023c4565b50601f01601f191660200190565b600082601f830112620024aa57600080fd5b8135620024c1620024bb826200246e565b6200242b565b818152846020838601011115620024d757600080fd5b816020850160208301376000918101602001919091529392505050565b8035620013b681620020c3565b600080600080608085870312156200251857600080fd5b84356001600160401b03808211156200253057600080fd5b9086019060a082890312156200254557600080fd5b6200254f620023da565b8235815260208301356200256381620020c3565b6020820152604083013562002578816200245e565b60408201526060830135828111156200259057600080fd5b6200259e8a82860162002498565b606083015250608083013582811115620025b757600080fd5b620025c58a82860162002498565b6080830152509550620025de91505060208601620024f4565b9250620022fa60408601620024f4565b600181811c908216806200260357607f821691505b6020821081036200262457634e487b7160e01b600052602260045260246000fd5b50919050565b8051620013b681620020c3565b6000606082840312156200264a57600080fd5b604051606081018181106001600160401b03821117156200266f576200266f620023c4565b6040528251815260208301516200268681620020c3565b60208201526040928301519281019290925250919050565b81810381811115620009ef57634e487b7160e01b600052601160045260246000fd5b60208152620026db6020820183516001600160801b03169052565b60006020830151620026f860408401826001600160a01b03169052565b50604083015160608301526060830151608083015260808301516200272860a08401826001600160a01b03169052565b5060a08301516001600160a01b03811660c08401525060c08301516001600160a01b03811660e08401525060e08301516101008381019190915283015161012080840191909152830151610140808401919091528301516101806101608085018290526200279b6101a0860184620021ea565b90860151858203601f190183870152909250620027b98382620021ea565b9695505050505050565b80516001600160801b0381168114620013b657600080fd5b600082601f830112620027ed57600080fd5b8151620027fe620024bb826200246e565b8181528460208386010111156200281457600080fd5b62001fda826020830160208701620021c4565b600080604083850312156200283b57600080fd5b8251915060208301516001600160401b03808211156200285a57600080fd5b9084019061018082870312156200287057600080fd5b6200287a62002405565b6200288583620027c3565b815262002895602084016200262a565b60208201526040830151604082015260608301516060820152620028bc608084016200262a565b6080820152620028cf60a084016200262a565b60a0820152620028e260c084016200262a565b60c082015260e083810151908201526101008084015190820152610120808401519082015261014080840151838111156200291c57600080fd5b6200292a89828701620027db565b82840152505061016080840151838111156200294557600080fd5b6200295389828701620027db565b8284015250508093505050509250929050565b6000602082840312156200297957600080fd5b8151620007df81620020c3565b634e487b7160e01b600052600160045260246000fd5b600060208284031215620029af57600080fd5b8151620007df816200245e565b600060208284031215620029cf57600080fd5b81516001600160401b03811115620029e657600080fd5b62001fda84828501620027db565b60006020828403121562002a0757600080fd5b5051919050565b60006020828403121562002a2157600080fd5b8151620007df8162002179565b60808152845160808201526000602086015160018060a01b0380821660a085015260ff60408901511660c08501526060880151915060a060e085015262002a7a610120850183620021ea565b91506080880151607f198584030161010086015262002a9a8382620021ea565b9188166020860152506001600160a01b0386166040850152915062002abc9050565b82606083015295945050505050565b6000808335601e1984360301811262002ae357600080fd5b83016020810192503590506001600160401b0381111562002b0357600080fd5b8036038213156200239157600080fd5b81835281816020850137506000828201602090810191909152601f909101601f19169091010190565b60208152813560208201526000602083013562002b5981620020c3565b6001600160a01b031660408381019190915283013562002b79816200245e565b60ff811660608401525062002b92606084018462002acb565b60a0608085015262002ba960c08501828462002b13565b91505062002bbb608085018562002acb565b848303601f190160a0860152620027b983828462002b13565b60006020828403121562002be757600080fd5b8135620007df816200245e565b6001600160a01b038981168252881660208201526040810187905260ff8616606082015260c06080820181905260009062002c33908301868862002b13565b82810360a084015262002c4881858762002b13565b9b9a5050505050505050505050565b6001600160e01b031983168152815160009062002c7c816004850160208701620021c4565b919091016004019392505050565b6001600160a01b0384811682528316602082015260606040820181905260009062002cb890830184620021ea565b95945050505050565b601f8211156200115057600081815260208120601f850160051c8101602086101562002cea5750805b601f850160051c820191505b8181101562002d0b5782815560010162002cf6565b505050505050565b6001600160401b0383111562002d2d5762002d2d620023c4565b62002d458362002d3e8354620025ee565b8362002cc1565b6000601f84116001811462002d7c576000851562002d635750838201355b600019600387901b1c1916600186901b17835562002dd9565b600083815260209020601f19861690835b8281101562002daf578685013582556020948501946001909201910162002d8d565b508682101562002dcd5760001960f88860031b161c19848701351681555b505060018560011b0183555b5050505050565b8135815560018101602083013562002df881620020c3565b8154604085013562002e0a816200245e565b60ff60a01b60a09190911b166001600160a01b03929092166001600160a81b0319919091161717905562002e42606083018362002348565b62002e5281836002860162002d13565b505062002e63608083018362002348565b62002e7381836003860162002d13565b50505050565b60608152600062002e8f60608301878962002b13565b828103602084015262002ea481868862002b13565b91505060ff831660408301529695505050505050565b6000825162002ece818460208701620021c4565b9190910192915050565b602081526000620009ec6020830184620021ea56fe608060405234801561001057600080fd5b5061001961001e565b6100de565b600054610100900460ff161561008a5760405162461bcd60e51b815260206004820152602760248201527f496e697469616c697a61626c653a20636f6e747261637420697320696e697469604482015266616c697a696e6760c81b606482015260840160405180910390fd5b60005460ff90811610156100dc576000805460ff191660ff9081179091556040519081527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b565b611899806100ed6000396000f3fe608060405234801561001057600080fd5b506004361061018e5760003560e01c80636c6563f6116100de57806395d89b4111610097578063a86f9d9e11610071578063a86f9d9e1461036d578063a9059cbb14610380578063dd62ed3e14610393578063f2fde38b146103a657600080fd5b806395d89b411461033f5780639dc29fac14610347578063a457c2d71461035a57600080fd5b80636c6563f6146102cf57806370a08231146102e2578063715018a61461030b5780637cf8ed0d146103135780638456cb59146103265780638da5cb5b1461032e57600080fd5b8063395093511161014b57806340c10f191161012557806340c10f191461028c57806349d126051461029f5780635c975abb146102a85780636c0db62b146102bc57600080fd5b806339509351146102445780633ab76e9f146102575780633f4ba83a1461028257600080fd5b806306fdde0314610193578063095ea7b3146101b157806318160ddd146101d457806323b872dd146101e657806326afaadd146101f9578063313ce5671461022f575b600080fd5b61019b6103b9565b6040516101a89190611366565b60405180910390f35b6101c46101bf3660046113ae565b6103f3565b60405190151581526020016101a8565b60cb545b6040519081526020016101a8565b6101c46101f43660046113da565b61040d565b61021060fb5460fc546001600160a01b0390911691565b604080516001600160a01b0390931683526020830191909152016101a8565b60fd5460405160ff90911681526020016101a8565b6101c46102523660046113ae565b61044d565b60655461026a906001600160a01b031681565b6040516001600160a01b0390911681526020016101a8565b61028a61046f565b005b61028a61029a3660046113ae565b6104ed565b6101d860fc5481565b6101c4609754610100900460ff1660021490565b61028a6102ca3660046114be565b610577565b61026a6102dd36600461157d565b61071d565b6101d86102f03660046115b2565b6001600160a01b0316600090815260c9602052604090205490565b61028a61072a565b60fb5461026a906001600160a01b031681565b61028a61073e565b6033546001600160a01b031661026a565b61019b6107b7565b61028a6103553660046113ae565b610849565b6101c46103683660046113ae565b6108ca565b61026a61037b3660046115cf565b610950565b6101c461038e3660046113ae565b61095d565b6101d86103a13660046115fb565b610992565b61028a6103b43660046115b2565b6109bd565b60606103c3610a36565b6103ce60fc54610a45565b6040516020016103df929190611634565b604051602081830303815290604052905090565b600033610401818585610ad8565b60019150505b92915050565b6000306001600160a01b0384160361043857604051636cfe544760e01b815260040160405180910390fd5b610443848484610bf4565b90505b9392505050565b6000336104018185856104608383610992565b61046a9190611672565b610ad8565b610483609754610100900460ff1660021490565b6104a05760405163bae6e2a960e01b815260040160405180910390fd5b6104a8610c0d565b6097805461ff0019166101001790556040513381527f5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa906020015b60405180910390a1565b6a195c98cc8c17dd985d5b1d60aa1b610507816001610950565b6001600160a01b0316336001600160a01b03161461053857604051630d85cccf60e11b815260040160405180910390fd5b6105428383610c67565b6040518281526001600160a01b03841690600090600080516020611844833981519152906020015b60405180910390a3505050565b600054610100900460ff16158080156105975750600054600160ff909116105b806105b15750303b1580156105b1575060005460ff166001145b6106195760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b60648201526084015b60405180910390fd5b6000805460ff19166001179055801561063c576000805461ff0019166101001790555b6001600160a01b0386161580610650575084155b8061065a57504685145b8061066457508251155b8061066e57508151155b1561068c57604051635d061ab760e11b815260040160405180910390fd5b61069587610d17565b61069f8284610d3a565b60fb80546001600160a01b0319166001600160a01b03881617905560fc85905560fd805460ff191660ff86161790558015610714576000805461ff0019169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b50505050505050565b6000610443848484610d6b565b610732610c0d565b61073c6000610e1f565b565b610752609754610100900460ff1660021490565b156107705760405163bae6e2a960e01b815260040160405180910390fd5b610778610c0d565b6097805461ff0019166102001790556040513381527f62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a258906020016104e3565b606060cd80546107c690611693565b80601f01602080910402602001604051908101604052809291908181526020018280546107f290611693565b801561083f5780601f106108145761010080835404028352916020019161083f565b820191906000526020600020905b81548152906001019060200180831161082257829003601f168201915b5050505050905090565b6a195c98cc8c17dd985d5b1d60aa1b610863816001610950565b6001600160a01b0316336001600160a01b03161461089457604051630d85cccf60e11b815260040160405180910390fd5b61089e8383610e71565b6040518281526000906001600160a01b038516906000805160206118448339815191529060200161056a565b600033816108d88286610992565b9050838110156109385760405162461bcd60e51b815260206004820152602560248201527f45524332303a2064656372656173656420616c6c6f77616e63652062656c6f77604482015264207a65726f60d81b6064820152608401610610565b6109458286868403610ad8565b506001949350505050565b6000610446468484610d6b565b6000306001600160a01b0384160361098857604051636cfe544760e01b815260040160405180910390fd5b6104468383610f90565b6001600160a01b03918216600090815260ca6020908152604080832093909416825291909152205490565b6109c5610c0d565b6001600160a01b038116610a2a5760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b6064820152608401610610565b610a3381610e1f565b50565b606060cc80546107c690611693565b60606000610a5283610f9e565b600101905060008167ffffffffffffffff811115610a7257610a7261141b565b6040519080825280601f01601f191660200182016040528015610a9c576020820181803683370190505b5090508181016020015b600019016f181899199a1a9b1b9c1cb0b131b232b360811b600a86061a8153600a8504945084610aa657509392505050565b6001600160a01b038316610b3a5760405162461bcd60e51b8152602060048201526024808201527f45524332303a20617070726f76652066726f6d20746865207a65726f206164646044820152637265737360e01b6064820152608401610610565b6001600160a01b038216610b9b5760405162461bcd60e51b815260206004820152602260248201527f45524332303a20617070726f766520746f20746865207a65726f206164647265604482015261737360f01b6064820152608401610610565b6001600160a01b03838116600081815260ca602090815260408083209487168084529482529182902085905590518481527f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925910161056a565b600033610c02858285611076565b6109458585856110f0565b6033546001600160a01b0316331461073c5760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610610565b6001600160a01b038216610cbd5760405162461bcd60e51b815260206004820152601f60248201527f45524332303a206d696e7420746f20746865207a65726f2061646472657373006044820152606401610610565b8060cb6000828254610ccf9190611672565b90915550506001600160a01b038216600081815260c96020908152604080832080548601905551848152600080516020611844833981519152910160405180910390a35b5050565b610d1f611289565b610d28816112b9565b506097805461ffff1916610101179055565b600054610100900460ff16610d615760405162461bcd60e51b8152600401610610906116cd565b610d138282611302565b60655460405163195ac1a960e21b815260048101859052602481018490526000916001600160a01b03169063656b06a490604401602060405180830381865afa158015610dbc573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610de09190611718565b905081158015610df757506001600160a01b038116155b1561044657604051631467050360e21b81526004810185905260248101849052604401610610565b603380546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b6001600160a01b038216610ed15760405162461bcd60e51b815260206004820152602160248201527f45524332303a206275726e2066726f6d20746865207a65726f206164647265736044820152607360f81b6064820152608401610610565b6001600160a01b038216600090815260c9602052604090205481811015610f455760405162461bcd60e51b815260206004820152602260248201527f45524332303a206275726e20616d6f756e7420657863656564732062616c616e604482015261636560f01b6064820152608401610610565b6001600160a01b038316600081815260c960209081526040808320868603905560cb8054879003905551858152919291600080516020611844833981519152910161056a565b505050565b6000336104018185856110f0565b60008072184f03e93ff9f4daa797ed6e38ed64bf6a1f0160401b8310610fdd5772184f03e93ff9f4daa797ed6e38ed64bf6a1f0160401b830492506040015b6d04ee2d6d415b85acef81000000008310611009576d04ee2d6d415b85acef8100000000830492506020015b662386f26fc10000831061102757662386f26fc10000830492506010015b6305f5e100831061103f576305f5e100830492506008015b612710831061105357612710830492506004015b60648310611065576064830492506002015b600a83106104075760010192915050565b60006110828484610992565b905060001981146110ea57818110156110dd5760405162461bcd60e51b815260206004820152601d60248201527f45524332303a20696e73756666696369656e7420616c6c6f77616e63650000006044820152606401610610565b6110ea8484848403610ad8565b50505050565b6001600160a01b0383166111545760405162461bcd60e51b815260206004820152602560248201527f45524332303a207472616e736665722066726f6d20746865207a65726f206164604482015264647265737360d81b6064820152608401610610565b6001600160a01b0382166111b65760405162461bcd60e51b815260206004820152602360248201527f45524332303a207472616e7366657220746f20746865207a65726f206164647260448201526265737360e81b6064820152608401610610565b6001600160a01b038316600090815260c960205260409020548181101561122e5760405162461bcd60e51b815260206004820152602660248201527f45524332303a207472616e7366657220616d6f756e7420657863656564732062604482015265616c616e636560d01b6064820152608401610610565b6001600160a01b03808516600081815260c9602052604080822086860390559286168082529083902080548601905591516000805160206118448339815191529061127c9086815260200190565b60405180910390a36110ea565b600054610100900460ff166112b05760405162461bcd60e51b8152600401610610906116cd565b61073c33610e1f565b6001600160a01b0381166112e057604051638ed88b2560e01b815260040160405180910390fd5b606580546001600160a01b0319166001600160a01b0392909216919091179055565b600054610100900460ff166113295760405162461bcd60e51b8152600401610610906116cd565b60cc6113358382611783565b5060cd610f8b8282611783565b60005b8381101561135d578181015183820152602001611345565b50506000910152565b6020815260008251806020840152611385816040850160208701611342565b601f01601f19169190910160400192915050565b6001600160a01b0381168114610a3357600080fd5b600080604083850312156113c157600080fd5b82356113cc81611399565b946020939093013593505050565b6000806000606084860312156113ef57600080fd5b83356113fa81611399565b9250602084013561140a81611399565b929592945050506040919091013590565b634e487b7160e01b600052604160045260246000fd5b600082601f83011261144257600080fd5b813567ffffffffffffffff8082111561145d5761145d61141b565b604051601f8301601f19908116603f011681019082821181831017156114855761148561141b565b8160405283815286602085880101111561149e57600080fd5b836020870160208301376000602085830101528094505050505092915050565b60008060008060008060c087890312156114d757600080fd5b86356114e281611399565b955060208701356114f281611399565b945060408701359350606087013560ff8116811461150f57600080fd5b9250608087013567ffffffffffffffff8082111561152c57600080fd5b6115388a838b01611431565b935060a089013591508082111561154e57600080fd5b5061155b89828a01611431565b9150509295509295509295565b8035801515811461157857600080fd5b919050565b60008060006060848603121561159257600080fd5b83359250602084013591506115a960408501611568565b90509250925092565b6000602082840312156115c457600080fd5b813561044681611399565b600080604083850312156115e257600080fd5b823591506115f260208401611568565b90509250929050565b6000806040838503121561160e57600080fd5b823561161981611399565b9150602083013561162981611399565b809150509250929050565b60008351611646818460208801611342565b6241c55b60e71b9083019081528351611666816004840160208801611342565b01600401949350505050565b8082018082111561040757634e487b7160e01b600052601160045260246000fd5b600181811c908216806116a757607f821691505b6020821081036116c757634e487b7160e01b600052602260045260246000fd5b50919050565b6020808252602b908201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960408201526a6e697469616c697a696e6760a81b606082015260800190565b60006020828403121561172a57600080fd5b815161044681611399565b601f821115610f8b57600081815260208120601f850160051c8101602086101561175c5750805b601f850160051c820191505b8181101561177b57828155600101611768565b505050505050565b815167ffffffffffffffff81111561179d5761179d61141b565b6117b1816117ab8454611693565b84611735565b602080601f8311600181146117e657600084156117ce5750858301515b600019600386901b1c1916600185901b17855561177b565b600085815260208120601f198616915b82811015611815578886015182559484019460019091019084016117f6565b50858210156118335787850151600019600388901b60f8161c191681555b5050505050600190811b0190555056feddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3efa2646970667358221220263570e5f6aad00cd73465157d1d2038ba0e55d481f9deb501998a5fc32f606364736f6c63430008140033a26469706673582212205e38ece0613387aa26f71c81ece84abd3f41ae813a8d5fffb5ffa1bc7caf343364736f6c63430008140033", + "balance": "0x0" + }, + "0x1000777700000000000000000000000000000002": { + "contractName": "ERC20VaultProxy", + "storage": { + "0x0000000000000000000000000000000000000000000000000000000000000000": "0x0000000000000000000000000000000000000000000000000000000000000001", + "0x0000000000000000000000000000000000000000000000000000000000000097": "0x0000000000000000000000000000000000000000000000000000000000000101", + "0x0000000000000000000000000000000000000000000000000000000000000033": "0x000000000000000000000000f39fd6e51aad88f6f4ce6ab8827279cfffb92266", + "0x0000000000000000000000000000000000000000000000000000000000000065": "0x0000000000000000000000001000777700000000000000000000000000000006", + "0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103": "0x70997970C51812dc3A010C7d01b50e0d17dc79C8", + "0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc": "0x0000777700000000000000000000000000000002" + }, + "code": "0x60806040526004361061004e5760003560e01c80633659cfe6146100655780634f1ef286146100855780635c60da1b146100985780638f283970146100c9578063f851a440146100e95761005d565b3661005d5761005b6100fe565b005b61005b6100fe565b34801561007157600080fd5b5061005b6100803660046106b3565b610118565b61005b6100933660046106ce565b610155565b3480156100a457600080fd5b506100ad6101bc565b6040516001600160a01b03909116815260200160405180910390f35b3480156100d557600080fd5b5061005b6100e43660046106b3565b6101ed565b3480156100f557600080fd5b506100ad61020d565b61010661022e565b6101166101116102c3565b6102cd565b565b6101206102f1565b6001600160a01b0316330361014d5761014a81604051806020016040528060008152506000610324565b50565b61014a6100fe565b61015d6102f1565b6001600160a01b031633036101b4576101af8383838080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525060019250610324915050565b505050565b6101af6100fe565b60006101c66102f1565b6001600160a01b031633036101e2576101dd6102c3565b905090565b6101ea6100fe565b90565b6101f56102f1565b6001600160a01b0316330361014d5761014a8161034f565b60006102176102f1565b6001600160a01b031633036101e2576101dd6102f1565b6102366102f1565b6001600160a01b031633036101165760405162461bcd60e51b815260206004820152604260248201527f5472616e73706172656e745570677261646561626c6550726f78793a2061646d60448201527f696e2063616e6e6f742066616c6c6261636b20746f2070726f78792074617267606482015261195d60f21b608482015260a4015b60405180910390fd5b60006101dd6103a3565b3660008037600080366000845af43d6000803e8080156102ec573d6000f35b3d6000fd5b60007fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035b546001600160a01b0316919050565b61032d836103cb565b60008251118061033a5750805b156101af57610349838361040b565b50505050565b7f7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f6103786102f1565b604080516001600160a01b03928316815291841660208301520160405180910390a161014a81610437565b60007f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc610315565b6103d4816104e0565b6040516001600160a01b038216907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b90600090a250565b606061043083836040518060600160405280602781526020016107c560279139610574565b9392505050565b6001600160a01b03811661049c5760405162461bcd60e51b815260206004820152602660248201527f455243313936373a206e65772061646d696e20697320746865207a65726f206160448201526564647265737360d01b60648201526084016102ba565b807fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035b80546001600160a01b0319166001600160a01b039290921691909117905550565b6001600160a01b0381163b61054d5760405162461bcd60e51b815260206004820152602d60248201527f455243313936373a206e657720696d706c656d656e746174696f6e206973206e60448201526c1bdd08184818dbdb9d1c9858dd609a1b60648201526084016102ba565b807f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc6104bf565b6060600080856001600160a01b0316856040516105919190610775565b600060405180830381855af49150503d80600081146105cc576040519150601f19603f3d011682016040523d82523d6000602084013e6105d1565b606091505b50915091506105e2868383876105ec565b9695505050505050565b6060831561065b578251600003610654576001600160a01b0385163b6106545760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e747261637400000060448201526064016102ba565b5081610665565b610665838361066d565b949350505050565b81511561067d5781518083602001fd5b8060405162461bcd60e51b81526004016102ba9190610791565b80356001600160a01b03811681146106ae57600080fd5b919050565b6000602082840312156106c557600080fd5b61043082610697565b6000806000604084860312156106e357600080fd5b6106ec84610697565b9250602084013567ffffffffffffffff8082111561070957600080fd5b818601915086601f83011261071d57600080fd5b81358181111561072c57600080fd5b87602082850101111561073e57600080fd5b6020830194508093505050509250925092565b60005b8381101561076c578181015183820152602001610754565b50506000910152565b60008251610787818460208701610751565b9190910192915050565b60208152600082518060208401526107b0816040850160208701610751565b601f01601f1916919091016040019291505056fe416464726573733a206c6f772d6c6576656c2064656c65676174652063616c6c206661696c6564a2646970667358221220e0c34caa93cb549737d2002fe0da3463bee0317add6c2f3da35498d4b65a974464736f6c63430008140033", + "balance": "0x0" + }, + "0x0000777700000000000000000000000000000008": { + "contractName": "ProxiedERC721Vault", + "storage": {}, + "code": "0x608060405260043610620001375760003560e01c80636c6563f611620000ad5780639aa8605c116200006c5780639aa8605c146200038f578063a86f9d9e14620003c6578063a9976baf14620003eb578063c287e5781462000402578063f2fde38b146200043657600080fd5b80636c6563f61462000303578063715018a614620003285780637333964314620003405780638456cb5914620003575780638da5cb5b146200036f57600080fd5b80633ab76e9f11620000fa5780633ab76e9f146200022b5780633f4ba83a146200026657806359f4a907146200027e5780635c975abb146200029b57806367090ccf14620002be57600080fd5b806301ffc9a7146200013c578063150b7a02146200018657806319ab453c14620001d05780632ca069a514620001f75780633005fb981462000214575b600080fd5b3480156200014957600080fd5b50620001716200015b366004620021db565b6001600160e01b031916630600bf7360e31b1490565b60405190151581526020015b60405180910390f35b3480156200019357600080fd5b50620001b6620001a53660046200221d565b630a85bd0160e11b95945050505050565b6040516001600160e01b031990911681526020016200017d565b348015620001dd57600080fd5b50620001f5620001ef366004620022c4565b6200045b565b005b3480156200020457600080fd5b50620001b6636cdb3d1360e11b81565b620001f562000225366004620022e4565b6200057b565b3480156200023857600080fd5b506065546200024d906001600160a01b031681565b6040516001600160a01b0390911681526020016200017d565b3480156200027357600080fd5b50620001f56200098e565b3480156200028b57600080fd5b50620001b66380ac58cd60e01b81565b348015620002a857600080fd5b5062000171609754610100900460ff1660021490565b348015620002cb57600080fd5b506200024d620002dd36600462002331565b60cb6020908152600092835260408084209091529082529020546001600160a01b031681565b3480156200031057600080fd5b506200024d6200032236600462002373565b62000a10565b3480156200033557600080fd5b50620001f562000a29565b620001f562000351366004620023af565b62000a41565b3480156200036457600080fd5b50620001f562000f5b565b3480156200037c57600080fd5b506033546001600160a01b03166200024d565b3480156200039c57600080fd5b50620003b4620003ae366004620022c4565b62000fd9565b6040516200017d949392919062002441565b348015620003d357600080fd5b506200024d620003e53660046200248c565b6200112c565b620001f5620003fc366004620025a6565b62001144565b3480156200040f57600080fd5b506200017162000421366004620022c4565b60c96020526000908152604090205460ff1681565b3480156200044357600080fd5b50620001f562000455366004620022c4565b620014a9565b600054610100900460ff16158080156200047c5750600054600160ff909116105b80620004985750303b15801562000498575060005460ff166001145b620005015760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b60648201526084015b60405180910390fd5b6000805460ff19166001179055801562000525576000805461ff0019166101001790555b620005308262001528565b801562000577576000805461ff0019169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b5050565b60975460ff1660011901620005a35760405163dfc60d8560e01b815260040160405180910390fd5b6097805460ff19166002179055620005c5609754610100900460ff1660021490565b15620005e45760405163bae6e2a960e01b815260040160405180910390fd5b6562726964676560d01b620005fb8160016200112c565b6001600160a01b0316336001600160a01b0316146200062d57604051630d85cccf60e11b815260040160405180910390fd5b60006200064160a0850160808601620022c4565b6001600160a01b031603620006695760405163016a294f60e41b815260040160405180910390fd5b468360400135146200068e57604051630a15fbb960e01b815260040160405180910390fd5b600080620006a161014086018662002644565b620006b191600490829062002694565b810190620006c09190620027fb565b6020840151939550935050506001600160a01b0316620006f3576040516303f8a7d360e01b815260040160405180910390fd5b6020808301516001600160a01b0316600090815260c9909152604090205460ff1615620007e25760005b8151811015620007db5760208301516001600160a01b03166340c10f196200074c60a0890160808a01620022c4565b8484815181106200076157620007616200284c565b60200260200101516040518363ffffffff1660e01b81526004016200079b9291906001600160a01b03929092168252602082015260400190565b600060405180830381600087803b158015620007b657600080fd5b505af1158015620007cb573d6000803e3d6000fd5b505050508060010190506200071d565b50620008ac565b60005b8151811015620008aa5760208301516001600160a01b03166342842e0e306200081560a08a0160808b01620022c4565b8585815181106200082a576200082a6200284c565b60209081029190910101516040516001600160e01b031960e086901b1681526001600160a01b0393841660048201529290911660248301526044820152606401600060405180830381600087803b1580156200088557600080fd5b505af11580156200089a573d6000803e3d6000fd5b50505050806001019050620007e5565b505b620008d760e0860135620008c760a0880160808901620022c4565b6001600160a01b0316906200154f565b620008e960a0860160808701620022c4565b6001600160a01b0316847fe8449897bd3c926a272780c39ba13e77bf7a2c823479a75bfbc13ef631183dfd84602001518460006001600160401b03811115620009365762000936620024b4565b60405190808252806020026020018201604052801562000960578160200160208202803683370190505b5060405162000972939291906200289f565b60405180910390a350506097805460ff19166001179055505050565b620009a3609754610100900460ff1660021490565b620009c15760405163bae6e2a960e01b815260040160405180910390fd5b620009cb620015f3565b6097805461ff0019166101001790556040513381527f5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa906020015b60405180910390a1565b600062000a1f8484846200164f565b90505b9392505050565b62000a33620015f3565b62000a3f600062001709565b565b60975460ff166001190162000a695760405163dfc60d8560e01b815260040160405180910390fd5b6097805460ff1916600217905562000a8b609754610100900460ff1660021490565b1562000aaa5760405163bae6e2a960e01b815260040160405180910390fd5b73502cF119B821a241E25F3acd19548C0Bd825DD7563c0619cc262000ad36080840184620028e3565b62000ae26060860186620028e3565b60016040518663ffffffff1660e01b815260040162000b0695949392919062002962565b60006040518083038186803b15801562000b1f57600080fd5b505af415801562000b34573d6000803e3d6000fd5b5050505073502cF119B821a241E25F3acd19548C0Bd825DD756393522e3e62000b7383600001356b195c98cdcc8c57dd985d5b1d60a21b600062000a10565b62000b856040850160208601620022c4565b62000b976060860160408701620022c4565b60405160e085901b6001600160e01b03191681526001600160a01b0393841660048201529183166024830152909116604482015260640160006040518083038186803b15801562000be757600080fd5b505af415801562000bfc573d6000803e3d6000fd5b5062000c3192506380ac58cd60e01b915062000c2190506060840160408501620022c4565b6001600160a01b0316906200175b565b62000c4f57604051633ee915f560e11b815260040160405180910390fd5b600062000c606080830183620028e3565b80806020026020016040519081016040528093929190818152602001838360200280828437600092018290525093945062000ca6925050506060840160408501620022c4565b9050600062000cb96060850185620028e3565b80806020026020016040519081016040528093929190818152602001838360200280828437600092018290525060408051610180810182528281526020810183905290810182905260608082018390526080820183905260a0820183905260c0820183905260e082018390526101008201839052610120820192909252610140810182905261016081019190915293945062000d5492505050565b8435606082015262000d673386620017f0565b610140820152336080820152606081015162000d95906b195c98cdcc8c57dd985d5b1d60a21b600062000a10565b6001600160a01b031660a08083019190915285013561012082015262000dc060c086013534620029a2565b60e08083019190915260c08601356101008084019190915262000de991908701908701620022c4565b6001600160a01b031660c082015262000e0761010086018662002644565b8080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201829052506101608601949094525082915062000e5b90506562726964676560d01b826200112c565b6001600160a01b0316635fc34de734856040518363ffffffff1660e01b815260040162000e899190620029c4565b60006040518083038185885af115801562000ea8573d6000803e3d6000fd5b50505050506040513d6000823e601f3d908101601f1916820160405262000ed3919081019062002b36565b909250905062000eea6040880160208901620022c4565b6001600160a01b031681608001516001600160a01b0316837f5e54276405062454e6226625b28a6fea0a838d6b054e38955667234afb3345a3846060015189898c60405162000f3d949392919062002c75565b60405180910390a450506097805460ff191660011790555050505050565b62000f70609754610100900460ff1660021490565b1562000f8f5760405163bae6e2a960e01b815260040160405180910390fd5b62000f99620015f3565b6097805461ff0019166102001790556040513381527f62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a2589060200162000a06565b60ca6020526000908152604090208054600182015460028301805492936001600160a01b03909216926200100d9062002cb5565b80601f01602080910402602001604051908101604052809291908181526020018280546200103b9062002cb5565b80156200108c5780601f1062001060576101008083540402835291602001916200108c565b820191906000526020600020905b8154815290600101906020018083116200106e57829003601f168201915b505050505090806003018054620010a39062002cb5565b80601f0160208091040260200160405190810160405280929190818152602001828054620010d19062002cb5565b8015620011225780601f10620010f65761010080835404028352916020019162001122565b820191906000526020600020905b8154815290600101906020018083116200110457829003601f168201915b5050505050905084565b60006200113b4684846200164f565b90505b92915050565b60975460ff16600119016200116c5760405163dfc60d8560e01b815260040160405180910390fd5b6097805460ff191660021790556200118e609754610100900460ff1660021490565b15620011ad5760405163bae6e2a960e01b815260040160405180910390fd5b6562726964676560d01b620011c48160016200112c565b6001600160a01b0316336001600160a01b031614620011f657604051630d85cccf60e11b815260040160405180910390fd5b60405163881107d960e01b81526b195c98cdcc8c57dd985d5b1d60a21b600482015230602482015260009073502cF119B821a241E25F3acd19548C0Bd825DD759063881107d990604401606060405180830381865af41580156200125e573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062001284919062002cf1565b90506000468735036200135f57620012a36040880160208901620022c4565b905060005b84518110156200135857816001600160a01b03166323b872dd3088888581518110620012d857620012d86200284c565b60209081029190910101516040516001600160e01b031960e086901b1681526001600160a01b0393841660048201529290911660248301526044820152606401600060405180830381600087803b1580156200133357600080fd5b505af115801562001348573d6000803e3d6000fd5b50505050806001019050620012a8565b506200141a565b6200136a8762001d1f565b905060005b84518110156200141857816001600160a01b03166340c10f19878784815181106200139e576200139e6200284c565b60200260200101516040518363ffffffff1660e01b8152600401620013d89291906001600160a01b03929092168252602082015260400190565b600060405180830381600087803b158015620013f357600080fd5b505af115801562001408573d6000803e3d6000fd5b505050508060010190506200136f565b505b6200142f6001600160a01b038616346200154f565b815160408301516001600160a01b0380881692908916917f0f60c37489e435ed8490c30b01c1fa57e62510e88b351b75796ad3d95babe6b1908589600060405190808252806020026020018201604052801562001496578160200160208202803683370190505b5060405162000f3d949392919062002c75565b620014b3620015f3565b6001600160a01b0381166200151a5760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b6064820152608401620004f8565b620015258162001709565b50565b6200153262001d88565b6200153d8162001e00565b506097805461ffff1916610101179055565b6001600160a01b0382166200157757604051634c67134d60e11b815260040160405180910390fd5b6000826001600160a01b03168260405160006040518083038185875af1925050503d8060008114620015c6576040519150601f19603f3d011682016040523d82523d6000602084013e620015cb565b606091505b5050905080620015ee57604051634c67134d60e11b815260040160405180910390fd5b505050565b6033546001600160a01b0316331462000a3f5760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401620004f8565b60655460405163195ac1a960e21b815260048101859052602481018490526000916001600160a01b03169063656b06a490604401602060405180830381865afa158015620016a1573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620016c7919062002d58565b905081158015620016df57506001600160a01b038116155b1562000a2257604051631467050360e21b81526004810185905260248101849052604401620004f8565b603380546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b60006001600160a01b0383163b62001776575060006200113e565b6040516301ffc9a760e01b81526001600160e01b0319831660048201526001600160a01b038416906301ffc9a790602401602060405180830381865afa925050508015620017e3575060408051601f3d908101601f19168201909252620017e09181019062002d78565b60015b156200113e579392505050565b6040805160808101825260008082526020820152606091810182905280820182905260c96000620018286060860160408701620022c4565b6001600160a01b0316815260208101919091526040016000205460ff161562001ab05760ca6000620018616060860160408701620022c4565b6001600160a01b0390811682526020808301939093526040918201600020825160808101845281548152600182015490921693820193909352600283018054919392840191620018b19062002cb5565b80601f0160208091040260200160405190810160405280929190818152602001828054620018df9062002cb5565b8015620019305780601f10620019045761010080835404028352916020019162001930565b820191906000526020600020905b8154815290600101906020018083116200191257829003601f168201915b505050505081526020016003820180546200194b9062002cb5565b80601f0160208091040260200160405190810160405280929190818152602001828054620019799062002cb5565b8015620019ca5780601f106200199e57610100808354040283529160200191620019ca565b820191906000526020600020905b815481529060010190602001808311620019ac57829003601f168201915b505050505081525050905060005b620019e76060850185620028e3565b905081101562001aa95762001a036060850160408601620022c4565b6001600160a01b0316639dc29fac8662001a216060880188620028e3565b8581811062001a345762001a346200284c565b6040516001600160e01b031960e087901b1681526001600160a01b0390941660048501526020029190910135602483015250604401600060405180830381600087803b15801562001a8457600080fd5b505af115801562001a99573d6000803e3d6000fd5b50505050806001019050620019d8565b5062001ca4565b600062001ac46060850160408601620022c4565b9050604051806080016040528046815260200185604001602081019062001aec9190620022c4565b6001600160a01b03168152602001826001600160a01b03166395d89b416040518163ffffffff1660e01b8152600401600060405180830381865afa15801562001b39573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405262001b63919081019062002d98565b8152602001826001600160a01b03166306fdde036040518163ffffffff1660e01b8152600401600060405180830381865afa15801562001ba7573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405262001bd1919081019062002d98565b9052915060005b62001be76060860186620028e3565b905081101562001ca1576001600160a01b0382166323b872dd873062001c1160608a018a620028e3565b8681811062001c245762001c246200284c565b6040516001600160e01b031960e088901b1681526001600160a01b03958616600482015294909316602485015250602090910201356044820152606401600060405180830381600087803b15801562001c7c57600080fd5b505af115801562001c91573d6000803e3d6000fd5b5050505080600101905062001bd8565b50505b63a9976baf60e01b818562001cc06040870160208801620022c4565b62001ccf6060880188620028e3565b60405160240162001ce595949392919062002e27565b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b031990931692909217909152949350505050565b8035600090815260cb6020908152604080832091839162001d4691908601908601620022c4565b6001600160a01b0390811682526020820192909252604001600020541690508062001d835762001d8062001d7a8362002e74565b62001e4a565b90505b919050565b600054610100900460ff1662001df55760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201526a6e697469616c697a696e6760a81b6064820152608401620004f8565b62000a3f3362001709565b6001600160a01b03811662001e2857604051638ed88b2560e01b815260040160405180910390fd5b606580546001600160a01b0319166001600160a01b0392909216919091179055565b60008062001ea760008460405160200162001e66919062002e82565b604051602081830303815290604052805190602001206040518060200162001e8e90620021cd565b601f1982820381018352601f90910116604052620020c3565b905073502cF119B821a241E25F3acd19548C0Bd825DD756378adc0d68262001ed76033546001600160a01b031690565b60655460208089015189516040808c015160608d0151915163689ccd8d60e11b9662001f13966001600160a01b03909116959493910162002e97565b60408051601f198184030181529082905262001f33929160200162002ee0565b6040516020818303038152906040526040518463ffffffff1660e01b815260040162001f629392919062002f13565b602060405180830381865af415801562001f80573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062001fa6919062002d58565b6001600160a01b03818116600090815260c9602090815260408083208054600160ff19909116811790915560ca835292819020885181559188015192820180546001600160a01b03191693909416929092179092558501519193508491600282019062002014908262002f93565b50606082015160038201906200202b908262002f93565b50508351600090815260cb6020908152604080832082880180516001600160a01b039081168652919093529281902080546001600160a01b031916878516908117909155915187518289015160608a015193519496509190941693927f2da3c4d305298f6df3653c23d98b4c055f72f7e6f981b2c477ccbec92b1ee57992620020b592916200305f565b60405180910390a450919050565b600083471015620021175760405162461bcd60e51b815260206004820152601d60248201527f437265617465323a20696e73756666696369656e742062616c616e63650000006044820152606401620004f8565b81516000036200216a5760405162461bcd60e51b815260206004820181905260248201527f437265617465323a2062797465636f6465206c656e677468206973207a65726f6044820152606401620004f8565b8282516020840186f590506001600160a01b03811662000a225760405162461bcd60e51b815260206004820152601960248201527f437265617465323a204661696c6564206f6e206465706c6f79000000000000006044820152606401620004f8565b611f9b806200308983390190565b600060208284031215620021ee57600080fd5b81356001600160e01b0319811681146200113b57600080fd5b6001600160a01b03811681146200152557600080fd5b6000806000806000608086880312156200223657600080fd5b8535620022438162002207565b94506020860135620022558162002207565b93506040860135925060608601356001600160401b03808211156200227957600080fd5b818801915088601f8301126200228e57600080fd5b8135818111156200229e57600080fd5b896020828501011115620022b157600080fd5b9699959850939650602001949392505050565b600060208284031215620022d757600080fd5b81356200113b8162002207565b60008060408385031215620022f857600080fd5b82356001600160401b038111156200230f57600080fd5b830161018081860312156200232357600080fd5b946020939093013593505050565b600080604083850312156200234557600080fd5b823591506020830135620023598162002207565b809150509250929050565b80151581146200152557600080fd5b6000806000606084860312156200238957600080fd5b83359250602084013591506040840135620023a48162002364565b809150509250925092565b600060208284031215620023c257600080fd5b81356001600160401b03811115620023d957600080fd5b820161012081850312156200113b57600080fd5b60005b838110156200240a578181015183820152602001620023f0565b50506000910152565b600081518084526200242d816020860160208601620023ed565b601f01601f19169290920160200192915050565b8481526001600160a01b03841660208201526080604082018190526000906200246d9083018562002413565b828103606084015262002481818562002413565b979650505050505050565b60008060408385031215620024a057600080fd5b823591506020830135620023598162002364565b634e487b7160e01b600052604160045260246000fd5b60405161018081016001600160401b0381118282101715620024f057620024f0620024b4565b60405290565b604051601f8201601f191681016001600160401b0381118282101715620025215762002521620024b4565b604052919050565b600082601f8301126200253b57600080fd5b813560206001600160401b03821115620025595762002559620024b4565b8160051b6200256a828201620024f6565b92835284810182019282810190878511156200258557600080fd5b83870192505b8483101562002481578235825291830191908301906200258b565b60008060008060808587031215620025bd57600080fd5b84356001600160401b0380821115620025d557600080fd5b9086019060808289031215620025ea57600080fd5b909450602086013590620025fe8262002207565b909350604086013590620026128262002207565b909250606086013590808211156200262957600080fd5b50620026388782880162002529565b91505092959194509250565b6000808335601e198436030181126200265c57600080fd5b8301803591506001600160401b038211156200267757600080fd5b6020019150368190038213156200268d57600080fd5b9250929050565b60008085851115620026a557600080fd5b83861115620026b357600080fd5b5050820193919092039150565b60006001600160401b03821115620026dc57620026dc620024b4565b50601f01601f191660200190565b600082601f830112620026fc57600080fd5b8135620027136200270d82620026c0565b620024f6565b8181528460208386010111156200272957600080fd5b816020850160208301376000918101602001919091529392505050565b6000608082840312156200275957600080fd5b604051608081016001600160401b0382821081831117156200277f576200277f620024b4565b8160405282935084358352602085013591506200279c8262002207565b8160208401526040850135915080821115620027b757600080fd5b620027c586838701620026ea565b60408401526060850135915080821115620027df57600080fd5b50620027ee85828601620026ea565b6060830152505092915050565b600080600080608085870312156200281257600080fd5b84356001600160401b03808211156200282a57600080fd5b620028388883890162002746565b955060208701359150620025fe8262002207565b634e487b7160e01b600052603260045260246000fd5b600081518084526020808501945080840160005b83811015620028945781518752958201959082019060010162002876565b509495945050505050565b6001600160a01b0384168152606060208201819052600090620028c59083018562002862565b8281036040840152620028d9818562002862565b9695505050505050565b6000808335601e19843603018112620028fb57600080fd5b8301803591506001600160401b038211156200291657600080fd5b6020019150600581901b36038213156200268d57600080fd5b81835260006001600160fb1b038311156200294957600080fd5b8260051b80836020870137939093016020019392505050565b606081526000620029786060830187896200292f565b82810360208401526200298d8186886200292f565b91505082151560408301529695505050505050565b818103818111156200113e57634e487b7160e01b600052601160045260246000fd5b60208152620029df6020820183516001600160801b03169052565b60006020830151620029fc60408401826001600160a01b03169052565b506040830151606083015260608301516080830152608083015162002a2c60a08401826001600160a01b03169052565b5060a08301516001600160a01b03811660c08401525060c08301516001600160a01b03811660e08401525060e083015161010083810191909152830151610120808401919091528301516101408084019190915283015161018061016080850182905262002a9f6101a086018462002413565b90860151858203601f190183870152909250620028d9838262002413565b80516001600160801b038116811462001d8357600080fd5b805162001d838162002207565b600082601f83011262002af457600080fd5b815162002b056200270d82620026c0565b81815284602083860101111562002b1b57600080fd5b62002b2e826020830160208701620023ed565b949350505050565b6000806040838503121562002b4a57600080fd5b8251915060208301516001600160401b038082111562002b6957600080fd5b90840190610180828703121562002b7f57600080fd5b62002b89620024ca565b62002b948362002abd565b815262002ba46020840162002ad5565b6020820152604083015160408201526060830151606082015262002bcb6080840162002ad5565b608082015262002bde60a0840162002ad5565b60a082015262002bf160c0840162002ad5565b60c082015260e0838101519082015261010080840151908201526101208084015190820152610140808401518381111562002c2b57600080fd5b62002c398982870162002ae2565b828401525050610160808401518381111562002c5457600080fd5b62002c628982870162002ae2565b8284015250508093505050509250929050565b8481526001600160a01b038416602082015260806040820181905260009062002ca19083018562002862565b828103606084015262002481818562002862565b600181811c9082168062002cca57607f821691505b60208210810362002ceb57634e487b7160e01b600052602260045260246000fd5b50919050565b60006060828403121562002d0457600080fd5b604051606081018181106001600160401b038211171562002d295762002d29620024b4565b60405282518152602083015162002d408162002207565b60208201526040928301519281019290925250919050565b60006020828403121562002d6b57600080fd5b81516200113b8162002207565b60006020828403121562002d8b57600080fd5b81516200113b8162002364565b60006020828403121562002dab57600080fd5b81516001600160401b0381111562002dc257600080fd5b62002b2e8482850162002ae2565b8051825260018060a01b036020820151166020830152600060408201516080604085015262002e03608085018262002413565b90506060830151848203606086015262002e1e828262002413565b95945050505050565b60808152600062002e3c608083018862002dd0565b6001600160a01b03878116602085015286166040840152828103606084015262002e688185876200292f565b98975050505050505050565b600062001d80368362002746565b6020815260006200113b602083018462002dd0565b6001600160a01b038681168252851660208201526040810184905260a06060820181905260009062002ecc9083018562002413565b828103608084015262002e68818562002413565b6001600160e01b031983168152815160009062002f05816004850160208701620023ed565b919091016004019392505050565b6001600160a01b0384811682528316602082015260606040820181905260009062002e1e9083018462002413565b601f821115620015ee57600081815260208120601f850160051c8101602086101562002f6a5750805b601f850160051c820191505b8181101562002f8b5782815560010162002f76565b505050505050565b81516001600160401b0381111562002faf5762002faf620024b4565b62002fc78162002fc0845462002cb5565b8462002f41565b602080601f83116001811462002fff576000841562002fe65750858301515b600019600386901b1c1916600185901b17855562002f8b565b600085815260208120601f198616915b8281101562003030578886015182559484019460019091019084016200300f565b50858210156200304f5787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b60408152600062003074604083018562002413565b828103602084015262002e1e81856200241356fe608060405234801561001057600080fd5b5061001961001e565b6100de565b600054610100900460ff161561008a5760405162461bcd60e51b815260206004820152602760248201527f496e697469616c697a61626c653a20636f6e747261637420697320696e697469604482015266616c697a696e6760c81b606482015260840160405180910390fd5b60005460ff90811610156100dc576000805460ff191660ff9081179091556040519081527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b565b611eae806100ed6000396000f3fe608060405234801561001057600080fd5b50600436106101c45760003560e01c806370a08231116100f9578063a22cb46511610097578063c87b56dd11610071578063c87b56dd146103c0578063d1399b1a146103e1578063e985e9c5146103f4578063f2fde38b1461043157600080fd5b8063a22cb46514610387578063a86f9d9e1461039a578063b88d4fde146103ad57600080fd5b80638456cb59116100d35780638456cb59146103535780638da5cb5b1461035b57806395d89b411461036c5780639dc29fac1461037457600080fd5b806370a0823114610324578063715018a6146103375780637cf8ed0d1461033f57600080fd5b806340c10f19116101665780635c975abb116101405780635c975abb146102b25780636352211e146102c657806367e828bf146102d95780636c6563f61461031157600080fd5b806340c10f191461027457806342842e0e1461028757806349d126051461029a57600080fd5b8063095ea7b3116101a2578063095ea7b31461023157806323b872dd146102465780633ab76e9f146102595780633f4ba83a1461026c57600080fd5b806301ffc9a7146101c957806306fdde03146101f1578063081812fc14610206575b600080fd5b6101dc6101d7366004611762565b610444565b60405190151581526020015b60405180910390f35b6101f9610496565b6040516101e891906117cf565b6102196102143660046117e2565b6104d1565b6040516001600160a01b0390911681526020016101e8565b61024461023f366004611810565b6104f8565b005b61024461025436600461183c565b610612565b606554610219906001600160a01b031681565b610244610646565b610244610282366004611810565b6106c4565b61024461029536600461183c565b610745565b6102a461012e5481565b6040519081526020016101e8565b6101dc609754610100900460ff1660021490565b6102196102d43660046117e2565b610760565b6102f261012d5461012e546001600160a01b0390911691565b604080516001600160a01b0390931683526020830191909152016101e8565b61021961031f366004611892565b6107c0565b6102a46103323660046118c7565b6107d7565b61024461085d565b61012d54610219906001600160a01b031681565b610244610871565b6033546001600160a01b0316610219565b6101f96108ea565b610244610382366004611810565b61097c565b6102446103953660046118e4565b610a36565b6102196103a8366004611919565b610a45565b6102446103bb3660046119c8565b610a52565b6101f96103ce3660046117e2565b5060408051602081019091526000815290565b6102446103ef366004611a68565b610a8a565b6101dc610402366004611afb565b6001600160a01b0391821660009081526101006020908152604080832093909416825291909152205460ff1690565b61024461043f3660046118c7565b610c1d565b60006001600160e01b031982166380ac58cd60e01b148061047557506001600160e01b03198216635b5e139f60e01b145b8061049057506301ffc9a760e01b6001600160e01b03198316145b92915050565b60606104a0610c96565b6104ac61012e54610ca5565b6040516020016104bd929190611b34565b604051602081830303815290604052905090565b60006104dc82610d38565b50600090815260ff60205260409020546001600160a01b031690565b600061050382610760565b9050806001600160a01b0316836001600160a01b0316036105755760405162461bcd60e51b815260206004820152602160248201527f4552433732313a20617070726f76616c20746f2063757272656e74206f776e656044820152603960f91b60648201526084015b60405180910390fd5b336001600160a01b038216148061059157506105918133610402565b6106035760405162461bcd60e51b815260206004820152603d60248201527f4552433732313a20617070726f76652063616c6c6572206973206e6f7420746f60448201527f6b656e206f776e6572206f7220617070726f76656420666f7220616c6c000000606482015260840161056c565b61060d8383610d97565b505050565b306001600160a01b0383160361063b57604051636cfe544760e01b815260040160405180910390fd5b61060d838383610e05565b61065a609754610100900460ff1660021490565b6106775760405163bae6e2a960e01b815260040160405180910390fd5b61067f610e36565b6097805461ff0019166101001790556040513381527f5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa906020015b60405180910390a1565b6b195c98cdcc8c57dd985d5b1d60a21b6106df816001610a45565b6001600160a01b0316336001600160a01b03161461071057604051630d85cccf60e11b815260040160405180910390fd5b61071a8383610e90565b60405182906001600160a01b03851690600090600080516020611e59833981519152908290a4505050565b61060d83838360405180602001604052806000815250610a52565b600081815260fd60205260408120546001600160a01b0316806104905760405162461bcd60e51b8152602060048201526018602482015277115490cdcc8c4e881a5b9d985b1a59081d1bdad95b88125160421b604482015260640161056c565b60006107cd848484611009565b90505b9392505050565b60006001600160a01b0382166108415760405162461bcd60e51b815260206004820152602960248201527f4552433732313a2061646472657373207a65726f206973206e6f7420612076616044820152683634b21037bbb732b960b91b606482015260840161056c565b506001600160a01b0316600090815260fe602052604090205490565b610865610e36565b61086f60006110bd565b565b610885609754610100900460ff1660021490565b156108a35760405163bae6e2a960e01b815260040160405180910390fd5b6108ab610e36565b6097805461ff0019166102001790556040513381527f62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a258906020016106ba565b606060fc80546108f990611b72565b80601f016020809104026020016040519081016040528092919081815260200182805461092590611b72565b80156109725780601f1061094757610100808354040283529160200191610972565b820191906000526020600020905b81548152906001019060200180831161095557829003601f168201915b5050505050905090565b6b195c98cdcc8c57dd985d5b1d60a21b610997816001610a45565b6001600160a01b0316336001600160a01b0316146109c857604051630d85cccf60e11b815260040160405180910390fd5b826001600160a01b03166109db83610760565b6001600160a01b031614610a02576040516302dca79760e41b815260040160405180910390fd5b610a0b8261110f565b60405182906000906001600160a01b03861690600080516020611e59833981519152908390a4505050565b610a41338383611192565b5050565b60006107d0468484611009565b610a5c3383611261565b610a785760405162461bcd60e51b815260040161056c90611bac565b610a84848484846112e1565b50505050565b600054610100900460ff1615808015610aaa5750600054600160ff909116105b80610ac45750303b158015610ac4575060005460ff166001145b610b275760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b606482015260840161056c565b6000805460ff191660011790558015610b4a576000805461ff0019166101001790555b6001600160a01b0385161580610b5e575083155b80610b6857504684145b80610b7257508251155b80610b7c57508151155b15610b9a57604051635d061ab760e11b815260040160405180910390fd5b610ba386611314565b610bad8284611337565b61012d80546001600160a01b0319166001600160a01b03871617905561012e8490558015610c15576000805461ff0019169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b505050505050565b610c25610e36565b6001600160a01b038116610c8a5760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b606482015260840161056c565b610c93816110bd565b50565b606060fb80546108f990611b72565b60606000610cb283611368565b600101905060008167ffffffffffffffff811115610cd257610cd261193c565b6040519080825280601f01601f191660200182016040528015610cfc576020820181803683370190505b5090508181016020015b600019016f181899199a1a9b1b9c1cb0b131b232b360811b600a86061a8153600a8504945084610d0657509392505050565b600081815260fd60205260409020546001600160a01b0316610c935760405162461bcd60e51b8152602060048201526018602482015277115490cdcc8c4e881a5b9d985b1a59081d1bdad95b88125160421b604482015260640161056c565b600081815260ff6020526040902080546001600160a01b0319166001600160a01b0384169081179091558190610dcc82610760565b6001600160a01b03167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92560405160405180910390a45050565b610e0f3382611261565b610e2b5760405162461bcd60e51b815260040161056c90611bac565b61060d838383611440565b6033546001600160a01b0316331461086f5760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015260640161056c565b6001600160a01b038216610ee65760405162461bcd60e51b815260206004820181905260248201527f4552433732313a206d696e7420746f20746865207a65726f2061646472657373604482015260640161056c565b600081815260fd60205260409020546001600160a01b031615610f4b5760405162461bcd60e51b815260206004820152601c60248201527f4552433732313a20746f6b656e20616c7265616479206d696e74656400000000604482015260640161056c565b600081815260fd60205260409020546001600160a01b031615610fb05760405162461bcd60e51b815260206004820152601c60248201527f4552433732313a20746f6b656e20616c7265616479206d696e74656400000000604482015260640161056c565b6001600160a01b038216600081815260fe602090815260408083208054600101905584835260fd90915280822080546001600160a01b031916841790555183929190600080516020611e59833981519152908290a45050565b60655460405163195ac1a960e21b815260048101859052602481018490526000916001600160a01b03169063656b06a490604401602060405180830381865afa15801561105a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061107e9190611bf9565b90508115801561109557506001600160a01b038116155b156107d057604051631467050360e21b8152600481018590526024810184905260440161056c565b603380546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b600061111a82610760565b905061112582610760565b600083815260ff6020908152604080832080546001600160a01b03199081169091556001600160a01b03851680855260fe8452828520805460001901905587855260fd90935281842080549091169055519293508492600080516020611e59833981519152908390a45050565b816001600160a01b0316836001600160a01b0316036111f35760405162461bcd60e51b815260206004820152601960248201527f4552433732313a20617070726f766520746f2063616c6c657200000000000000604482015260640161056c565b6001600160a01b0383811660008181526101006020908152604080832094871680845294825291829020805460ff191686151590811790915591519182527f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c31910160405180910390a3505050565b60008061126d83610760565b9050806001600160a01b0316846001600160a01b031614806112b557506001600160a01b038082166000908152610100602090815260408083209388168352929052205460ff165b806112d95750836001600160a01b03166112ce846104d1565b6001600160a01b0316145b949350505050565b6112ec848484611440565b6112f884848484611592565b610a845760405162461bcd60e51b815260040161056c90611c16565b61131c611693565b611325816116c3565b506097805461ffff1916610101179055565b600054610100900460ff1661135e5760405162461bcd60e51b815260040161056c90611c68565b610a41828261170c565b60008072184f03e93ff9f4daa797ed6e38ed64bf6a1f0160401b83106113a75772184f03e93ff9f4daa797ed6e38ed64bf6a1f0160401b830492506040015b6d04ee2d6d415b85acef810000000083106113d3576d04ee2d6d415b85acef8100000000830492506020015b662386f26fc1000083106113f157662386f26fc10000830492506010015b6305f5e1008310611409576305f5e100830492506008015b612710831061141d57612710830492506004015b6064831061142f576064830492506002015b600a83106104905760010192915050565b826001600160a01b031661145382610760565b6001600160a01b0316146114795760405162461bcd60e51b815260040161056c90611cb3565b6001600160a01b0382166114db5760405162461bcd60e51b8152602060048201526024808201527f4552433732313a207472616e7366657220746f20746865207a65726f206164646044820152637265737360e01b606482015260840161056c565b826001600160a01b03166114ee82610760565b6001600160a01b0316146115145760405162461bcd60e51b815260040161056c90611cb3565b600081815260ff6020908152604080832080546001600160a01b03199081169091556001600160a01b0387811680865260fe855283862080546000190190559087168086528386208054600101905586865260fd9094528285208054909216841790915590518493600080516020611e5983398151915291a4505050565b60006001600160a01b0384163b1561168857604051630a85bd0160e11b81526001600160a01b0385169063150b7a02906115d6903390899088908890600401611cf8565b6020604051808303816000875af1925050508015611611575060408051601f3d908101601f1916820190925261160e91810190611d35565b60015b61166e573d80801561163f576040519150601f19603f3d011682016040523d82523d6000602084013e611644565b606091505b5080516000036116665760405162461bcd60e51b815260040161056c90611c16565b805181602001fd5b6001600160e01b031916630a85bd0160e11b1490506112d9565b506001949350505050565b600054610100900460ff166116ba5760405162461bcd60e51b815260040161056c90611c68565b61086f336110bd565b6001600160a01b0381166116ea57604051638ed88b2560e01b815260040160405180910390fd5b606580546001600160a01b0319166001600160a01b0392909216919091179055565b600054610100900460ff166117335760405162461bcd60e51b815260040161056c90611c68565b60fb61173f8382611d98565b5060fc61060d8282611d98565b6001600160e01b031981168114610c9357600080fd5b60006020828403121561177457600080fd5b81356107d08161174c565b60005b8381101561179a578181015183820152602001611782565b50506000910152565b600081518084526117bb81602086016020860161177f565b601f01601f19169290920160200192915050565b6020815260006107d060208301846117a3565b6000602082840312156117f457600080fd5b5035919050565b6001600160a01b0381168114610c9357600080fd5b6000806040838503121561182357600080fd5b823561182e816117fb565b946020939093013593505050565b60008060006060848603121561185157600080fd5b833561185c816117fb565b9250602084013561186c816117fb565b929592945050506040919091013590565b8035801515811461188d57600080fd5b919050565b6000806000606084860312156118a757600080fd5b83359250602084013591506118be6040850161187d565b90509250925092565b6000602082840312156118d957600080fd5b81356107d0816117fb565b600080604083850312156118f757600080fd5b8235611902816117fb565b91506119106020840161187d565b90509250929050565b6000806040838503121561192c57600080fd5b823591506119106020840161187d565b634e487b7160e01b600052604160045260246000fd5b600067ffffffffffffffff8084111561196d5761196d61193c565b604051601f8501601f19908116603f011681019082821181831017156119955761199561193c565b816040528093508581528686860111156119ae57600080fd5b858560208301376000602087830101525050509392505050565b600080600080608085870312156119de57600080fd5b84356119e9816117fb565b935060208501356119f9816117fb565b925060408501359150606085013567ffffffffffffffff811115611a1c57600080fd5b8501601f81018713611a2d57600080fd5b611a3c87823560208401611952565b91505092959194509250565b600082601f830112611a5957600080fd5b6107d083833560208501611952565b600080600080600060a08688031215611a8057600080fd5b8535611a8b816117fb565b94506020860135611a9b816117fb565b935060408601359250606086013567ffffffffffffffff80821115611abf57600080fd5b611acb89838a01611a48565b93506080880135915080821115611ae157600080fd5b50611aee88828901611a48565b9150509295509295909350565b60008060408385031215611b0e57600080fd5b8235611b19816117fb565b91506020830135611b29816117fb565b809150509250929050565b60008351611b4681846020880161177f565b6241c55b60e71b9083019081528351611b6681600484016020880161177f565b01600401949350505050565b600181811c90821680611b8657607f821691505b602082108103611ba657634e487b7160e01b600052602260045260246000fd5b50919050565b6020808252602d908201527f4552433732313a2063616c6c6572206973206e6f7420746f6b656e206f776e6560408201526c1c881bdc88185c1c1c9bdd9959609a1b606082015260800190565b600060208284031215611c0b57600080fd5b81516107d0816117fb565b60208082526032908201527f4552433732313a207472616e7366657220746f206e6f6e20455243373231526560408201527131b2b4bb32b91034b6b83632b6b2b73a32b960711b606082015260800190565b6020808252602b908201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960408201526a6e697469616c697a696e6760a81b606082015260800190565b60208082526025908201527f4552433732313a207472616e736665722066726f6d20696e636f72726563742060408201526437bbb732b960d91b606082015260800190565b6001600160a01b0385811682528416602082015260408101839052608060608201819052600090611d2b908301846117a3565b9695505050505050565b600060208284031215611d4757600080fd5b81516107d08161174c565b601f82111561060d57600081815260208120601f850160051c81016020861015611d795750805b601f850160051c820191505b81811015610c1557828155600101611d85565b815167ffffffffffffffff811115611db257611db261193c565b611dc681611dc08454611b72565b84611d52565b602080601f831160018114611dfb5760008415611de35750858301515b600019600386901b1c1916600185901b178555610c15565b600085815260208120601f198616915b82811015611e2a57888601518255948401946001909101908401611e0b565b5085821015611e485787850151600019600388901b60f8161c191681555b5050505050600190811b0190555056feddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3efa2646970667358221220bfa463938d2c1b37ce8bf2874f3ed7cf383a5e35c121b5812174a79b5309c84164736f6c63430008140033a2646970667358221220740f3cb9624e33bff8d4e691345bcea7689a5314f1271dcd508219d6f0cb765b64736f6c63430008140033", + "balance": "0x0" + }, + "0x1000777700000000000000000000000000000008": { + "contractName": "ERC721VaultProxy", + "storage": { + "0x0000000000000000000000000000000000000000000000000000000000000000": "0x0000000000000000000000000000000000000000000000000000000000000001", + "0x0000000000000000000000000000000000000000000000000000000000000097": "0x0000000000000000000000000000000000000000000000000000000000000101", + "0x0000000000000000000000000000000000000000000000000000000000000033": "0x000000000000000000000000f39fd6e51aad88f6f4ce6ab8827279cfffb92266", + "0x0000000000000000000000000000000000000000000000000000000000000065": "0x0000000000000000000000001000777700000000000000000000000000000006", + "0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103": "0x70997970C51812dc3A010C7d01b50e0d17dc79C8", + "0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc": "0x0000777700000000000000000000000000000008" + }, + "code": "0x60806040526004361061004e5760003560e01c80633659cfe6146100655780634f1ef286146100855780635c60da1b146100985780638f283970146100c9578063f851a440146100e95761005d565b3661005d5761005b6100fe565b005b61005b6100fe565b34801561007157600080fd5b5061005b6100803660046106b3565b610118565b61005b6100933660046106ce565b610155565b3480156100a457600080fd5b506100ad6101bc565b6040516001600160a01b03909116815260200160405180910390f35b3480156100d557600080fd5b5061005b6100e43660046106b3565b6101ed565b3480156100f557600080fd5b506100ad61020d565b61010661022e565b6101166101116102c3565b6102cd565b565b6101206102f1565b6001600160a01b0316330361014d5761014a81604051806020016040528060008152506000610324565b50565b61014a6100fe565b61015d6102f1565b6001600160a01b031633036101b4576101af8383838080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525060019250610324915050565b505050565b6101af6100fe565b60006101c66102f1565b6001600160a01b031633036101e2576101dd6102c3565b905090565b6101ea6100fe565b90565b6101f56102f1565b6001600160a01b0316330361014d5761014a8161034f565b60006102176102f1565b6001600160a01b031633036101e2576101dd6102f1565b6102366102f1565b6001600160a01b031633036101165760405162461bcd60e51b815260206004820152604260248201527f5472616e73706172656e745570677261646561626c6550726f78793a2061646d60448201527f696e2063616e6e6f742066616c6c6261636b20746f2070726f78792074617267606482015261195d60f21b608482015260a4015b60405180910390fd5b60006101dd6103a3565b3660008037600080366000845af43d6000803e8080156102ec573d6000f35b3d6000fd5b60007fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035b546001600160a01b0316919050565b61032d836103cb565b60008251118061033a5750805b156101af57610349838361040b565b50505050565b7f7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f6103786102f1565b604080516001600160a01b03928316815291841660208301520160405180910390a161014a81610437565b60007f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc610315565b6103d4816104e0565b6040516001600160a01b038216907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b90600090a250565b606061043083836040518060600160405280602781526020016107c560279139610574565b9392505050565b6001600160a01b03811661049c5760405162461bcd60e51b815260206004820152602660248201527f455243313936373a206e65772061646d696e20697320746865207a65726f206160448201526564647265737360d01b60648201526084016102ba565b807fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035b80546001600160a01b0319166001600160a01b039290921691909117905550565b6001600160a01b0381163b61054d5760405162461bcd60e51b815260206004820152602d60248201527f455243313936373a206e657720696d706c656d656e746174696f6e206973206e60448201526c1bdd08184818dbdb9d1c9858dd609a1b60648201526084016102ba565b807f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc6104bf565b6060600080856001600160a01b0316856040516105919190610775565b600060405180830381855af49150503d80600081146105cc576040519150601f19603f3d011682016040523d82523d6000602084013e6105d1565b606091505b50915091506105e2868383876105ec565b9695505050505050565b6060831561065b578251600003610654576001600160a01b0385163b6106545760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e747261637400000060448201526064016102ba565b5081610665565b610665838361066d565b949350505050565b81511561067d5781518083602001fd5b8060405162461bcd60e51b81526004016102ba9190610791565b80356001600160a01b03811681146106ae57600080fd5b919050565b6000602082840312156106c557600080fd5b61043082610697565b6000806000604084860312156106e357600080fd5b6106ec84610697565b9250602084013567ffffffffffffffff8082111561070957600080fd5b818601915086601f83011261071d57600080fd5b81358181111561072c57600080fd5b87602082850101111561073e57600080fd5b6020830194508093505050509250925092565b60005b8381101561076c578181015183820152602001610754565b50506000910152565b60008251610787818460208701610751565b9190910192915050565b60208152600082518060208401526107b0816040850160208701610751565b601f01601f1916919091016040019291505056fe416464726573733a206c6f772d6c6576656c2064656c65676174652063616c6c206661696c6564a2646970667358221220e0c34caa93cb549737d2002fe0da3463bee0317add6c2f3da35498d4b65a974464736f6c63430008140033", + "balance": "0x0" + }, + "0x0000777700000000000000000000000000000009": { + "contractName": "ProxiedERC1155Vault", + "storage": {}, + "code": "0x608060405260043610620001435760003560e01c80636c6563f611620000b95780639aa8605c11620000785780639aa8605c1462000372578063a86f9d9e14620003a9578063bc197c8114620003ce578063c287e5781462000401578063f23a6e611462000435578063f2fde38b146200046657600080fd5b80636c6563f614620002e6578063715018a6146200030b5780637333964314620003235780638456cb59146200033a5780638da5cb5b146200035257600080fd5b80633ab76e9f11620001065780633ab76e9f146200020e5780633f4ba83a146200024957806359f4a90714620002615780635c975abb146200027e57806367090ccf14620002a157600080fd5b806301ffc9a7146200014857806319ab453c146200018257806320b8155914620001a95780632ca069a514620001c05780633005fb9814620001f7575b600080fd5b3480156200015557600080fd5b506200016d62000167366004620020b6565b6200048b565b60405190151581526020015b60405180910390f35b3480156200018f57600080fd5b50620001a7620001a136600462002105565b620004d5565b005b620001a7620001ba36600462002248565b620005f5565b348015620001cd57600080fd5b50620001dd636cdb3d1360e11b81565b6040516001600160e01b0319909116815260200162000179565b620001a7620002083660046200230e565b62000986565b3480156200021b57600080fd5b5060655462000230906001600160a01b031681565b6040516001600160a01b03909116815260200162000179565b3480156200025657600080fd5b50620001a762000d1f565b3480156200026e57600080fd5b50620001dd6380ac58cd60e01b81565b3480156200028b57600080fd5b506200016d609754610100900460ff1660021490565b348015620002ae57600080fd5b5062000230620002c03660046200235b565b60cb6020908152600092835260408084209091529082529020546001600160a01b031681565b348015620002f357600080fd5b5062000230620003053660046200239d565b62000da1565b3480156200031857600080fd5b50620001a762000dba565b620001a7620003343660046200245f565b62000dd2565b3480156200034757600080fd5b50620001a7620011ba565b3480156200035f57600080fd5b506033546001600160a01b031662000230565b3480156200037f57600080fd5b50620003976200039136600462002105565b62001238565b604051620001799493929190620025d1565b348015620003b657600080fd5b5062000230620003c836600462002611565b6200138b565b348015620003db57600080fd5b50620001dd620003ed366004620026cb565b63bc197c8160e01b98975050505050505050565b3480156200040e57600080fd5b506200016d6200042036600462002105565b60c96020526000908152604090205460ff1681565b3480156200044257600080fd5b50620001dd6200045436600462002797565b63f23a6e6160e01b9695505050505050565b3480156200047357600080fd5b50620001a76200048536600462002105565b6200139a565b60006001600160e01b031982166301ffc9a760e01b1480620004bd57506001600160e01b03198216630600bf7360e31b145b80620004cf5750620004cf8262001419565b92915050565b600054610100900460ff1615808015620004f65750600054600160ff909116105b80620005125750303b15801562000512575060005460ff166001145b6200057b5760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b60648201526084015b60405180910390fd5b6000805460ff1916600117905580156200059f576000805461ff0019166101001790555b620005aa8262001450565b8015620005f1576000805461ff0019169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b5050565b60975460ff16600119016200061d5760405163dfc60d8560e01b815260040160405180910390fd5b6097805460ff191660021790556200063f609754610100900460ff1660021490565b156200065e5760405163bae6e2a960e01b815260040160405180910390fd5b6562726964676560d01b620006758160016200138b565b6001600160a01b0316336001600160a01b031614620006a757604051630d85cccf60e11b815260040160405180910390fd5b60405163881107d960e01b81526c195c98cc4c4d4d57dd985d5b1d609a1b600482015230602482015260009073502cF119B821a241E25F3acd19548C0Bd825DD759063881107d990604401606060405180830381865af415801562000710573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062000736919062002827565b90506000468835036200081757620007556040890160208a0162002105565b905060005b85518110156200081057816001600160a01b031663f242432a30898985815181106200078a576200078a6200288e565b6020026020010151898681518110620007a757620007a76200288e565b60200260200101516040518563ffffffff1660e01b8152600401620007d09493929190620028a4565b600060405180830381600087803b158015620007eb57600080fd5b505af115801562000800573d6000803e3d6000fd5b505050508060010190506200075a565b50620008fe565b6200082c620008268962002991565b62001477565b905060005b8551811015620008fc57816001600160a01b031663156e29f6888884815181106200086057620008606200288e565b60200260200101518885815181106200087d576200087d6200288e565b60209081029190910101516040516001600160e01b031960e086901b1681526001600160a01b03909316600484015260248301919091526044820152606401600060405180830381600087803b158015620008d757600080fd5b505af1158015620008ec573d6000803e3d6000fd5b5050505080600101905062000831565b505b620009136001600160a01b03871634620014b8565b856001600160a01b0316876001600160a01b031683600001517f0f60c37489e435ed8490c30b01c1fa57e62510e88b351b75796ad3d95babe6b18560400151858a8a604051620009679493929190620029dc565b60405180910390a450506097805460ff19166001179055505050505050565b60975460ff1660011901620009ae5760405163dfc60d8560e01b815260040160405180910390fd5b6097805460ff19166002179055620009d0609754610100900460ff1660021490565b15620009ef5760405163bae6e2a960e01b815260040160405180910390fd5b6562726964676560d01b62000a068160016200138b565b6001600160a01b0316336001600160a01b03161462000a3857604051630d85cccf60e11b815260040160405180910390fd5b6000808062000a4c61014087018762002a1c565b62000a5c91600490829062002a65565b81019062000a6b919062002a91565b6020850151949750909550935050506001600160a01b031662000aa1576040516303f8a7d360e01b815260040160405180910390fd5b6020808401516001600160a01b0316600090815260c9909152604090205460ff161562000bb25760005b825181101562000bab5760208401516001600160a01b031663156e29f662000afa60a08a0160808b0162002105565b85848151811062000b0f5762000b0f6200288e565b602002602001015185858151811062000b2c5762000b2c6200288e565b60209081029190910101516040516001600160e01b031960e086901b1681526001600160a01b03909316600484015260248301919091526044820152606401600060405180830381600087803b15801562000b8657600080fd5b505af115801562000b9b573d6000803e3d6000fd5b5050505080600101905062000acb565b5062000c82565b60005b825181101562000c805760208401516001600160a01b031663f242432a3062000be560a08b0160808c0162002105565b86858151811062000bfa5762000bfa6200288e565b602002602001015186868151811062000c175762000c176200288e565b60200260200101516040518563ffffffff1660e01b815260040162000c409493929190620028a4565b600060405180830381600087803b15801562000c5b57600080fd5b505af115801562000c70573d6000803e3d6000fd5b5050505080600101905062000bb5565b505b62000cad60e087013562000c9d60a0890160808a0162002105565b6001600160a01b031690620014b8565b62000cbf60a087016080880162002105565b6001600160a01b0316857fe8449897bd3c926a272780c39ba13e77bf7a2c823479a75bfbc13ef631183dfd8560200151858560405162000d029392919062002ae4565b60405180910390a350506097805460ff1916600117905550505050565b62000d34609754610100900460ff1660021490565b62000d525760405163bae6e2a960e01b815260040160405180910390fd5b62000d5c6200155c565b6097805461ff0019166101001790556040513381527f5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa906020015b60405180910390a1565b600062000db0848484620015b8565b90505b9392505050565b62000dc46200155c565b62000dd0600062001672565b565b60975460ff166001190162000dfa5760405163dfc60d8560e01b815260040160405180910390fd5b6097805460ff1916600217905562000e1c609754610100900460ff1660021490565b1562000e3b5760405163bae6e2a960e01b815260040160405180910390fd5b60808101516060820151604051636030ce6160e11b815273502cF119B821a241E25F3acd19548C0Bd825DD759263c0619cc29262000e7f9260009060040162002b28565b60006040518083038186803b15801562000e9857600080fd5b505af415801562000ead573d6000803e3d6000fd5b5050505073502cF119B821a241E25F3acd19548C0Bd825DD756393522e3e62000eed83600001516c195c98cc4c4d4d57dd985d5b1d609a1b600062000da1565b602084015160408086015190516001600160e01b031960e086901b1681526001600160a01b039384166004820152918316602483015291909116604482015260640160006040518083038186803b15801562000f4857600080fd5b505af415801562000f5d573d6000803e3d6000fd5b505050604082015162000f8291506001600160a01b0316636cdb3d1360e11b620016c4565b62000fa057604051633ee915f560e11b815260040160405180910390fd5b60808082015160408084015160608086015183516101808101855260008082526020820181905294810185905280830185905295860184905260a0860184905260c0860184905260e086018490526101008601849052610120860193909352610140850181905261016085015291928451606082015262001022338662001759565b610140820152336080820152606081015162001051906c195c98cc4c4d4d57dd985d5b1d609a1b600062000da1565b6001600160a01b031660a08083019190915285015161012082015260c08501516200107d903462002b64565b60e08083019190915260c08087015161010080850191909152918701516001600160a01b031690830152850151610160820152600080620010c86562726964676560d01b826200138b565b6001600160a01b0316635fc34de734856040518363ffffffff1660e01b8152600401620010f6919062002b86565b60006040518083038185885af115801562001115573d6000803e3d6000fd5b50505050506040513d6000823e601f3d908101601f1916820160405262001140919081019062002ceb565b9150915086602001516001600160a01b031681608001516001600160a01b0316837f5e54276405062454e6226625b28a6fea0a838d6b054e38955667234afb3345a3846060015189898c6040516200119c9493929190620029dc565b60405180910390a450506097805460ff191660011790555050505050565b620011cf609754610100900460ff1660021490565b15620011ee5760405163bae6e2a960e01b815260040160405180910390fd5b620011f86200155c565b6097805461ff0019166102001790556040513381527f62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a2589060200162000d97565b60ca6020526000908152604090208054600182015460028301805492936001600160a01b03909216926200126c9062002e2a565b80601f01602080910402602001604051908101604052809291908181526020018280546200129a9062002e2a565b8015620012eb5780601f10620012bf57610100808354040283529160200191620012eb565b820191906000526020600020905b815481529060010190602001808311620012cd57829003601f168201915b505050505090806003018054620013029062002e2a565b80601f0160208091040260200160405190810160405280929190818152602001828054620013309062002e2a565b8015620013815780601f10620013555761010080835404028352916020019162001381565b820191906000526020600020905b8154815290600101906020018083116200136357829003601f168201915b5050505050905084565b600062000db3468484620015b8565b620013a46200155c565b6001600160a01b0381166200140b5760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b606482015260840162000572565b620014168162001672565b50565b60006001600160e01b03198216630271189760e51b1480620004cf57506301ffc9a760e01b6001600160e01b0319831614620004cf565b6200145a62001c63565b620014658162001cdb565b506097805461ffff1916610101179055565b8051600090815260cb60209081526040808320828501516001600160a01b0390811685529252909120541680620014b357620004cf8262001d25565b919050565b6001600160a01b038216620014e057604051634c67134d60e11b815260040160405180910390fd5b6000826001600160a01b03168260405160006040518083038185875af1925050503d80600081146200152f576040519150601f19603f3d011682016040523d82523d6000602084013e62001534565b606091505b50509050806200155757604051634c67134d60e11b815260040160405180910390fd5b505050565b6033546001600160a01b0316331462000dd05760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015260640162000572565b60655460405163195ac1a960e21b815260048101859052602481018490526000916001600160a01b03169063656b06a490604401602060405180830381865afa1580156200160a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062001630919062002e66565b9050811580156200164857506001600160a01b038116155b1562000db357604051631467050360e21b8152600481018590526024810184905260440162000572565b603380546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b60006001600160a01b0383163b620016df57506000620004cf565b6040516301ffc9a760e01b81526001600160e01b0319831660048201526001600160a01b038416906301ffc9a790602401602060405180830381865afa9250505080156200174c575060408051601f3d908101601f19168201909252620017499181019062002e86565b60015b15620004cf579392505050565b604080516080810182526000808252602082015260609181018290528082018290526040808401516001600160a01b0316600090815260c9602052205460ff1615620019fd576040808401516001600160a01b03908116600090815260ca6020908152908390208351608081018552815481526001820154909316918301919091526002810180549293919291840191620017f49062002e2a565b80601f0160208091040260200160405190810160405280929190818152602001828054620018229062002e2a565b8015620018735780601f10620018475761010080835404028352916020019162001873565b820191906000526020600020905b8154815290600101906020018083116200185557829003601f168201915b505050505081526020016003820180546200188e9062002e2a565b80601f0160208091040260200160405190810160405280929190818152602001828054620018bc9062002e2a565b80156200190d5780601f10620018e1576101008083540402835291602001916200190d565b820191906000526020600020905b815481529060010190602001808311620018ef57829003601f168201915b505050505081525050905060005b836060015151811015620019f65783604001516001600160a01b031663f5298aca86866060015184815181106200195657620019566200288e565b6020026020010151876080015185815181106200197757620019776200288e565b60209081029190910101516040516001600160e01b031960e086901b1681526001600160a01b03909316600484015260248301919091526044820152606401600060405180830381600087803b158015620019d157600080fd5b505af1158015620019e6573d6000803e3d6000fd5b505050508060010190506200191b565b5062001bfc565b604051806080016040528046815260200184604001516001600160a01b03168152602001604051806020016040528060008152508152602001604051806020016040528060008152508152509050600083604001519050806001600160a01b03166306fdde036040518163ffffffff1660e01b8152600401600060405180830381865afa92505050801562001ab657506040513d6000823e601f3d908101601f1916820160405262001ab3919081019062002ea6565b60015b1562001ac25760608301525b806001600160a01b03166395d89b416040518163ffffffff1660e01b8152600401600060405180830381865afa92505050801562001b2457506040513d6000823e601f3d908101601f1916820160405262001b21919081019062002ea6565b60015b1562001b305760408301525b60005b84606001515181101562001bf95784604001516001600160a01b031663f242432a33308860600151858151811062001b6f5762001b6f6200288e565b60200260200101518960800151868151811062001b905762001b906200288e565b60200260200101516040518563ffffffff1660e01b815260040162001bb99493929190620028a4565b600060405180830381600087803b15801562001bd457600080fd5b505af115801562001be9573d6000803e3d6000fd5b5050505080600101905062001b33565b50505b6020830151606084015160808501516040516320b8155960e01b9362001c299386938a9360240162002f35565b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b031990931692909217909152949350505050565b600054610100900460ff1662001cd05760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201526a6e697469616c697a696e6760a81b606482015260840162000572565b62000dd03362001672565b6001600160a01b03811662001d0357604051638ed88b2560e01b815260040160405180910390fd5b606580546001600160a01b0319166001600160a01b0392909216919091179055565b60008062001d8260008460405160200162001d41919062002f97565b604051602081830303815290604052805190602001206040518060200162001d6990620020a8565b601f1982820381018352601f9091011660405262001f9e565b905073502cF119B821a241E25F3acd19548C0Bd825DD756378adc0d68262001db26033546001600160a01b031690565b60655460208089015189516040808c015160608d0151915163689ccd8d60e11b9662001dee966001600160a01b03909116959493910162002fac565b60408051601f198184030181529082905262001e0e929160200162002ff5565b6040516020818303038152906040526040518463ffffffff1660e01b815260040162001e3d9392919062003028565b602060405180830381865af415801562001e5b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062001e81919062002e66565b6001600160a01b03818116600090815260c9602090815260408083208054600160ff19909116811790915560ca835292819020885181559188015192820180546001600160a01b03191693909416929092179092558501519193508491600282019062001eef9082620030a8565b506060820151600382019062001f069082620030a8565b50508351600090815260cb6020908152604080832082880180516001600160a01b039081168652919093529281902080546001600160a01b031916878516908117909155915187518289015160608a015193519496509190941693927f2da3c4d305298f6df3653c23d98b4c055f72f7e6f981b2c477ccbec92b1ee5799262001f90929162003174565b60405180910390a450919050565b60008347101562001ff25760405162461bcd60e51b815260206004820152601d60248201527f437265617465323a20696e73756666696369656e742062616c616e6365000000604482015260640162000572565b8151600003620020455760405162461bcd60e51b815260206004820181905260248201527f437265617465323a2062797465636f6465206c656e677468206973207a65726f604482015260640162000572565b8282516020840186f590506001600160a01b03811662000db35760405162461bcd60e51b815260206004820152601960248201527f437265617465323a204661696c6564206f6e206465706c6f7900000000000000604482015260640162000572565b612570806200319e83390190565b600060208284031215620020c957600080fd5b81356001600160e01b03198116811462000db357600080fd5b6001600160a01b03811681146200141657600080fd5b8035620014b381620020e2565b6000602082840312156200211857600080fd5b813562000db381620020e2565b634e487b7160e01b600052604160045260246000fd5b60405161012081016001600160401b038111828210171562002161576200216162002125565b60405290565b60405161018081016001600160401b038111828210171562002161576200216162002125565b604051601f8201601f191681016001600160401b0381118282101715620021b857620021b862002125565b604052919050565b600082601f830112620021d257600080fd5b813560206001600160401b03821115620021f057620021f062002125565b8160051b620022018282016200218d565b92835284810182019282810190878511156200221c57600080fd5b83870192505b848310156200223d5782358252918301919083019062002222565b979650505050505050565b600080600080600060a086880312156200226157600080fd5b85356001600160401b03808211156200227957600080fd5b908701906080828a0312156200228e57600080fd5b909550602087013590620022a282620020e2565b909450604087013590620022b682620020e2565b90935060608701359080821115620022cd57600080fd5b620022db89838a01620021c0565b93506080880135915080821115620022f257600080fd5b506200230188828901620021c0565b9150509295509295909350565b600080604083850312156200232257600080fd5b82356001600160401b038111156200233957600080fd5b830161018081860312156200234d57600080fd5b946020939093013593505050565b600080604083850312156200236f57600080fd5b8235915060208301356200238381620020e2565b809150509250929050565b80151581146200141657600080fd5b600080600060608486031215620023b357600080fd5b83359250602084013591506040840135620023ce816200238e565b809150509250925092565b60006001600160401b03821115620023f557620023f562002125565b50601f01601f191660200190565b600082601f8301126200241557600080fd5b81356200242c6200242682620023d9565b6200218d565b8181528460208386010111156200244257600080fd5b816020850160208301376000918101602001919091529392505050565b6000602082840312156200247257600080fd5b81356001600160401b03808211156200248a57600080fd5b908301906101208286031215620024a057600080fd5b620024aa6200213b565b82358152620024bc60208401620020f8565b6020820152620024cf60408401620020f8565b6040820152606083013582811115620024e757600080fd5b620024f587828601620021c0565b6060830152506080830135828111156200250e57600080fd5b6200251c87828601620021c0565b60808301525060a083013560a082015260c083013560c08201526200254460e08401620020f8565b60e082015261010080840135838111156200255e57600080fd5b6200256c8882870162002403565b918301919091525095945050505050565b60005b838110156200259a57818101518382015260200162002580565b50506000910152565b60008151808452620025bd8160208601602086016200257d565b601f01601f19169290920160200192915050565b8481526001600160a01b0384166020820152608060408201819052600090620025fd90830185620025a3565b82810360608401526200223d8185620025a3565b600080604083850312156200262557600080fd5b82359150602083013562002383816200238e565b60008083601f8401126200264c57600080fd5b5081356001600160401b038111156200266457600080fd5b6020830191508360208260051b85010111156200268057600080fd5b9250929050565b60008083601f8401126200269a57600080fd5b5081356001600160401b03811115620026b257600080fd5b6020830191508360208285010111156200268057600080fd5b60008060008060008060008060a0898b031215620026e857600080fd5b8835620026f581620020e2565b975060208901356200270781620020e2565b965060408901356001600160401b03808211156200272457600080fd5b620027328c838d0162002639565b909850965060608b01359150808211156200274c57600080fd5b6200275a8c838d0162002639565b909650945060808b01359150808211156200277457600080fd5b50620027838b828c0162002687565b999c989b5096995094979396929594505050565b60008060008060008060a08789031215620027b157600080fd5b8635620027be81620020e2565b95506020870135620027d081620020e2565b9450604087013593506060870135925060808701356001600160401b03811115620027fa57600080fd5b6200280889828a0162002687565b979a9699509497509295939492505050565b8051620014b381620020e2565b6000606082840312156200283a57600080fd5b604051606081018181106001600160401b03821117156200285f576200285f62002125565b6040528251815260208301516200287681620020e2565b60208201526040928301519281019290925250919050565b634e487b7160e01b600052603260045260246000fd5b6001600160a01b0394851681529290931660208301526040820152606081019190915260a06080820181905260009082015260c00190565b600060808284031215620028ef57600080fd5b604051608081016001600160401b03828210818311171562002915576200291562002125565b8160405282935084358352602085013591506200293282620020e2565b81602084015260408501359150808211156200294d57600080fd5b6200295b8683870162002403565b604084015260608501359150808211156200297557600080fd5b50620029848582860162002403565b6060830152505092915050565b6000620004cf3683620028dc565b600081518084526020808501945080840160005b83811015620029d157815187529582019590820190600101620029b3565b509495945050505050565b8481526001600160a01b038416602082015260806040820181905260009062002a08908301856200299f565b82810360608401526200223d81856200299f565b6000808335601e1984360301811262002a3457600080fd5b8301803591506001600160401b0382111562002a4f57600080fd5b6020019150368190038213156200268057600080fd5b6000808585111562002a7657600080fd5b8386111562002a8457600080fd5b5050820193919092039150565b600080600080600060a0868803121562002aaa57600080fd5b85356001600160401b038082111562002ac257600080fd5b62002ad089838a01620028dc565b965060208801359150620022a282620020e2565b6001600160a01b038416815260606020820181905260009062002b0a908301856200299f565b828103604084015262002b1e81856200299f565b9695505050505050565b60608152600062002b3d60608301866200299f565b828103602084015262002b5181866200299f565b9150508215156040830152949350505050565b81810381811115620004cf57634e487b7160e01b600052601160045260246000fd5b6020815262002ba16020820183516001600160801b03169052565b6000602083015162002bbe60408401826001600160a01b03169052565b506040830151606083015260608301516080830152608083015162002bee60a08401826001600160a01b03169052565b5060a08301516001600160a01b03811660c08401525060c08301516001600160a01b03811660e08401525060e083015161010083810191909152830151610120808401919091528301516101408084019190915283015161018061016080850182905262002c616101a0860184620025a3565b90860151858203601f19018387015290925062002b1e8382620025a3565b80516001600160801b0381168114620014b357600080fd5b600082601f83011262002ca957600080fd5b815162002cba6200242682620023d9565b81815284602083860101111562002cd057600080fd5b62002ce38260208301602087016200257d565b949350505050565b6000806040838503121562002cff57600080fd5b8251915060208301516001600160401b038082111562002d1e57600080fd5b90840190610180828703121562002d3457600080fd5b62002d3e62002167565b62002d498362002c7f565b815262002d59602084016200281a565b6020820152604083015160408201526060830151606082015262002d80608084016200281a565b608082015262002d9360a084016200281a565b60a082015262002da660c084016200281a565b60c082015260e0838101519082015261010080840151908201526101208084015190820152610140808401518381111562002de057600080fd5b62002dee8982870162002c97565b828401525050610160808401518381111562002e0957600080fd5b62002e178982870162002c97565b8284015250508093505050509250929050565b600181811c9082168062002e3f57607f821691505b60208210810362002e6057634e487b7160e01b600052602260045260246000fd5b50919050565b60006020828403121562002e7957600080fd5b815162000db381620020e2565b60006020828403121562002e9957600080fd5b815162000db3816200238e565b60006020828403121562002eb957600080fd5b81516001600160401b0381111562002ed057600080fd5b62002ce38482850162002c97565b8051825260018060a01b036020820151166020830152600060408201516080604085015262002f116080850182620025a3565b90506060830151848203606086015262002f2c8282620025a3565b95945050505050565b60a08152600062002f4a60a083018862002ede565b6001600160a01b03878116602085015286166040840152828103606084015262002f7581866200299f565b9050828103608084015262002f8b81856200299f565b98975050505050505050565b60208152600062000db3602083018462002ede565b6001600160a01b038681168252851660208201526040810184905260a06060820181905260009062002fe190830185620025a3565b828103608084015262002f8b8185620025a3565b6001600160e01b03198316815281516000906200301a8160048501602087016200257d565b919091016004019392505050565b6001600160a01b0384811682528316602082015260606040820181905260009062002f2c90830184620025a3565b601f8211156200155757600081815260208120601f850160051c810160208610156200307f5750805b601f850160051c820191505b81811015620030a0578281556001016200308b565b505050505050565b81516001600160401b03811115620030c457620030c462002125565b620030dc81620030d5845462002e2a565b8462003056565b602080601f831160018114620031145760008415620030fb5750858301515b600019600386901b1c1916600185901b178555620030a0565b600085815260208120601f198616915b82811015620031455788860151825594840194600190910190840162003124565b5085821015620031645787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b604081526000620031896040830185620025a3565b828103602084015262002f2c8185620025a356fe608060405234801561001057600080fd5b5061001961001e565b6100de565b600054610100900460ff161561008a5760405162461bcd60e51b815260206004820152602760248201527f496e697469616c697a61626c653a20636f6e747261637420697320696e697469604482015266616c697a696e6760c81b606482015260840160405180910390fd5b60005460ff90811610156100dc576000805460ff191660ff9081179091556040519081527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b565b61248280620000ee6000396000f3fe608060405234801561001057600080fd5b50600436106101575760003560e01c8063715018a6116100c3578063a86f9d9e1161007c578063a86f9d9e146102c9578063d1399b1a146102dc578063e985e9c5146102ef578063f242432a1461032b578063f2fde38b1461033e578063f5298aca1461035157600080fd5b8063715018a6146102795780637cf8ed0d146102815780638456cb59146102955780638da5cb5b1461029d57806395d89b41146102ae578063a22cb465146102b657600080fd5b80633ab76e9f116101155780633ab76e9f146101f55780633f4ba83a1461022057806349d12605146102285780634e1273f4146102325780635c975abb146102525780636c6563f61461026657600080fd5b8062fdd58e1461015c57806301ffc9a71461018257806306fdde03146101a55780630e89341c146101ba578063156e29f6146101cd5780632eb2c2d6146101e2575b600080fd5b61016f61016a36600461190f565b610364565b6040519081526020015b60405180910390f35b610195610190366004611951565b6103ff565b6040519015158152602001610179565b6101ad61044f565b60405161017991906119be565b6101ad6101c83660046119d1565b610485565b6101e06101db3660046119ea565b610519565b005b6101e06101f0366004611b6b565b6105cf565b606554610208906001600160a01b031681565b6040516001600160a01b039091168152602001610179565b6101e061061b565b61016f61012e5481565b610245610240366004611c19565b610699565b6040516101799190611d21565b610195609754610100900460ff1660021490565b610208610274366004611d49565b6107c3565b6101e06107da565b61012d54610208906001600160a01b031681565b6101e06107ee565b6033546001600160a01b0316610208565b6101ad610867565b6101e06102c4366004611d7e565b6108f6565b6102086102d7366004611db3565b610905565b6101e06102ea366004611dd6565b610912565b6101956102fd366004611e39565b6001600160a01b03918216600090815260fc6020908152604080832093909416825291909152205460ff1690565b6101e0610339366004611e72565b610abb565b6101e061034c366004611edb565b610af1565b6101e061035f3660046119ea565b610b6a565b60006001600160a01b0383166103d45760405162461bcd60e51b815260206004820152602a60248201527f455243313135353a2061646472657373207a65726f206973206e6f742061207660448201526930b634b21037bbb732b960b11b60648201526084015b60405180910390fd5b50600081815260fb602090815260408083206001600160a01b03861684529091529020545b92915050565b60006001600160e01b03198216636cdb3d1360e11b148061043057506001600160e01b031982166303a24d0760e21b145b806103f957506301ffc9a760e01b6001600160e01b03198316146103f9565b606061013061046061012e54610c06565b604051602001610471929190611f32565b604051602081830303815290604052905090565b606060fd805461049490611ef8565b80601f01602080910402602001604051908101604052809291908181526020018280546104c090611ef8565b801561050d5780601f106104e25761010080835404028352916020019161050d565b820191906000526020600020905b8154815290600101906020018083116104f057829003601f168201915b50505050509050919050565b6c195c98cc4c4d4d57dd985d5b1d609a1b610535816001610905565b6001600160a01b0316336001600160a01b03161461056657604051630d85cccf60e11b815260040160405180910390fd5b61058184848460405180602001604052806000815250610c99565b60408051848152602081018490526001600160a01b038616916000917f9ed053bb818ff08b8353cd46f78db1f0799f31c9e4458fdb425c10eccd2efc4491015b60405180910390a350505050565b6001600160a01b0385163314806105eb57506105eb85336102fd565b6106075760405162461bcd60e51b81526004016103cb90611fc8565b6106148585858585610daf565b5050505050565b61062f609754610100900460ff1660021490565b61064c5760405163bae6e2a960e01b815260040160405180910390fd5b610654610f87565b6097805461ff0019166101001790556040513381527f5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa906020015b60405180910390a1565b606081518351146106fe5760405162461bcd60e51b815260206004820152602960248201527f455243313135353a206163636f756e747320616e6420696473206c656e677468604482015268040dad2e6dac2e8c6d60bb1b60648201526084016103cb565b6000835167ffffffffffffffff81111561071a5761071a611a1f565b604051908082528060200260200182016040528015610743578160200160208202803683370190505b50905060005b84518110156107bb5761078e85828151811061076757610767612016565b602002602001015185838151811061078157610781612016565b6020026020010151610364565b8282815181106107a0576107a0612016565b60209081029190910101526107b481612042565b9050610749565b509392505050565b60006107d0848484610fe1565b90505b9392505050565b6107e2610f87565b6107ec6000611095565b565b610802609754610100900460ff1660021490565b156108205760405163bae6e2a960e01b815260040160405180910390fd5b610828610f87565b6097805461ff0019166102001790556040513381527f62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a2589060200161068f565b61012f805461087590611ef8565b80601f01602080910402602001604051908101604052809291908181526020018280546108a190611ef8565b80156108ee5780601f106108c3576101008083540402835291602001916108ee565b820191906000526020600020905b8154815290600101906020018083116108d157829003601f168201915b505050505081565b6109013383836110e7565b5050565b60006107d3468484610fe1565b600054610100900460ff16158080156109325750600054600160ff909116105b8061094c5750303b15801561094c575060005460ff166001145b6109af5760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b60648201526084016103cb565b6000805460ff1916600117905580156109d2576000805461ff0019166101001790555b6001600160a01b03851615806109e6575083155b806109f057504684145b15610a0e57604051635d061ab760e11b815260040160405180910390fd5b610a17866111c7565b610a2f604051806020016040528060008152506111ea565b61012d80546001600160a01b0319166001600160a01b03871617905561012e84905561012f610a5e84826120a6565b50610130610a6c83826120a6565b508015610ab3576000805461ff0019169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b505050505050565b306001600160a01b03851603610ae457604051636cfe544760e01b815260040160405180910390fd5b610614858585858561121a565b610af9610f87565b6001600160a01b038116610b5e5760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b60648201526084016103cb565b610b6781611095565b50565b6c195c98cc4c4d4d57dd985d5b1d609a1b610b86816001610905565b6001600160a01b0316336001600160a01b031614610bb757604051630d85cccf60e11b815260040160405180910390fd5b610bc284848461125f565b60408051848152602081018490526000916001600160a01b038716917f9ed053bb818ff08b8353cd46f78db1f0799f31c9e4458fdb425c10eccd2efc4491016105c1565b60606000610c13836113de565b600101905060008167ffffffffffffffff811115610c3357610c33611a1f565b6040519080825280601f01601f191660200182016040528015610c5d576020820181803683370190505b5090508181016020015b600019016f181899199a1a9b1b9c1cb0b131b232b360811b600a86061a8153600a8504945084610c6757509392505050565b6001600160a01b038416610cf95760405162461bcd60e51b815260206004820152602160248201527f455243313135353a206d696e7420746f20746865207a65726f206164647265736044820152607360f81b60648201526084016103cb565b336000610d05856114b6565b90506000610d12856114b6565b9050600086815260fb602090815260408083206001600160a01b038b16845290915281208054879290610d46908490612166565b909155505060408051878152602081018790526001600160a01b03808a1692600092918716917fc3d58168c5ae7397731d063d5bbf3d657854427343f4c083240f7aacaa2d0f62910160405180910390a4610da683600089898989611501565b50505050505050565b8151835114610e115760405162461bcd60e51b815260206004820152602860248201527f455243313135353a2069647320616e6420616d6f756e7473206c656e677468206044820152670dad2e6dac2e8c6d60c31b60648201526084016103cb565b6001600160a01b038416610e375760405162461bcd60e51b81526004016103cb90612179565b3360005b8451811015610f21576000858281518110610e5857610e58612016565b602002602001015190506000858381518110610e7657610e76612016565b602090810291909101810151600084815260fb835260408082206001600160a01b038e168352909352919091205490915081811015610ec75760405162461bcd60e51b81526004016103cb906121be565b600083815260fb602090815260408083206001600160a01b038e8116855292528083208585039055908b16825281208054849290610f06908490612166565b9250508190555050505080610f1a90612042565b9050610e3b565b50846001600160a01b0316866001600160a01b0316826001600160a01b03167f4a39dc06d4c0dbc64b70af90fd698a233a518aa5d07e595d983b8c0526c8f7fb8787604051610f71929190612208565b60405180910390a4610ab381878787878761165c565b6033546001600160a01b031633146107ec5760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657260448201526064016103cb565b60655460405163195ac1a960e21b815260048101859052602481018490526000916001600160a01b03169063656b06a490604401602060405180830381865afa158015611032573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110569190612236565b90508115801561106d57506001600160a01b038116155b156107d357604051631467050360e21b815260048101859052602481018490526044016103cb565b603380546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b816001600160a01b0316836001600160a01b03160361115a5760405162461bcd60e51b815260206004820152602960248201527f455243313135353a2073657474696e6720617070726f76616c20737461747573604482015268103337b91039b2b63360b91b60648201526084016103cb565b6001600160a01b03838116600081815260fc6020908152604080832094871680845294825291829020805460ff191686151590811790915591519182527f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c31910160405180910390a3505050565b6111cf611717565b6111d881611747565b506097805461ffff1916610101179055565b600054610100900460ff166112115760405162461bcd60e51b81526004016103cb90612253565b610b6781611790565b6001600160a01b038516331480611236575061123685336102fd565b6112525760405162461bcd60e51b81526004016103cb90611fc8565b61061485858585856117c0565b6001600160a01b0383166112c15760405162461bcd60e51b815260206004820152602360248201527f455243313135353a206275726e2066726f6d20746865207a65726f206164647260448201526265737360e81b60648201526084016103cb565b3360006112cd846114b6565b905060006112da846114b6565b604080516020808201835260009182905288825260fb81528282206001600160a01b038b16835290522054909150848110156113645760405162461bcd60e51b8152602060048201526024808201527f455243313135353a206275726e20616d6f756e7420657863656564732062616c604482015263616e636560e01b60648201526084016103cb565b600086815260fb602090815260408083206001600160a01b038b81168086529184528285208a8703905582518b81529384018a90529092908816917fc3d58168c5ae7397731d063d5bbf3d657854427343f4c083240f7aacaa2d0f62910160405180910390a4604080516020810190915260009052610da6565b60008072184f03e93ff9f4daa797ed6e38ed64bf6a1f0160401b831061141d5772184f03e93ff9f4daa797ed6e38ed64bf6a1f0160401b830492506040015b6d04ee2d6d415b85acef81000000008310611449576d04ee2d6d415b85acef8100000000830492506020015b662386f26fc10000831061146757662386f26fc10000830492506010015b6305f5e100831061147f576305f5e100830492506008015b612710831061149357612710830492506004015b606483106114a5576064830492506002015b600a83106103f95760010192915050565b604080516001808252818301909252606091600091906020808301908036833701905050905082816000815181106114f0576114f0612016565b602090810291909101015292915050565b6001600160a01b0384163b15610ab35760405163f23a6e6160e01b81526001600160a01b0385169063f23a6e6190611545908990899088908890889060040161229e565b6020604051808303816000875af1925050508015611580575060408051601f3d908101601f1916820190925261157d918101906122e3565b60015b61162c5761158c612300565b806308c379a0036115c557506115a061231c565b806115ab57506115c7565b8060405162461bcd60e51b81526004016103cb91906119be565b505b60405162461bcd60e51b815260206004820152603460248201527f455243313135353a207472616e7366657220746f206e6f6e2d455243313135356044820152732932b1b2b4bb32b91034b6b83632b6b2b73a32b960611b60648201526084016103cb565b6001600160e01b0319811663f23a6e6160e01b14610da65760405162461bcd60e51b81526004016103cb906123a6565b6001600160a01b0384163b15610ab35760405163bc197c8160e01b81526001600160a01b0385169063bc197c81906116a090899089908890889088906004016123ee565b6020604051808303816000875af19250505080156116db575060408051601f3d908101601f191682019092526116d8918101906122e3565b60015b6116e75761158c612300565b6001600160e01b0319811663bc197c8160e01b14610da65760405162461bcd60e51b81526004016103cb906123a6565b600054610100900460ff1661173e5760405162461bcd60e51b81526004016103cb90612253565b6107ec33611095565b6001600160a01b03811661176e57604051638ed88b2560e01b815260040160405180910390fd5b606580546001600160a01b0319166001600160a01b0392909216919091179055565b600054610100900460ff166117b75760405162461bcd60e51b81526004016103cb90612253565b610b67816118ee565b6001600160a01b0384166117e65760405162461bcd60e51b81526004016103cb90612179565b3360006117f2856114b6565b905060006117ff856114b6565b9050600086815260fb602090815260408083206001600160a01b038c168452909152902054858110156118445760405162461bcd60e51b81526004016103cb906121be565b600087815260fb602090815260408083206001600160a01b038d8116855292528083208985039055908a16825281208054889290611883908490612166565b909155505060408051888152602081018890526001600160a01b03808b16928c821692918816917fc3d58168c5ae7397731d063d5bbf3d657854427343f4c083240f7aacaa2d0f62910160405180910390a46118e3848a8a8a8a8a611501565b505050505050505050565b60fd61090182826120a6565b6001600160a01b0381168114610b6757600080fd5b6000806040838503121561192257600080fd5b823561192d816118fa565b946020939093013593505050565b6001600160e01b031981168114610b6757600080fd5b60006020828403121561196357600080fd5b81356107d38161193b565b60005b83811015611989578181015183820152602001611971565b50506000910152565b600081518084526119aa81602086016020860161196e565b601f01601f19169290920160200192915050565b6020815260006107d36020830184611992565b6000602082840312156119e357600080fd5b5035919050565b6000806000606084860312156119ff57600080fd5b8335611a0a816118fa565b95602085013595506040909401359392505050565b634e487b7160e01b600052604160045260246000fd5b601f8201601f1916810167ffffffffffffffff81118282101715611a5b57611a5b611a1f565b6040525050565b600067ffffffffffffffff821115611a7c57611a7c611a1f565b5060051b60200190565b600082601f830112611a9757600080fd5b81356020611aa482611a62565b604051611ab18282611a35565b83815260059390931b8501820192828101915086841115611ad157600080fd5b8286015b84811015611aec5780358352918301918301611ad5565b509695505050505050565b600082601f830112611b0857600080fd5b813567ffffffffffffffff811115611b2257611b22611a1f565b604051611b39601f8301601f191660200182611a35565b818152846020838601011115611b4e57600080fd5b816020850160208301376000918101602001919091529392505050565b600080600080600060a08688031215611b8357600080fd5b8535611b8e816118fa565b94506020860135611b9e816118fa565b9350604086013567ffffffffffffffff80821115611bbb57600080fd5b611bc789838a01611a86565b94506060880135915080821115611bdd57600080fd5b611be989838a01611a86565b93506080880135915080821115611bff57600080fd5b50611c0c88828901611af7565b9150509295509295909350565b60008060408385031215611c2c57600080fd5b823567ffffffffffffffff80821115611c4457600080fd5b818501915085601f830112611c5857600080fd5b81356020611c6582611a62565b604051611c728282611a35565b83815260059390931b8501820192828101915089841115611c9257600080fd5b948201945b83861015611cb9578535611caa816118fa565b82529482019490820190611c97565b96505086013592505080821115611ccf57600080fd5b50611cdc85828601611a86565b9150509250929050565b600081518084526020808501945080840160005b83811015611d1657815187529582019590820190600101611cfa565b509495945050505050565b6020815260006107d36020830184611ce6565b80358015158114611d4457600080fd5b919050565b600080600060608486031215611d5e57600080fd5b8335925060208401359150611d7560408501611d34565b90509250925092565b60008060408385031215611d9157600080fd5b8235611d9c816118fa565b9150611daa60208401611d34565b90509250929050565b60008060408385031215611dc657600080fd5b82359150611daa60208401611d34565b600080600080600060a08688031215611dee57600080fd5b8535611df9816118fa565b94506020860135611e09816118fa565b935060408601359250606086013567ffffffffffffffff80821115611e2d57600080fd5b611be989838a01611af7565b60008060408385031215611e4c57600080fd5b8235611e57816118fa565b91506020830135611e67816118fa565b809150509250929050565b600080600080600060a08688031215611e8a57600080fd5b8535611e95816118fa565b94506020860135611ea5816118fa565b93506040860135925060608601359150608086013567ffffffffffffffff811115611ecf57600080fd5b611c0c88828901611af7565b600060208284031215611eed57600080fd5b81356107d3816118fa565b600181811c90821680611f0c57607f821691505b602082108103611f2c57634e487b7160e01b600052602260045260246000fd5b50919050565b6000808454611f4081611ef8565b60018281168015611f585760018114611f6d57611f9c565b60ff1984168752821515830287019450611f9c565b8860005260208060002060005b85811015611f935781548a820152908401908201611f7a565b50505082870194505b50506241c55b60e71b835250508351611fbc81600484016020880161196e565b01600401949350505050565b6020808252602e908201527f455243313135353a2063616c6c6572206973206e6f7420746f6b656e206f776e60408201526d195c881bdc88185c1c1c9bdd995960921b606082015260800190565b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052601160045260246000fd5b6000600182016120545761205461202c565b5060010190565b601f8211156120a157600081815260208120601f850160051c810160208610156120825750805b601f850160051c820191505b81811015610ab35782815560010161208e565b505050565b815167ffffffffffffffff8111156120c0576120c0611a1f565b6120d4816120ce8454611ef8565b8461205b565b602080601f83116001811461210957600084156120f15750858301515b600019600386901b1c1916600185901b178555610ab3565b600085815260208120601f198616915b8281101561213857888601518255948401946001909101908401612119565b50858210156121565787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b808201808211156103f9576103f961202c565b60208082526025908201527f455243313135353a207472616e7366657220746f20746865207a65726f206164604082015264647265737360d81b606082015260800190565b6020808252602a908201527f455243313135353a20696e73756666696369656e742062616c616e636520666f60408201526939103a3930b739b332b960b11b606082015260800190565b60408152600061221b6040830185611ce6565b828103602084015261222d8185611ce6565b95945050505050565b60006020828403121561224857600080fd5b81516107d3816118fa565b6020808252602b908201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960408201526a6e697469616c697a696e6760a81b606082015260800190565b6001600160a01b03868116825285166020820152604081018490526060810183905260a0608082018190526000906122d890830184611992565b979650505050505050565b6000602082840312156122f557600080fd5b81516107d38161193b565b600060033d11156123195760046000803e5060005160e01c5b90565b600060443d101561232a5790565b6040516003193d81016004833e81513d67ffffffffffffffff816024840111818411171561235a57505050505090565b82850191508151818111156123725750505050505090565b843d870101602082850101111561238c5750505050505090565b61239b60208286010187611a35565b509095945050505050565b60208082526028908201527f455243313135353a204552433131353552656365697665722072656a656374656040820152676420746f6b656e7360c01b606082015260800190565b6001600160a01b0386811682528516602082015260a06040820181905260009061241a90830186611ce6565b828103606084015261242c8186611ce6565b905082810360808401526124408185611992565b9897505050505050505056fea264697066735822122024301b126fd789913dbc2205293d09b76b47f21d2d27ff492e762fd23eade43c64736f6c63430008140033a2646970667358221220dd4492ce9ce9743ae9f35d0eb864627d2ad5a0d8a5852fa377c3341d3072e60564736f6c63430008140033", + "balance": "0x0" + }, + "0x1000777700000000000000000000000000000009": { + "contractName": "ERC1155VaultProxy", + "storage": { + "0x0000000000000000000000000000000000000000000000000000000000000000": "0x0000000000000000000000000000000000000000000000000000000000000001", + "0x0000000000000000000000000000000000000000000000000000000000000097": "0x0000000000000000000000000000000000000000000000000000000000000101", + "0x0000000000000000000000000000000000000000000000000000000000000033": "0x000000000000000000000000f39fd6e51aad88f6f4ce6ab8827279cfffb92266", + "0x0000000000000000000000000000000000000000000000000000000000000065": "0x0000000000000000000000001000777700000000000000000000000000000006", + "0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103": "0x70997970C51812dc3A010C7d01b50e0d17dc79C8", + "0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc": "0x0000777700000000000000000000000000000009" + }, + "code": "0x60806040526004361061004e5760003560e01c80633659cfe6146100655780634f1ef286146100855780635c60da1b146100985780638f283970146100c9578063f851a440146100e95761005d565b3661005d5761005b6100fe565b005b61005b6100fe565b34801561007157600080fd5b5061005b6100803660046106b3565b610118565b61005b6100933660046106ce565b610155565b3480156100a457600080fd5b506100ad6101bc565b6040516001600160a01b03909116815260200160405180910390f35b3480156100d557600080fd5b5061005b6100e43660046106b3565b6101ed565b3480156100f557600080fd5b506100ad61020d565b61010661022e565b6101166101116102c3565b6102cd565b565b6101206102f1565b6001600160a01b0316330361014d5761014a81604051806020016040528060008152506000610324565b50565b61014a6100fe565b61015d6102f1565b6001600160a01b031633036101b4576101af8383838080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525060019250610324915050565b505050565b6101af6100fe565b60006101c66102f1565b6001600160a01b031633036101e2576101dd6102c3565b905090565b6101ea6100fe565b90565b6101f56102f1565b6001600160a01b0316330361014d5761014a8161034f565b60006102176102f1565b6001600160a01b031633036101e2576101dd6102f1565b6102366102f1565b6001600160a01b031633036101165760405162461bcd60e51b815260206004820152604260248201527f5472616e73706172656e745570677261646561626c6550726f78793a2061646d60448201527f696e2063616e6e6f742066616c6c6261636b20746f2070726f78792074617267606482015261195d60f21b608482015260a4015b60405180910390fd5b60006101dd6103a3565b3660008037600080366000845af43d6000803e8080156102ec573d6000f35b3d6000fd5b60007fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035b546001600160a01b0316919050565b61032d836103cb565b60008251118061033a5750805b156101af57610349838361040b565b50505050565b7f7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f6103786102f1565b604080516001600160a01b03928316815291841660208301520160405180910390a161014a81610437565b60007f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc610315565b6103d4816104e0565b6040516001600160a01b038216907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b90600090a250565b606061043083836040518060600160405280602781526020016107c560279139610574565b9392505050565b6001600160a01b03811661049c5760405162461bcd60e51b815260206004820152602660248201527f455243313936373a206e65772061646d696e20697320746865207a65726f206160448201526564647265737360d01b60648201526084016102ba565b807fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035b80546001600160a01b0319166001600160a01b039290921691909117905550565b6001600160a01b0381163b61054d5760405162461bcd60e51b815260206004820152602d60248201527f455243313936373a206e657720696d706c656d656e746174696f6e206973206e60448201526c1bdd08184818dbdb9d1c9858dd609a1b60648201526084016102ba565b807f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc6104bf565b6060600080856001600160a01b0316856040516105919190610775565b600060405180830381855af49150503d80600081146105cc576040519150601f19603f3d011682016040523d82523d6000602084013e6105d1565b606091505b50915091506105e2868383876105ec565b9695505050505050565b6060831561065b578251600003610654576001600160a01b0385163b6106545760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e747261637400000060448201526064016102ba565b5081610665565b610665838361066d565b949350505050565b81511561067d5781518083602001fd5b8060405162461bcd60e51b81526004016102ba9190610791565b80356001600160a01b03811681146106ae57600080fd5b919050565b6000602082840312156106c557600080fd5b61043082610697565b6000806000604084860312156106e357600080fd5b6106ec84610697565b9250602084013567ffffffffffffffff8082111561070957600080fd5b818601915086601f83011261071d57600080fd5b81358181111561072c57600080fd5b87602082850101111561073e57600080fd5b6020830194508093505050509250925092565b60005b8381101561076c578181015183820152602001610754565b50506000910152565b60008251610787818460208701610751565b9190910192915050565b60208152600082518060208401526107b0816040850160208701610751565b601f01601f1916919091016040019291505056fe416464726573733a206c6f772d6c6576656c2064656c65676174652063616c6c206661696c6564a2646970667358221220e0c34caa93cb549737d2002fe0da3463bee0317add6c2f3da35498d4b65a974464736f6c63430008140033", + "balance": "0x0" + }, + "0x0000777700000000000000000000000000000003": { + "contractName": "ProxiedEtherVault", + "storage": {}, + "code": "0x6080604052600436106100e15760003560e01c80638456cb591161007f578063ba0bbd9511610059578063ba0bbd951461023a578063d73bb3d01461025a578063f2fde38b1461027a578063fe9fbb801461029a57600080fd5b80638456cb59146101e75780638da5cb5b146101fc578063a86f9d9e1461021a57600080fd5b80633f4ba83a116100bb5780633f4ba83a1461016c5780635c975abb146101815780636c6563f6146101b2578063715018a6146101d257600080fd5b806319ab453c146100ed5780632d1fb3891461010f5780633ab76e9f1461012f57600080fd5b366100e857005b600080fd5b3480156100f957600080fd5b5061010d610108366004610b57565b6102ca565b005b34801561011b57600080fd5b5061010d61012a366004610b89565b6103e2565b34801561013b57600080fd5b5060655461014f906001600160a01b031681565b6040516001600160a01b0390911681526020015b60405180910390f35b34801561017857600080fd5b5061010d6104b1565b34801561018d57600080fd5b506101a2609754610100900460ff1660021490565b6040519015158152602001610163565b3480156101be57600080fd5b5061014f6101cd366004610bbe565b61052f565b3480156101de57600080fd5b5061010d610546565b3480156101f357600080fd5b5061010d61055a565b34801561020857600080fd5b506033546001600160a01b031661014f565b34801561022657600080fd5b5061014f610235366004610bf3565b6105d3565b34801561024657600080fd5b5061010d610255366004610c16565b6105e0565b34801561026657600080fd5b5061010d610275366004610c42565b610704565b34801561028657600080fd5b5061010d610295366004610b57565b6107e9565b3480156102a657600080fd5b506101a26102b5366004610b57565b60c96020526000908152604090205460ff1681565b600054610100900460ff16158080156102ea5750600054600160ff909116105b806103045750303b158015610304575060005460ff166001145b61036c5760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b60648201526084015b60405180910390fd5b6000805460ff19166001179055801561038f576000805461ff0019166101001790555b61039882610862565b80156103de576000805461ff0019169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b5050565b6103ea610885565b6001600160a01b03821661041157604051632f711bc960e11b815260040160405180910390fd5b6001600160a01b038216600090815260c9602052604090205481151560ff90911615150361045257604051632f711bc960e11b815260040160405180910390fd5b6001600160a01b038216600081815260c96020908152604091829020805460ff191685151590811790915591519182527f4c0079b9bcd37cd5d29a13938effd97c881798cbc6bd52a3026a29d94b27d1bf910160405180910390a25050565b6104c5609754610100900460ff1660021490565b6104e25760405163bae6e2a960e01b815260040160405180910390fd5b6104ea610885565b6097805461ff0019166101001790556040513381527f5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa906020015b60405180910390a1565b600061053c8484846108df565b90505b9392505050565b61054e610885565b6105586000610993565b565b61056e609754610100900460ff1660021490565b1561058c5760405163bae6e2a960e01b815260040160405180910390fd5b610594610885565b6097805461ff0019166102001790556040513381527f62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a25890602001610525565b600061053f4684846108df565b33600090815260c9602052604090205460ff1661061057604051632583296b60e01b815260040160405180910390fd5b60975460ff16600119016106375760405163dfc60d8560e01b815260040160405180910390fd5b6097805460ff19166002179055610658609754610100900460ff1660021490565b156106765760405163bae6e2a960e01b815260040160405180910390fd5b6001600160a01b03821661069d5760405163f355fa3360e01b815260040160405180910390fd5b6106b06001600160a01b038316826109e5565b816001600160a01b03167f7b9f77d35803cd201eac9c4ed739bc1fcd3f1be6ab8877d925d1e55517b6fd6e826040516106eb91815260200190565b60405180910390a250506097805460ff19166001179055565b33600090815260c9602052604090205460ff1661073457604051632583296b60e01b815260040160405180910390fd5b60975460ff166001190161075b5760405163dfc60d8560e01b815260040160405180910390fd5b6097805460ff1916600217905561077c609754610100900460ff1660021490565b1561079a5760405163bae6e2a960e01b815260040160405180910390fd5b6107a433826109e5565b60405181815233907f7b9f77d35803cd201eac9c4ed739bc1fcd3f1be6ab8877d925d1e55517b6fd6e9060200160405180910390a2506097805460ff19166001179055565b6107f1610885565b6001600160a01b0381166108565760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b6064820152608401610363565b61085f81610993565b50565b61086a610a85565b61087381610af9565b506097805461ffff1916610101179055565b6033546001600160a01b031633146105585760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610363565b60655460405163195ac1a960e21b815260048101859052602481018490526000916001600160a01b03169063656b06a490604401602060405180830381865afa158015610930573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906109549190610c5b565b90508115801561096b57506001600160a01b038116155b1561053f57604051631467050360e21b81526004810185905260248101849052604401610363565b603380546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b6001600160a01b038216610a0c57604051634c67134d60e11b815260040160405180910390fd5b6000826001600160a01b03168260405160006040518083038185875af1925050503d8060008114610a59576040519150601f19603f3d011682016040523d82523d6000602084013e610a5e565b606091505b5050905080610a8057604051634c67134d60e11b815260040160405180910390fd5b505050565b600054610100900460ff16610af05760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201526a6e697469616c697a696e6760a81b6064820152608401610363565b61055833610993565b6001600160a01b038116610b2057604051638ed88b2560e01b815260040160405180910390fd5b606580546001600160a01b0319166001600160a01b0392909216919091179055565b6001600160a01b038116811461085f57600080fd5b600060208284031215610b6957600080fd5b813561053f81610b42565b80358015158114610b8457600080fd5b919050565b60008060408385031215610b9c57600080fd5b8235610ba781610b42565b9150610bb560208401610b74565b90509250929050565b600080600060608486031215610bd357600080fd5b8335925060208401359150610bea60408501610b74565b90509250925092565b60008060408385031215610c0657600080fd5b82359150610bb560208401610b74565b60008060408385031215610c2957600080fd5b8235610c3481610b42565b946020939093013593505050565b600060208284031215610c5457600080fd5b5035919050565b600060208284031215610c6d57600080fd5b815161053f81610b4256fea264697066735822122074d45297cbd3fc5e6b85ef863c2df1e4227fb3dd97046550a739a4820b3fb61064736f6c63430008140033", + "balance": "0x0" + }, + "0x1000777700000000000000000000000000000003": { + "contractName": "EtherVaultProxy", + "storage": { + "0x0000000000000000000000000000000000000000000000000000000000000000": "0x0000000000000000000000000000000000000000000000000000000000000001", + "0x0000000000000000000000000000000000000000000000000000000000000097": "0x0000000000000000000000000000000000000000000000000000000000000101", + "0x0000000000000000000000000000000000000000000000000000000000000033": "0x000000000000000000000000f39fd6e51aad88f6f4ce6ab8827279cfffb92266", + "0x0000000000000000000000000000000000000000000000000000000000000065": "0x0000000000000000000000001000777700000000000000000000000000000006", + "0xa738d3397c1eb96f671d7e4bd29cabbfa1a9c9ebc0db4142aee17809c43ab720": "0x0000000000000000000000000000000000000000000000000000000000000001", + "0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103": "0x70997970C51812dc3A010C7d01b50e0d17dc79C8", + "0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc": "0x0000777700000000000000000000000000000003" + }, + "code": "0x60806040526004361061004e5760003560e01c80633659cfe6146100655780634f1ef286146100855780635c60da1b146100985780638f283970146100c9578063f851a440146100e95761005d565b3661005d5761005b6100fe565b005b61005b6100fe565b34801561007157600080fd5b5061005b6100803660046106b3565b610118565b61005b6100933660046106ce565b610155565b3480156100a457600080fd5b506100ad6101bc565b6040516001600160a01b03909116815260200160405180910390f35b3480156100d557600080fd5b5061005b6100e43660046106b3565b6101ed565b3480156100f557600080fd5b506100ad61020d565b61010661022e565b6101166101116102c3565b6102cd565b565b6101206102f1565b6001600160a01b0316330361014d5761014a81604051806020016040528060008152506000610324565b50565b61014a6100fe565b61015d6102f1565b6001600160a01b031633036101b4576101af8383838080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525060019250610324915050565b505050565b6101af6100fe565b60006101c66102f1565b6001600160a01b031633036101e2576101dd6102c3565b905090565b6101ea6100fe565b90565b6101f56102f1565b6001600160a01b0316330361014d5761014a8161034f565b60006102176102f1565b6001600160a01b031633036101e2576101dd6102f1565b6102366102f1565b6001600160a01b031633036101165760405162461bcd60e51b815260206004820152604260248201527f5472616e73706172656e745570677261646561626c6550726f78793a2061646d60448201527f696e2063616e6e6f742066616c6c6261636b20746f2070726f78792074617267606482015261195d60f21b608482015260a4015b60405180910390fd5b60006101dd6103a3565b3660008037600080366000845af43d6000803e8080156102ec573d6000f35b3d6000fd5b60007fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035b546001600160a01b0316919050565b61032d836103cb565b60008251118061033a5750805b156101af57610349838361040b565b50505050565b7f7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f6103786102f1565b604080516001600160a01b03928316815291841660208301520160405180910390a161014a81610437565b60007f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc610315565b6103d4816104e0565b6040516001600160a01b038216907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b90600090a250565b606061043083836040518060600160405280602781526020016107c560279139610574565b9392505050565b6001600160a01b03811661049c5760405162461bcd60e51b815260206004820152602660248201527f455243313936373a206e65772061646d696e20697320746865207a65726f206160448201526564647265737360d01b60648201526084016102ba565b807fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035b80546001600160a01b0319166001600160a01b039290921691909117905550565b6001600160a01b0381163b61054d5760405162461bcd60e51b815260206004820152602d60248201527f455243313936373a206e657720696d706c656d656e746174696f6e206973206e60448201526c1bdd08184818dbdb9d1c9858dd609a1b60648201526084016102ba565b807f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc6104bf565b6060600080856001600160a01b0316856040516105919190610775565b600060405180830381855af49150503d80600081146105cc576040519150601f19603f3d011682016040523d82523d6000602084013e6105d1565b606091505b50915091506105e2868383876105ec565b9695505050505050565b6060831561065b578251600003610654576001600160a01b0385163b6106545760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e747261637400000060448201526064016102ba565b5081610665565b610665838361066d565b949350505050565b81511561067d5781518083602001fd5b8060405162461bcd60e51b81526004016102ba9190610791565b80356001600160a01b03811681146106ae57600080fd5b919050565b6000602082840312156106c557600080fd5b61043082610697565b6000806000604084860312156106e357600080fd5b6106ec84610697565b9250602084013567ffffffffffffffff8082111561070957600080fd5b818601915086601f83011261071d57600080fd5b81358181111561072c57600080fd5b87602082850101111561073e57600080fd5b6020830194508093505050509250925092565b60005b8381101561076c578181015183820152602001610754565b50506000910152565b60008251610787818460208701610751565b9190910192915050565b60208152600082518060208401526107b0816040850160208701610751565b601f01601f1916919091016040019291505056fe416464726573733a206c6f772d6c6576656c2064656c65676174652063616c6c206661696c6564a2646970667358221220e0c34caa93cb549737d2002fe0da3463bee0317add6c2f3da35498d4b65a974464736f6c63430008140033", + "balance": "0xfffffffffffffba9c6e7dbb0bfffffff" + }, + "0x0000777700000000000000000000000000000007": { + "contractName": "ProxiedSignalService", + "storage": {}, + "code": "0x608060405234801561001057600080fd5b50600436106100f55760003560e01c8063715018a61161009757806392824e901161006657806392824e90146101e6578063a86f9d9e146101f9578063cbb3ddf31461020c578063f2fde38b1461021357600080fd5b8063715018a6146101b25780638456cb59146101ba578063850fd955146101c25780638da5cb5b146101d557600080fd5b80633f4ba83a116100d35780633f4ba83a146101625780635c975abb1461016a57806366ca2bc01461017e5780636c6563f61461019f57600080fd5b806319ab453c146100fa57806332676bc61461010f5780633ab76e9f14610137575b600080fd5b61010d610108366004611c31565b610226565b005b61012261011d366004611c4e565b61033e565b60405190151581526020015b60405180910390f35b60655461014a906001600160a01b031681565b6040516001600160a01b03909116815260200161012e565b61010d6103a6565b610122609754610100900460ff1660021490565b61019161018c366004611c7a565b610424565b60405190815260200161012e565b61014a6101ad366004611ca8565b61045d565b61010d610474565b61010d610488565b6101916101d0366004611cdd565b610501565b6033546001600160a01b031661014a565b6101226101f4366004611d15565b61055f565b61014a610207366004611dab565b610823565b6000610122565b61010d610221366004611c31565b610839565b600054610100900460ff16158080156102465750600054600160ff909116105b806102605750303b158015610260575060005460ff166001145b6102c85760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b60648201526084015b60405180910390fd5b6000805460ff1916600117905580156102eb576000805461ff0019166101001790555b6102f4826108b2565b801561033a576000805461ff0019169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b5050565b6000826001600160a01b0381166103685760405163985389db60e01b815260040160405180910390fd5b82600081900361038b5760405163c7b4b9bf60e01b815260040160405180910390fd5b6000610398468787610501565b546001149695505050505050565b6103ba609754610100900460ff1660021490565b6103d75760405163bae6e2a960e01b815260040160405180910390fd5b6103df6108d5565b6097805461ff0019166101001790556040513381527f5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa906020015b60405180910390a1565b6000818082036104475760405163c7b4b9bf60e01b815260040160405180910390fd5b610452463385610501565b600181559392505050565b600061046a84848461092f565b90505b9392505050565b61047c6108d5565b61048660006109e3565b565b61049c609754610100900460ff1660021490565b156104ba5760405163bae6e2a960e01b815260040160405180910390fd5b6104c26108d5565b6097805461ff0019166102001790556040513381527f62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a2589060200161041a565b6040516514d251d3905360d21b6020820152602681018490526bffffffffffffffffffffffff19606084901b166046820152605a8101829052600090607a016040516020818303038152906040528051906020012090509392505050565b60006001600160a01b0385161580610575575083155b8061057e575085155b8061058857504686145b156105955750600061081a565b60006105a383850185611eb7565b90508060200151516000036105bc57600091505061081a565b60005b81604001515181101561064757816040015181815181106105e2576105e261202b565b6020026020010151602001516000801b036106025760009250505061081a565b816040015181815181106106185761061861202b565b602002602001015160400151516000036106375760009250505061081a565b61064081612057565b90506105bf565b50600061065d647461696b6f60d81b6000610823565b8251604051638cfb045960e01b815267ffffffffffffffff90911660048201526001600160a01b039190911690638cfb0459906024016040805180830381865afa1580156106af573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906106d39190612070565b60200151905060008190036106ed5760009250505061081a565b60005b8260400151518110156107c0576000836040015182815181106107155761071561202b565b60200260200101519050600061074b82600001516107418460000151647461696b6f60d81b600061045d565b8460200151610501565b905060006107928260405160200161076591815260200190565b60408051601f19818403018152828201825260018352600160f81b60208401529086015190919088610a35565b9050806107a8576000965050505050505061081a565b50506020015191506107b981612057565b90506106f0565b506108156107cf898989610501565b6040516020016107e191815260200190565b604051602081830303815290604052604051806040016040528060018152602001600160f81b815250846020015184610a35565b925050505b95945050505050565b600061083046848461092f565b90505b92915050565b6108416108d5565b6001600160a01b0381166108a65760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b60648201526084016102bf565b6108af816109e3565b50565b6108ba610a59565b6108c381610acd565b506097805461ffff1916610101179055565b6033546001600160a01b031633146104865760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657260448201526064016102bf565b60655460405163195ac1a960e21b815260048101859052602481018490526000916001600160a01b03169063656b06a490604401602060405180830381865afa158015610980573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906109a491906120bf565b9050811580156109bb57506001600160a01b038116155b1561046d57604051631467050360e21b815260048101859052602481018490526044016102bf565b603380546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b600080610a4186610b16565b9050610a4f81868686610b48565b9695505050505050565b600054610100900460ff16610ac45760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201526a6e697469616c697a696e6760a81b60648201526084016102bf565b610486336109e3565b6001600160a01b038116610af457604051638ed88b2560e01b815260040160405180910390fd5b606580546001600160a01b0319166001600160a01b0392909216919091179055565b60608180519060200120604051602001610b3291815260200190565b6040516020818303038152906040529050919050565b6000806000610b58878686610b85565b91509150818015610b7a57508051602080830191909120875191880191909120145b979650505050505050565b600060606000610b9485610c60565b90506000806000610ba6848a89610d59565b81519295509093509150158080610bba5750815b610c065760405162461bcd60e51b815260206004820152601a60248201527f50726f76696465642070726f6f6620697320696e76616c69642e00000000000060448201526064016102bf565b600081610c225760405180602001604052806000815250610c4e565b610c4e86610c316001886120dc565b81518110610c4157610c4161202b565b6020026020010151611179565b919b919a509098505050505050505050565b60606000610c6d836111a0565b90506000815167ffffffffffffffff811115610c8b57610c8b611dd7565b604051908082528060200260200182016040528015610cd057816020015b6040805180820190915260608082526020820152815260200190600190039081610ca95790505b50905060005b8251811015610d51576000610d03848381518110610cf657610cf661202b565b60200260200101516111d3565b90506040518060400160405280610d19836111a0565b815260200182815250838381518110610d3457610d3461202b565b60200260200101819052505080610d4a90612057565b9050610cd6565b509392505050565b600060606000806000610d6b8761125a565b90506000869050600080610d92604051806040016040528060608152602001606081525090565b60005b8c51811015611151578c8181518110610db057610db061202b565b602002602001015191508284610dc691906120ef565b9350610dd36001886120ef565b965083600003610e30578482602001518051906020012014610e2b5760405162461bcd60e51b8152602060048201526011602482015270092dcecc2d8d2c840e4dedee840d0c2e6d607b1b60448201526064016102bf565b610ef2565b602082602001515110610e97578482602001518051906020012014610e2b5760405162461bcd60e51b815260206004820152601b60248201527f496e76616c6964206c6172676520696e7465726e616c2068617368000000000060448201526064016102bf565b84610ea58360200151611393565b14610ef25760405162461bcd60e51b815260206004820152601a60248201527f496e76616c696420696e7465726e616c206e6f6465206861736800000000000060448201526064016102bf565b610efe60106001612102565b60ff1682600001515103610f6c5785518414611151576000868581518110610f2857610f2861202b565b01602001518351805160f89290921c925060009183908110610f4c57610f4c61202b565b60200260200101519050610f5f816113bb565b9650600194505050611141565b815151600119016110f9576000610f82836113f1565b9050600081600081518110610f9957610f9961202b565b016020015160f81c90506000610fb060028361211b565b610fbb90600261214b565b90506000610fcc848360ff16611415565b90506000610fda8b8a611415565b90506000610fe8838361144b565b905060ff851660021480610fff575060ff85166003145b15611039578083511480156110145750808251145b1561102657611023818b6120ef565b99505b50600160ff1b9950611151945050505050565b60ff8516158061104c575060ff85166001145b156110a2578251811461106c5750600160ff1b9950611151945050505050565b61109388600001516001815181106110865761108661202b565b60200260200101516113bb565b9a509750611141945050505050565b60405162461bcd60e51b815260206004820152602660248201527f52656365697665642061206e6f6465207769746820616e20756e6b6e6f776e206044820152650e0e4caccd2f60d31b60648201526084016102bf565b60405162461bcd60e51b815260206004820152601d60248201527f526563656976656420616e20756e706172736561626c65206e6f64652e00000060448201526064016102bf565b61114a81612057565b9050610d95565b50600160ff1b8414866111648786611415565b909e909d50909b509950505050505050505050565b8051805160609161083391611190906001906120dc565b81518110610cf657610cf661202b565b604080518082018252600080825260209182015281518083019092528251825280830190820152606090610833906114c5565b606060008060006111e3856116b1565b9194509250905060008160018111156111fe576111fe612164565b1461124b5760405162461bcd60e51b815260206004820152601860248201527f496e76616c696420524c502062797465732076616c75652e000000000000000060448201526064016102bf565b61081a856020015184846119fb565b606060008251600261126c919061217a565b67ffffffffffffffff81111561128457611284611dd7565b6040519080825280601f01601f1916602001820160405280156112ae576020820181803683370190505b50905060005b835181101561138c5760048482815181106112d1576112d161202b565b01602001516001600160f81b031916901c826112ee83600261217a565b815181106112fe576112fe61202b565b60200101906001600160f81b031916908160001a90535060108482815181106113295761132961202b565b016020015161133b919060f81c61211b565b60f81b8261134a83600261217a565b6113559060016120ef565b815181106113655761136561202b565b60200101906001600160f81b031916908160001a90535061138581612057565b90506112b4565b5092915050565b60006020825110156113a757506020015190565b818060200190518101906108339190612191565b600060606020836000015110156113dc576113d583611aa4565b90506113e8565b6113e5836111d3565b90505b61046d81611393565b60606108336114108360000151600081518110610cf657610cf661202b565b61125a565b6060825182106114345750604080516020810190915260008152610833565b610830838384865161144691906120dc565b611aaf565b6000805b80845111801561145f5750808351115b80156114b057508281815181106114785761147861202b565b602001015160f81c60f81b6001600160f81b03191684828151811061149f5761149f61202b565b01602001516001600160f81b031916145b15610830576114be81612057565b905061144f565b60606000806114d3846116b1565b919350909150600190508160018111156114ef576114ef612164565b1461153c5760405162461bcd60e51b815260206004820152601760248201527f496e76616c696420524c50206c6973742076616c75652e00000000000000000060448201526064016102bf565b6040805160208082526104208201909252600091816020015b60408051808201909152600080825260208201528152602001906001900390816115555790505090506000835b86518110156116a657602082106115ee5760405162461bcd60e51b815260206004820152602a60248201527f50726f766964656420524c50206c6973742065786365656473206d6178206c6960448201526939ba103632b733ba341760b11b60648201526084016102bf565b60008061162b6040518060400160405280858c6000015161160f91906120dc565b8152602001858c6020015161162491906120ef565b90526116b1565b50915091506040518060400160405280838361164791906120ef565b8152602001848b6020015161165c91906120ef565b8152508585815181106116715761167161202b565b60209081029190910101526116876001856120ef565b935061169381836120ef565b61169d90846120ef565b92505050611582565b508152949350505050565b6000806000808460000151116117095760405162461bcd60e51b815260206004820152601860248201527f524c50206974656d2063616e6e6f74206265206e756c6c2e000000000000000060448201526064016102bf565b6020840151805160001a607f811161172e5760006001600094509450945050506119f4565b60b781116117aa5760006117436080836120dc565b9050808760000151116117985760405162461bcd60e51b815260206004820152601960248201527f496e76616c696420524c502073686f727420737472696e672e0000000000000060448201526064016102bf565b600195509350600092506119f4915050565b60bf81116118995760006117bf60b7836120dc565b9050808760000151116118145760405162461bcd60e51b815260206004820152601f60248201527f496e76616c696420524c50206c6f6e6720737472696e67206c656e6774682e0060448201526064016102bf565b600183015160208290036101000a900461182e81836120ef565b88511161187d5760405162461bcd60e51b815260206004820152601860248201527f496e76616c696420524c50206c6f6e6720737472696e672e000000000000000060448201526064016102bf565b6118888260016120ef565b96509450600093506119f492505050565b60f781116119145760006118ae60c0836120dc565b9050808760000151116119035760405162461bcd60e51b815260206004820152601760248201527f496e76616c696420524c502073686f7274206c6973742e00000000000000000060448201526064016102bf565b6001955093508492506119f4915050565b600061192160f7836120dc565b9050808760000151116119765760405162461bcd60e51b815260206004820152601d60248201527f496e76616c696420524c50206c6f6e67206c697374206c656e6774682e00000060448201526064016102bf565b600183015160208290036101000a900461199081836120ef565b8851116119d85760405162461bcd60e51b815260206004820152601660248201527524b73b30b634b210292628103637b733903634b9ba1760511b60448201526064016102bf565b6119e38260016120ef565b96509450600193506119f492505050565b9193909250565b606060008267ffffffffffffffff811115611a1857611a18611dd7565b6040519080825280601f01601f191660200182016040528015611a42576020820181803683370190505b5090508051600003611a5557905061046d565b8484016020820160005b85811015611a77578281015182820152602001611a5f565b5060006001602087066020036101000a039050808251168119845116178252839450505050509392505050565b606061083382611c06565b606081611abd81601f6120ef565b1015611afc5760405162461bcd60e51b815260206004820152600e60248201526d736c6963655f6f766572666c6f7760901b60448201526064016102bf565b82611b0783826120ef565b1015611b465760405162461bcd60e51b815260206004820152600e60248201526d736c6963655f6f766572666c6f7760901b60448201526064016102bf565b611b5082846120ef565b84511015611b945760405162461bcd60e51b8152602060048201526011602482015270736c6963655f6f75744f66426f756e647360781b60448201526064016102bf565b606082158015611bb35760405191506000825260208201604052611bfd565b6040519150601f8416801560200281840101858101878315602002848b0101015b81831015611bec578051835260209283019201611bd4565b5050858452601f01601f1916604052505b50949350505050565b60606108338260200151600084600001516119fb565b6001600160a01b03811681146108af57600080fd5b600060208284031215611c4357600080fd5b813561083081611c1c565b60008060408385031215611c6157600080fd5b8235611c6c81611c1c565b946020939093013593505050565b600060208284031215611c8c57600080fd5b5035919050565b80358015158114611ca357600080fd5b919050565b600080600060608486031215611cbd57600080fd5b8335925060208401359150611cd460408501611c93565b90509250925092565b600080600060608486031215611cf257600080fd5b833592506020840135611d0481611c1c565b929592945050506040919091013590565b600080600080600060808688031215611d2d57600080fd5b853594506020860135611d3f81611c1c565b935060408601359250606086013567ffffffffffffffff80821115611d6357600080fd5b818801915088601f830112611d7757600080fd5b813581811115611d8657600080fd5b896020828501011115611d9857600080fd5b9699959850939650602001949392505050565b60008060408385031215611dbe57600080fd5b82359150611dce60208401611c93565b90509250929050565b634e487b7160e01b600052604160045260246000fd5b6040516060810167ffffffffffffffff81118282101715611e1057611e10611dd7565b60405290565b604051601f8201601f1916810167ffffffffffffffff81118282101715611e3f57611e3f611dd7565b604052919050565b600082601f830112611e5857600080fd5b813567ffffffffffffffff811115611e7257611e72611dd7565b611e85601f8201601f1916602001611e16565b818152846020838601011115611e9a57600080fd5b816020850160208301376000918101602001919091529392505050565b60006020808385031215611eca57600080fd5b823567ffffffffffffffff80821115611ee257600080fd5b9084019060608287031215611ef657600080fd5b611efe611ded565b82358281168114611f0e57600080fd5b81528284013582811115611f2157600080fd5b611f2d88828601611e47565b858301525060408084013583811115611f4557600080fd5b80850194505087601f850112611f5a57600080fd5b833583811115611f6c57611f6c611dd7565b8060051b611f7b878201611e16565b918252858101870191878101908b841115611f9557600080fd5b88880192505b8383101561201657823587811115611fb35760008081fd5b88016060818e03601f19011215611fca5760008081fd5b611fd2611ded565b8a8201358152868201358b820152606082013589811115611ff35760008081fd5b6120018f8d83860101611e47565b82890152508352509188019190880190611f9b565b93850193909352509198975050505050505050565b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052601160045260246000fd5b60006001820161206957612069612041565b5060010190565b60006040828403121561208257600080fd5b6040516040810181811067ffffffffffffffff821117156120a5576120a5611dd7565b604052825181526020928301519281019290925250919050565b6000602082840312156120d157600080fd5b815161083081611c1c565b8181038181111561083357610833612041565b8082018082111561083357610833612041565b60ff818116838216019081111561083357610833612041565b600060ff83168061213c57634e487b7160e01b600052601260045260246000fd5b8060ff84160691505092915050565b60ff828116828216039081111561083357610833612041565b634e487b7160e01b600052602160045260246000fd5b808202811582820484141761083357610833612041565b6000602082840312156121a357600080fd5b505191905056fea26469706673582212203757b44de254a7e528a4a9476f4ed102ede625b5f584178f2beec729aa1781c464736f6c63430008140033", + "balance": "0x0" + }, + "0x1000777700000000000000000000000000000007": { + "contractName": "SignalServiceProxy", + "storage": { + "0x0000000000000000000000000000000000000000000000000000000000000000": "0x0000000000000000000000000000000000000000000000000000000000000001", + "0x0000000000000000000000000000000000000000000000000000000000000097": "0x0000000000000000000000000000000000000000000000000000000000000101", + "0x0000000000000000000000000000000000000000000000000000000000000033": "0x000000000000000000000000f39fd6e51aad88f6f4ce6ab8827279cfffb92266", + "0x0000000000000000000000000000000000000000000000000000000000000065": "0x0000000000000000000000001000777700000000000000000000000000000006", + "0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103": "0x70997970C51812dc3A010C7d01b50e0d17dc79C8", + "0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc": "0x0000777700000000000000000000000000000007" + }, + "code": "0x60806040526004361061004e5760003560e01c80633659cfe6146100655780634f1ef286146100855780635c60da1b146100985780638f283970146100c9578063f851a440146100e95761005d565b3661005d5761005b6100fe565b005b61005b6100fe565b34801561007157600080fd5b5061005b6100803660046106b3565b610118565b61005b6100933660046106ce565b610155565b3480156100a457600080fd5b506100ad6101bc565b6040516001600160a01b03909116815260200160405180910390f35b3480156100d557600080fd5b5061005b6100e43660046106b3565b6101ed565b3480156100f557600080fd5b506100ad61020d565b61010661022e565b6101166101116102c3565b6102cd565b565b6101206102f1565b6001600160a01b0316330361014d5761014a81604051806020016040528060008152506000610324565b50565b61014a6100fe565b61015d6102f1565b6001600160a01b031633036101b4576101af8383838080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525060019250610324915050565b505050565b6101af6100fe565b60006101c66102f1565b6001600160a01b031633036101e2576101dd6102c3565b905090565b6101ea6100fe565b90565b6101f56102f1565b6001600160a01b0316330361014d5761014a8161034f565b60006102176102f1565b6001600160a01b031633036101e2576101dd6102f1565b6102366102f1565b6001600160a01b031633036101165760405162461bcd60e51b815260206004820152604260248201527f5472616e73706172656e745570677261646561626c6550726f78793a2061646d60448201527f696e2063616e6e6f742066616c6c6261636b20746f2070726f78792074617267606482015261195d60f21b608482015260a4015b60405180910390fd5b60006101dd6103a3565b3660008037600080366000845af43d6000803e8080156102ec573d6000f35b3d6000fd5b60007fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035b546001600160a01b0316919050565b61032d836103cb565b60008251118061033a5750805b156101af57610349838361040b565b50505050565b7f7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f6103786102f1565b604080516001600160a01b03928316815291841660208301520160405180910390a161014a81610437565b60007f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc610315565b6103d4816104e0565b6040516001600160a01b038216907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b90600090a250565b606061043083836040518060600160405280602781526020016107c560279139610574565b9392505050565b6001600160a01b03811661049c5760405162461bcd60e51b815260206004820152602660248201527f455243313936373a206e65772061646d696e20697320746865207a65726f206160448201526564647265737360d01b60648201526084016102ba565b807fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035b80546001600160a01b0319166001600160a01b039290921691909117905550565b6001600160a01b0381163b61054d5760405162461bcd60e51b815260206004820152602d60248201527f455243313936373a206e657720696d706c656d656e746174696f6e206973206e60448201526c1bdd08184818dbdb9d1c9858dd609a1b60648201526084016102ba565b807f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc6104bf565b6060600080856001600160a01b0316856040516105919190610775565b600060405180830381855af49150503d80600081146105cc576040519150601f19603f3d011682016040523d82523d6000602084013e6105d1565b606091505b50915091506105e2868383876105ec565b9695505050505050565b6060831561065b578251600003610654576001600160a01b0385163b6106545760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e747261637400000060448201526064016102ba565b5081610665565b610665838361066d565b949350505050565b81511561067d5781518083602001fd5b8060405162461bcd60e51b81526004016102ba9190610791565b80356001600160a01b03811681146106ae57600080fd5b919050565b6000602082840312156106c557600080fd5b61043082610697565b6000806000604084860312156106e357600080fd5b6106ec84610697565b9250602084013567ffffffffffffffff8082111561070957600080fd5b818601915086601f83011261071d57600080fd5b81358181111561072c57600080fd5b87602082850101111561073e57600080fd5b6020830194508093505050509250925092565b60005b8381101561076c578181015183820152602001610754565b50506000910152565b60008251610787818460208701610751565b9190910192915050565b60208152600082518060208401526107b0816040850160208701610751565b601f01601f1916919091016040019291505056fe416464726573733a206c6f772d6c6576656c2064656c65676174652063616c6c206661696c6564a2646970667358221220e0c34caa93cb549737d2002fe0da3463bee0317add6c2f3da35498d4b65a974464736f6c63430008140033", + "balance": "0x0" + }, + "0x0000777700000000000000000000000000000005": { + "contractName": "RegularERC20", + "storage": { + "0x0000000000000000000000000000000000000000000000000000000000000003": "0x526567756c617245524332300000000000000000000000000000000000000018", + "0x0000000000000000000000000000000000000000000000000000000000000004": "0x52474c0000000000000000000000000000000000000000000000000000000006", + "0x0000000000000000000000000000000000000000000000000000000000000002": "0x0000000000000000000000000000000000000000000000000000000001388000", + "0x723077b8a1b173adc35e5f0e7e3662fd1208212cb629f9c128551ea7168da722": "0x00000000000000000000000000000000000000000000000000000000000fa000", + "0x14e04a66bf74771820a7400ff6cf065175b3d7eb25805a5bd1633b161af5d101": "0x00000000000000000000000000000000000000000000000000000000000fa000", + "0x215be5d23550ceb1beff54fb579a765903ba2ccc85b6f79bcf9bda4e8cb86034": "0x00000000000000000000000000000000000000000000000000000000000fa000", + "0x6d1035fce6503985ab075a4ff3f7ce2e57cd5a9c5e6a0589dccacfea7bcb0af4": "0x00000000000000000000000000000000000000000000000000000000000fa000", + "0x2a95ee547cef07a2fff0a68144824a0d9ded35ed87da118a53e1cda4aca8b944": "0x00000000000000000000000000000000000000000000000000000000000fa000", + "0x7fcecd2a720442e9bc0cf1a8a6976f9fbddf6b996dc0d78af7e94dadf360d579": "0x00000000000000000000000000000000000000000000000000000000000fa000", + "0x18bbf5fcf8fe870ecff419c4677497c08b2e6a5431bb94541d06c9da3f308e55": "0x00000000000000000000000000000000000000000000000000000000000fa000", + "0x6e3431b4e42570cb9e3d926eb26f9e54de2df536ae0741ae16350d17a6c16ddc": "0x00000000000000000000000000000000000000000000000000000000000fa000", + "0xdb302bf24b1ad5f23949da8e6b05747dc699499a995361a7bf40ec7204696d6f": "0x00000000000000000000000000000000000000000000000000000000000fa000", + "0xa1d47ef1a6916dfbe65888f77739da164feb3a9a6afc95ee57e8b3e85ea5e955": "0x00000000000000000000000000000000000000000000000000000000000fa000", + "0x454340b1295f9ff1c0fb9192166d0215d33f84dc5f2dc3f3e5732a4b557186bf": "0x00000000000000000000000000000000000000000000000000000000000fa000", + "0x6a3bb1dada7c82a99b4a02d16da3fda07cb31d8887b9b99ec829ab67fd7a817e": "0x00000000000000000000000000000000000000000000000000000000000fa000", + "0x2fe2844d12634f5dce1e2be5be96b2ea1c573f8f25171997e2f4bd943dd32f92": "0x00000000000000000000000000000000000000000000000000000000000fa000", + "0x3836a017087644fbf6925ae1aca14201ce898a35434d9dea9ebd03cea44e049a": "0x00000000000000000000000000000000000000000000000000000000000fa000", + "0x1c7a29f5a750951acb14fdf82a876085914eb17f15a162b054a3d2f8c92e2451": "0x00000000000000000000000000000000000000000000000000000000000fa000", + "0x271927a243b678b7a071f19b4051ef93b16e397066e3fdef5bba26527e34a1a1": "0x00000000000000000000000000000000000000000000000000000000000fa000", + "0x4663d660b5d810c9ab2f6dc64af7ff84ebae28a72342391622649a7fe87c93d4": "0x00000000000000000000000000000000000000000000000000000000000fa000", + "0x352c3281a58937f04ef7cc7b88f3456b6ffd47f52a321c253dc083fb53a3a114": "0x00000000000000000000000000000000000000000000000000000000000fa000", + "0x6d5faa5f4e671e6fe47b0eab51c62f8cebf354e21e8fdccf8cdfc0293dd341a3": "0x00000000000000000000000000000000000000000000000000000000000fa000", + "0x673de83553dc3a2c0f59aa7193de392a4530feb73b9d6cd4fcef68802b8195c1": "0x00000000000000000000000000000000000000000000000000000000000fa000" + }, + "code": "0x608060405234801561001057600080fd5b50600436106100a95760003560e01c80633950935111610071578063395093511461012357806370a082311461013657806395d89b411461015f578063a457c2d714610167578063a9059cbb1461017a578063dd62ed3e1461018d57600080fd5b806306fdde03146100ae578063095ea7b3146100cc57806318160ddd146100ef57806323b872dd14610101578063313ce56714610114575b600080fd5b6100b66101a0565b6040516100c3919061069c565b60405180910390f35b6100df6100da366004610706565b610232565b60405190151581526020016100c3565b6002545b6040519081526020016100c3565b6100df61010f366004610730565b61024c565b604051601281526020016100c3565b6100df610131366004610706565b610270565b6100f361014436600461076c565b6001600160a01b031660009081526020819052604090205490565b6100b6610292565b6100df610175366004610706565b6102a1565b6100df610188366004610706565b610321565b6100f361019b36600461078e565b61032f565b6060600380546101af906107c1565b80601f01602080910402602001604051908101604052809291908181526020018280546101db906107c1565b80156102285780601f106101fd57610100808354040283529160200191610228565b820191906000526020600020905b81548152906001019060200180831161020b57829003601f168201915b5050505050905090565b60003361024081858561035a565b60019150505b92915050565b60003361025a85828561047e565b6102658585856104f8565b506001949350505050565b600033610240818585610283838361032f565b61028d91906107fb565b61035a565b6060600480546101af906107c1565b600033816102af828661032f565b9050838110156103145760405162461bcd60e51b815260206004820152602560248201527f45524332303a2064656372656173656420616c6c6f77616e63652062656c6f77604482015264207a65726f60d81b60648201526084015b60405180910390fd5b610265828686840361035a565b6000336102408185856104f8565b6001600160a01b03918216600090815260016020908152604080832093909416825291909152205490565b6001600160a01b0383166103bc5760405162461bcd60e51b8152602060048201526024808201527f45524332303a20617070726f76652066726f6d20746865207a65726f206164646044820152637265737360e01b606482015260840161030b565b6001600160a01b03821661041d5760405162461bcd60e51b815260206004820152602260248201527f45524332303a20617070726f766520746f20746865207a65726f206164647265604482015261737360f01b606482015260840161030b565b6001600160a01b0383811660008181526001602090815260408083209487168084529482529182902085905590518481527f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925910160405180910390a3505050565b600061048a848461032f565b905060001981146104f257818110156104e55760405162461bcd60e51b815260206004820152601d60248201527f45524332303a20696e73756666696369656e7420616c6c6f77616e6365000000604482015260640161030b565b6104f2848484840361035a565b50505050565b6001600160a01b03831661055c5760405162461bcd60e51b815260206004820152602560248201527f45524332303a207472616e736665722066726f6d20746865207a65726f206164604482015264647265737360d81b606482015260840161030b565b6001600160a01b0382166105be5760405162461bcd60e51b815260206004820152602360248201527f45524332303a207472616e7366657220746f20746865207a65726f206164647260448201526265737360e81b606482015260840161030b565b6001600160a01b038316600090815260208190526040902054818110156106365760405162461bcd60e51b815260206004820152602660248201527f45524332303a207472616e7366657220616d6f756e7420657863656564732062604482015265616c616e636560d01b606482015260840161030b565b6001600160a01b03848116600081815260208181526040808320878703905593871680835291849020805487019055925185815290927fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef910160405180910390a36104f2565b600060208083528351808285015260005b818110156106c9578581018301518582016040015282016106ad565b506000604082860101526040601f19601f8301168501019250505092915050565b80356001600160a01b038116811461070157600080fd5b919050565b6000806040838503121561071957600080fd5b610722836106ea565b946020939093013593505050565b60008060006060848603121561074557600080fd5b61074e846106ea565b925061075c602085016106ea565b9150604084013590509250925092565b60006020828403121561077e57600080fd5b610787826106ea565b9392505050565b600080604083850312156107a157600080fd5b6107aa836106ea565b91506107b8602084016106ea565b90509250929050565b600181811c908216806107d557607f821691505b6020821081036107f557634e487b7160e01b600052602260045260246000fd5b50919050565b8082018082111561024657634e487b7160e01b600052601160045260246000fdfea264697066735822122055389869d93aea00eadfbfb381b9a03a1b06411c851d9e0166c4d6547c456d8664736f6c63430008140033", + "balance": "0x0" + } +}
diff --git ethereum/go-ethereum/core/taiko_genesis/jolnir.json taikoxyz/taiko-geth/core/taiko_genesis/jolnir.json new file mode 100644 index 0000000000000000000000000000000000000000..d460a95a4d9e288c338e89248803ad14ed65f362 --- /dev/null +++ taikoxyz/taiko-geth/core/taiko_genesis/jolnir.json @@ -0,0 +1,210 @@ +{ + "0x19B4F9C381C7927FE33D853e48b560141A380C44": { + "balance": "0xfffffffffffffacbbb7ca13a7fffffff" + }, + "0x113cE23c9e0cc50F4D41d7cE6DA02dCAFf8BFF85": { + "balance": "0xfffffffffffffacbbb7ca13a7fffffff" + }, + "0xFa9d666c396c64d155BDc23a2AAA53984939A4Ee": { + "balance": "0xfffffffffffffacbbb7ca13a7fffffff" + }, + "0xb631796561d587AeEF2Fdd09AD33b8DE4bc92510": { + "balance": "0xfffffffffffffacbbb7ca13a7fffffff" + }, + "0x8a9f79C3dc6158E58484ceEd46d93c4B0bAD0824": { + "contractName": "LibTrieProof", + "storage": {}, + "code": "0x73000000000000000000000000000000000000000030146080604052600436106100355760003560e01c80636892abdc1461003a575b600080fd5b61004d61004836600461170f565b610061565b604051901515815260200160405180910390f35b600080806100718486018661185f565b6040516bffffffffffffffffffffffff1960608c901b166020820152919350915060009081906100b490603401604051602081830303815290604052858d610150565b91509150816100d657604051639dbcc1a760e01b815260040160405180910390fd5b60006100e182610179565b90506000610108826002815181106100fb576100fb6118c3565b60200260200101516101b2565b905061013f8b60405160200161012091815260200190565b6040516020818303038152906040526101388c6102ba565b87846102cd565b9d9c50505050505050505050505050565b60006060600061015f866102e7565b905061016c818686610319565b9250925050935093915050565b6040805180820182526000808252602091820152815180830190925282518252808301908201526060906101ac906103f4565b92915050565b600060218260000151111561020e5760405162461bcd60e51b815260206004820152601a60248201527f496e76616c696420524c5020627974657333322076616c75652e00000000000060448201526064015b60405180910390fd5b600080600061021c856105e0565b919450925090506000816001811115610237576102376118d9565b146102845760405162461bcd60e51b815260206004820152601a60248201527f496e76616c696420524c5020627974657333322076616c75652e0000000000006044820152606401610205565b60008386602001516102969190611905565b805190915060208410156102b05760208490036101000a90045b9695505050505050565b60606101ac6102c88361092a565b610a5e565b6000806102d9866102e7565b90506102b081868686610acd565b6060818051906020012060405160200161030391815260200190565b6040516020818303038152906040529050919050565b60006060600061032885610b0a565b9050600080600061033a848a89610c03565b8151929550909350915015808061034e5750815b61039a5760405162461bcd60e51b815260206004820152601a60248201527f50726f76696465642070726f6f6620697320696e76616c69642e0000000000006044820152606401610205565b6000816103b657604051806020016040528060008152506103e2565b6103e2866103c5600188611918565b815181106103d5576103d56118c3565b6020026020010151611023565b919b919a509098505050505050505050565b6060600080610402846105e0565b9193509091506001905081600181111561041e5761041e6118d9565b1461046b5760405162461bcd60e51b815260206004820152601760248201527f496e76616c696420524c50206c6973742076616c75652e0000000000000000006044820152606401610205565b6040805160208082526104208201909252600091816020015b60408051808201909152600080825260208201528152602001906001900390816104845790505090506000835b86518110156105d5576020821061051d5760405162461bcd60e51b815260206004820152602a60248201527f50726f766964656420524c50206c6973742065786365656473206d6178206c6960448201526939ba103632b733ba341760b11b6064820152608401610205565b60008061055a6040518060400160405280858c6000015161053e9190611918565b8152602001858c602001516105539190611905565b90526105e0565b5091509150604051806040016040528083836105769190611905565b8152602001848b6020015161058b9190611905565b8152508585815181106105a0576105a06118c3565b60209081029190910101526105b6600185611905565b93506105c28183611905565b6105cc9084611905565b925050506104b1565b508152949350505050565b6000806000808460000151116106385760405162461bcd60e51b815260206004820152601860248201527f524c50206974656d2063616e6e6f74206265206e756c6c2e00000000000000006044820152606401610205565b6020840151805160001a607f811161065d576000600160009450945094505050610923565b60b781116106d9576000610672608083611918565b9050808760000151116106c75760405162461bcd60e51b815260206004820152601960248201527f496e76616c696420524c502073686f727420737472696e672e000000000000006044820152606401610205565b60019550935060009250610923915050565b60bf81116107c85760006106ee60b783611918565b9050808760000151116107435760405162461bcd60e51b815260206004820152601f60248201527f496e76616c696420524c50206c6f6e6720737472696e67206c656e6774682e006044820152606401610205565b600183015160208290036101000a900461075d8183611905565b8851116107ac5760405162461bcd60e51b815260206004820152601860248201527f496e76616c696420524c50206c6f6e6720737472696e672e00000000000000006044820152606401610205565b6107b7826001611905565b965094506000935061092392505050565b60f781116108435760006107dd60c083611918565b9050808760000151116108325760405162461bcd60e51b815260206004820152601760248201527f496e76616c696420524c502073686f7274206c6973742e0000000000000000006044820152606401610205565b600195509350849250610923915050565b600061085060f783611918565b9050808760000151116108a55760405162461bcd60e51b815260206004820152601d60248201527f496e76616c696420524c50206c6f6e67206c697374206c656e6774682e0000006044820152606401610205565b600183015160208290036101000a90046108bf8183611905565b8851116109075760405162461bcd60e51b815260206004820152601660248201527524b73b30b634b210292628103637b733903634b9ba1760511b6044820152606401610205565b610912826001611905565b965094506001935061092392505050565b9193909250565b606060008260405160200161094191815260200190565b604051602081830303815290604052905060005b602081101561099657818181518110610970576109706118c3565b01602001516001600160f81b0319166000036109965761098f8161192b565b9050610955565b60006109a3826020611918565b67ffffffffffffffff8111156109bb576109bb6117bc565b6040519080825280601f01601f1916602001820160405280156109e5576020820181803683370190505b50905060005b8151811015610a555783836109ff8161192b565b945081518110610a1157610a116118c3565b602001015160f81c60f81b828281518110610a2e57610a2e6118c3565b60200101906001600160f81b031916908160001a905350610a4e8161192b565b90506109eb565b50949350505050565b60608082516001148015610a8c5750608083600081518110610a8257610a826118c3565b016020015160f81c105b15610a985750816101ac565b610aa48351608061104a565b83604051602001610ab6929190611974565b604051602081830303815290604052905092915050565b6000806000610add878686610319565b91509150818015610aff57508051602080830191909120875191880191909120145b979650505050505050565b60606000610b1783610179565b90506000815167ffffffffffffffff811115610b3557610b356117bc565b604051908082528060200260200182016040528015610b7a57816020015b6040805180820190915260608082526020820152815260200190600190039081610b535790505b50905060005b8251811015610bfb576000610bad848381518110610ba057610ba06118c3565b60200260200101516111f4565b90506040518060400160405280610bc383610179565b815260200182815250838381518110610bde57610bde6118c3565b60200260200101819052505080610bf49061192b565b9050610b80565b509392505050565b600060606000806000610c1587611284565b90506000869050600080610c3c604051806040016040528060608152602001606081525090565b60005b8c51811015610ffb578c8181518110610c5a57610c5a6118c3565b602002602001015191508284610c709190611905565b9350610c7d600188611905565b965083600003610cda578482602001518051906020012014610cd55760405162461bcd60e51b8152602060048201526011602482015270092dcecc2d8d2c840e4dedee840d0c2e6d607b1b6044820152606401610205565b610d9c565b602082602001515110610d41578482602001518051906020012014610cd55760405162461bcd60e51b815260206004820152601b60248201527f496e76616c6964206c6172676520696e7465726e616c206861736800000000006044820152606401610205565b84610d4f83602001516113bd565b14610d9c5760405162461bcd60e51b815260206004820152601a60248201527f496e76616c696420696e7465726e616c206e6f646520686173680000000000006044820152606401610205565b610da860106001611991565b60ff1682600001515103610e165785518414610ffb576000868581518110610dd257610dd26118c3565b01602001518351805160f89290921c925060009183908110610df657610df66118c3565b60200260200101519050610e09816113e5565b9650600194505050610feb565b81515160011901610fa3576000610e2c8361141b565b9050600081600081518110610e4357610e436118c3565b016020015160f81c90506000610e5a6002836119c0565b610e659060026119e2565b90506000610e76848360ff1661143f565b90506000610e848b8a61143f565b90506000610e928383611475565b905060ff851660021480610ea9575060ff85166003145b15610ee357808351148015610ebe5750808251145b15610ed057610ecd818b611905565b99505b50600160ff1b9950610ffb945050505050565b60ff85161580610ef6575060ff85166001145b15610f4c5782518114610f165750600160ff1b9950610ffb945050505050565b610f3d8860000151600181518110610f3057610f306118c3565b60200260200101516113e5565b9a509750610feb945050505050565b60405162461bcd60e51b815260206004820152602660248201527f52656365697665642061206e6f6465207769746820616e20756e6b6e6f776e206044820152650e0e4caccd2f60d31b6064820152608401610205565b60405162461bcd60e51b815260206004820152601d60248201527f526563656976656420616e20756e706172736561626c65206e6f64652e0000006044820152606401610205565b610ff48161192b565b9050610c3f565b50600160ff1b84148661100e878661143f565b909e909d50909b509950505050505050505050565b805180516060916101ac9161103a90600190611918565b81518110610ba057610ba06118c3565b60608060388410156110b1576040805160018082528183019092529060208201818036833701905050905061107f8385611991565b60f81b81600081518110611095576110956118c3565b60200101906001600160f81b031916908160001a9053506111ed565b600060015b6110c081876119fb565b156110e3576110ce8261192b565b91506110dc61010082611a0f565b90506110b6565b6110ee826001611905565b67ffffffffffffffff811115611106576111066117bc565b6040519080825280601f01601f191660200182016040528015611130576020820181803683370190505b50925061113d8583611991565b611148906037611991565b60f81b8360008151811061115e5761115e6118c3565b60200101906001600160f81b031916908160001a905350600190505b8181116111ea5761010061118e8284611918565b61119a90610100611b0a565b6111a490886119fb565b6111ae9190611b16565b60f81b8382815181106111c3576111c36118c3565b60200101906001600160f81b031916908160001a9053506111e38161192b565b905061117a565b50505b9392505050565b60606000806000611204856105e0565b91945092509050600081600181111561121f5761121f6118d9565b1461126c5760405162461bcd60e51b815260206004820152601860248201527f496e76616c696420524c502062797465732076616c75652e00000000000000006044820152606401610205565b61127b856020015184846114ef565b95945050505050565b60606000825160026112969190611a0f565b67ffffffffffffffff8111156112ae576112ae6117bc565b6040519080825280601f01601f1916602001820160405280156112d8576020820181803683370190505b50905060005b83518110156113b65760048482815181106112fb576112fb6118c3565b01602001516001600160f81b031916901c82611318836002611a0f565b81518110611328576113286118c3565b60200101906001600160f81b031916908160001a9053506010848281518110611353576113536118c3565b0160200151611365919060f81c6119c0565b60f81b82611374836002611a0f565b61137f906001611905565b8151811061138f5761138f6118c3565b60200101906001600160f81b031916908160001a9053506113af8161192b565b90506112de565b5092915050565b60006020825110156113d157506020015190565b818060200190518101906101ac9190611b2a565b60006060602083600001511015611406576113ff83611598565b9050611412565b61140f836111f4565b90505b6111ed816113bd565b60606101ac61143a8360000151600081518110610ba057610ba06118c3565b611284565b60608251821061145e57506040805160208101909152600081526101ac565b6111ed83838486516114709190611918565b6115a3565b6000805b8084511180156114895750808351115b80156114da57508281815181106114a2576114a26118c3565b602001015160f81c60f81b6001600160f81b0319168482815181106114c9576114c96118c3565b01602001516001600160f81b031916145b156111ed576114e88161192b565b9050611479565b606060008267ffffffffffffffff81111561150c5761150c6117bc565b6040519080825280601f01601f191660200182016040528015611536576020820181803683370190505b50905080516000036115495790506111ed565b8484016020820160005b8581101561156b578281015182820152602001611553565b5060006001602087066020036101000a039050808251168119845116178252839450505050509392505050565b60606101ac826116f9565b6060816115b181601f611905565b10156115f05760405162461bcd60e51b815260206004820152600e60248201526d736c6963655f6f766572666c6f7760901b6044820152606401610205565b826115fb8382611905565b101561163a5760405162461bcd60e51b815260206004820152600e60248201526d736c6963655f6f766572666c6f7760901b6044820152606401610205565b6116448284611905565b845110156116885760405162461bcd60e51b8152602060048201526011602482015270736c6963655f6f75744f66426f756e647360781b6044820152606401610205565b6060821580156116a75760405191506000825260208201604052610a55565b6040519150601f8416801560200281840101858101878315602002848b0101015b818310156116e05780518352602092830192016116c8565b5050858452601f01601f19166040525050949350505050565b60606101ac8260200151600084600001516114ef565b60008060008060008060a0878903121561172857600080fd5b8635955060208701356001600160a01b038116811461174657600080fd5b94506040870135935060608701359250608087013567ffffffffffffffff8082111561177157600080fd5b818901915089601f83011261178557600080fd5b81358181111561179457600080fd5b8a60208285010111156117a657600080fd5b6020830194508093505050509295509295509295565b634e487b7160e01b600052604160045260246000fd5b600082601f8301126117e357600080fd5b813567ffffffffffffffff808211156117fe576117fe6117bc565b604051601f8301601f19908116603f01168101908282118183101715611826576118266117bc565b8160405283815286602085880101111561183f57600080fd5b836020870160208301376000602085830101528094505050505092915050565b6000806040838503121561187257600080fd5b823567ffffffffffffffff8082111561188a57600080fd5b611896868387016117d2565b935060208501359150808211156118ac57600080fd5b506118b9858286016117d2565b9150509250929050565b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052602160045260246000fd5b634e487b7160e01b600052601160045260246000fd5b808201808211156101ac576101ac6118ef565b818103818111156101ac576101ac6118ef565b60006001820161193d5761193d6118ef565b5060010190565b6000815160005b81811015611965576020818501810151868301520161194b565b50600093019283525090919050565b60006119896119838386611944565b84611944565b949350505050565b60ff81811683821601908111156101ac576101ac6118ef565b634e487b7160e01b600052601260045260246000fd5b600060ff8316806119d3576119d36119aa565b8060ff84160691505092915050565b60ff82811682821603908111156101ac576101ac6118ef565b600082611a0a57611a0a6119aa565b500490565b80820281158282048414176101ac576101ac6118ef565b600181815b80851115611a61578160001904821115611a4757611a476118ef565b80851615611a5457918102915b93841c9390800290611a2b565b509250929050565b600082611a78575060016101ac565b81611a85575060006101ac565b8160018114611a9b5760028114611aa557611ac1565b60019150506101ac565b60ff841115611ab657611ab66118ef565b50506001821b6101ac565b5060208310610133831016604e8410600b8410161715611ae4575081810a6101ac565b611aee8383611a26565b8060001904821115611b0257611b026118ef565b029392505050565b60006111ed8383611a69565b600082611b2557611b256119aa565b500690565b600060208284031215611b3c57600080fd5b505191905056fea26469706673582212204875324a0ffbec2ef4b8b54e737ba4f199bc66a7bbc669362262c64003f5eb4964736f6c63430008140033", + "balance": "0x0" + }, + "0xb2Bcd028F53637a4FC4E06C52d247F38f44cBe4d": { + "contractName": "LibVaultUtils", + "storage": {}, + "code": "0x7300000000000000000000000000000000000000003014608060405260043610620000735760003560e01c80632c6a56af1462000078578063634da63a14620000a257806378adc0d614620000ab578063881107d914620000e957806393522e3e146200012c578063c0619cc21462000145575b600080fd5b6200008f6200008936600462000567565b6200015c565b6040519081526020015b60405180910390f35b6200008f600a81565b818015620000b857600080fd5b50620000d0620000ca36600462000622565b62000205565b6040516001600160a01b03909116815260200162000099565b62000100620000fa366004620006e9565b62000265565b60408051825181526020808401516001600160a01b031690820152918101519082015260600162000099565b620001436200013d3660046200071c565b620003a6565b005b6200014362000156366004620007c8565b6200041a565b6040516304c68c7960e31b815260009083906001600160a01b0382169063263463c8906200018f908890600401620008bb565b602060405180830381865afa158015620001ad573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620001d39190620009d1565b91506001600160a01b038316620001fd576040516303f8a7d360e01b815260040160405180910390fd5b509392505050565b60006001600160a01b038416620002205762000220620009eb565b83838360405162000231906200052e565b6200023f9392919062000a01565b604051809103906000f0801580156200025c573d6000803e3d6000fd5b50949350505050565b6040805160608101825260008082526020820181905291810191909152336001600160a01b031663d0496d6a6040518163ffffffff1660e01b8152600401606060405180830381865afa158015620002c1573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620002e7919062000a6d565b6040818101519051633632b1fb60e11b8152600481019190915260248101859052600060448201529091506001600160a01b03831690636c6563f690606401602060405180830381865afa15801562000344573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200036a919062000ad5565b6001600160a01b031681602001516001600160a01b031614620003a057604051636659b9bb60e11b815260040160405180910390fd5b92915050565b6001600160a01b0382161580620003ce5750826001600160a01b0316826001600160a01b0316145b15620003ed5760405163def9481360e01b815260040160405180910390fd5b6001600160a01b03811662000415576040516303f8a7d360e01b815260040160405180910390fd5b505050565b82518251146200043d5760405163196e8a4160e31b815260040160405180910390fd5b600a82511115620004615760405163e4a4c1c760e01b815260040160405180910390fd5b8015620004ce5760005b8251811015620004c8578381815181106200048a576200048a62000afc565b6020026020010151600014620004b357604051634299323b60e11b815260040160405180910390fd5b80620004bf8162000b12565b9150506200046b565b50505050565b60005b8351811015620004c857838181518110620004f057620004f062000afc565b60200260200101516000036200051957604051634299323b60e11b815260040160405180910390fd5b80620005258162000b12565b915050620004d1565b610dcf8062000b3b83390190565b6001600160a01b03811681146200055257600080fd5b50565b803562000562816200053c565b919050565b6000806000606084860312156200057d57600080fd5b833567ffffffffffffffff8111156200059557600080fd5b84016101808187031215620005a957600080fd5b92506020840135620005bb816200053c565b91506040840135620005cd816200053c565b809150509250925092565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f1916810167ffffffffffffffff811182821017156200061a576200061a620005d8565b604052919050565b6000806000606084860312156200063857600080fd5b833562000645816200053c565b925060208481013562000658816200053c565b9250604085013567ffffffffffffffff808211156200067657600080fd5b818701915087601f8301126200068b57600080fd5b813581811115620006a057620006a0620005d8565b620006b4601f8201601f19168501620005ee565b91508082528884828501011115620006cb57600080fd5b80848401858401376000848284010152508093505050509250925092565b60008060408385031215620006fd57600080fd5b82359150602083013562000711816200053c565b809150509250929050565b6000806000606084860312156200073257600080fd5b8335620005a9816200053c565b600082601f8301126200075157600080fd5b8135602067ffffffffffffffff821115620007705762000770620005d8565b8160051b62000781828201620005ee565b92835284810182019282810190878511156200079c57600080fd5b83870192505b84831015620007bd57823582529183019190830190620007a2565b979650505050505050565b600080600060608486031215620007de57600080fd5b833567ffffffffffffffff80821115620007f757600080fd5b62000805878388016200073f565b945060208601359150808211156200081c57600080fd5b506200082b868287016200073f565b92505060408401358015158114620005cd57600080fd5b6000808335601e198436030181126200085a57600080fd5b830160208101925035905067ffffffffffffffff8111156200087b57600080fd5b8036038213156200088b57600080fd5b9250929050565b81835281816020850137506000828201602090810191909152601f909101601f19169091010190565b60208152813560208201526000620008d66020840162000555565b6001600160a01b0381166040840152506040830135606083015260608301356080830152620009086080840162000555565b6001600160a01b03811660a0840152506200092660a0840162000555565b6001600160a01b03811660c0840152506200094460c0840162000555565b6001600160a01b03811660e08401525061010060e08401358184015261012081850135818501526101409150808501358285015250620009878185018562000842565b91506101806101608181870152620009a56101a08701858562000892565b9350620009b58188018862000842565b878603601f19018489015293509050620007bd84848362000892565b600060208284031215620009e457600080fd5b5051919050565b634e487b7160e01b600052600160045260246000fd5b600060018060a01b038086168352602081861681850152606060408501528451915081606085015260005b8281101562000a4a5785810182015185820160800152810162000a2c565b50506000608082850101526080601f19601f830116840101915050949350505050565b60006060828403121562000a8057600080fd5b6040516060810181811067ffffffffffffffff8211171562000aa65762000aa6620005d8565b60405282518152602083015162000abd816200053c565b60208201526040928301519281019290925250919050565b60006020828403121562000ae857600080fd5b815162000af5816200053c565b9392505050565b634e487b7160e01b600052603260045260246000fd5b60006001820162000b3357634e487b7160e01b600052601160045260246000fd5b506001019056fe608060405260405162000dcf38038062000dcf833981016040819052620000269162000424565b828162000036828260006200004d565b50620000449050826200007f565b50505062000557565b6200005883620000f1565b600082511180620000665750805b156200007a5762000078838362000133565b505b505050565b7f7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f620000c160008051602062000d88833981519152546001600160a01b031690565b604080516001600160a01b03928316815291841660208301520160405180910390a1620000ee8162000162565b50565b620000fc8162000200565b6040516001600160a01b038216907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b90600090a250565b60606200015b838360405180606001604052806027815260200162000da86027913962000297565b9392505050565b6001600160a01b038116620001cd5760405162461bcd60e51b815260206004820152602660248201527f455243313936373a206e65772061646d696e20697320746865207a65726f206160448201526564647265737360d01b60648201526084015b60405180910390fd5b8060008051602062000d888339815191525b80546001600160a01b0319166001600160a01b039290921691909117905550565b6001600160a01b0381163b6200026f5760405162461bcd60e51b815260206004820152602d60248201527f455243313936373a206e657720696d706c656d656e746174696f6e206973206e60448201526c1bdd08184818dbdb9d1c9858dd609a1b6064820152608401620001c4565b807f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc620001df565b6060600080856001600160a01b031685604051620002b6919062000504565b600060405180830381855af49150503d8060008114620002f3576040519150601f19603f3d011682016040523d82523d6000602084013e620002f8565b606091505b5090925090506200030c8683838762000316565b9695505050505050565b606083156200038a57825160000362000382576001600160a01b0385163b620003825760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401620001c4565b508162000396565b6200039683836200039e565b949350505050565b815115620003af5781518083602001fd5b8060405162461bcd60e51b8152600401620001c4919062000522565b80516001600160a01b0381168114620003e357600080fd5b919050565b634e487b7160e01b600052604160045260246000fd5b60005b838110156200041b57818101518382015260200162000401565b50506000910152565b6000806000606084860312156200043a57600080fd5b6200044584620003cb565b92506200045560208501620003cb565b60408501519092506001600160401b03808211156200047357600080fd5b818601915086601f8301126200048857600080fd5b8151818111156200049d576200049d620003e8565b604051601f8201601f19908116603f01168101908382118183101715620004c857620004c8620003e8565b81604052828152896020848701011115620004e257600080fd5b620004f5836020830160208801620003fe565b80955050505050509250925092565b6000825162000518818460208701620003fe565b9190910192915050565b602081526000825180602084015262000543816040850160208701620003fe565b601f01601f19169190910160400192915050565b61082180620005676000396000f3fe60806040526004361061004e5760003560e01c80633659cfe6146100655780634f1ef286146100855780635c60da1b146100985780638f283970146100c9578063f851a440146100e95761005d565b3661005d5761005b6100fe565b005b61005b6100fe565b34801561007157600080fd5b5061005b6100803660046106b3565b610118565b61005b6100933660046106ce565b610155565b3480156100a457600080fd5b506100ad6101bc565b6040516001600160a01b03909116815260200160405180910390f35b3480156100d557600080fd5b5061005b6100e43660046106b3565b6101ed565b3480156100f557600080fd5b506100ad61020d565b61010661022e565b6101166101116102c3565b6102cd565b565b6101206102f1565b6001600160a01b0316330361014d5761014a81604051806020016040528060008152506000610324565b50565b61014a6100fe565b61015d6102f1565b6001600160a01b031633036101b4576101af8383838080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525060019250610324915050565b505050565b6101af6100fe565b60006101c66102f1565b6001600160a01b031633036101e2576101dd6102c3565b905090565b6101ea6100fe565b90565b6101f56102f1565b6001600160a01b0316330361014d5761014a8161034f565b60006102176102f1565b6001600160a01b031633036101e2576101dd6102f1565b6102366102f1565b6001600160a01b031633036101165760405162461bcd60e51b815260206004820152604260248201527f5472616e73706172656e745570677261646561626c6550726f78793a2061646d60448201527f696e2063616e6e6f742066616c6c6261636b20746f2070726f78792074617267606482015261195d60f21b608482015260a4015b60405180910390fd5b60006101dd6103a3565b3660008037600080366000845af43d6000803e8080156102ec573d6000f35b3d6000fd5b60007fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035b546001600160a01b0316919050565b61032d836103cb565b60008251118061033a5750805b156101af57610349838361040b565b50505050565b7f7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f6103786102f1565b604080516001600160a01b03928316815291841660208301520160405180910390a161014a81610437565b60007f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc610315565b6103d4816104e0565b6040516001600160a01b038216907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b90600090a250565b606061043083836040518060600160405280602781526020016107c560279139610574565b9392505050565b6001600160a01b03811661049c5760405162461bcd60e51b815260206004820152602660248201527f455243313936373a206e65772061646d696e20697320746865207a65726f206160448201526564647265737360d01b60648201526084016102ba565b807fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035b80546001600160a01b0319166001600160a01b039290921691909117905550565b6001600160a01b0381163b61054d5760405162461bcd60e51b815260206004820152602d60248201527f455243313936373a206e657720696d706c656d656e746174696f6e206973206e60448201526c1bdd08184818dbdb9d1c9858dd609a1b60648201526084016102ba565b807f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc6104bf565b6060600080856001600160a01b0316856040516105919190610775565b600060405180830381855af49150503d80600081146105cc576040519150601f19603f3d011682016040523d82523d6000602084013e6105d1565b606091505b50915091506105e2868383876105ec565b9695505050505050565b6060831561065b578251600003610654576001600160a01b0385163b6106545760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e747261637400000060448201526064016102ba565b5081610665565b610665838361066d565b949350505050565b81511561067d5781518083602001fd5b8060405162461bcd60e51b81526004016102ba9190610791565b80356001600160a01b03811681146106ae57600080fd5b919050565b6000602082840312156106c557600080fd5b61043082610697565b6000806000604084860312156106e357600080fd5b6106ec84610697565b9250602084013567ffffffffffffffff8082111561070957600080fd5b818601915086601f83011261071d57600080fd5b81358181111561072c57600080fd5b87602082850101111561073e57600080fd5b6020830194508093505050509250925092565b60005b8381101561076c578181015183820152602001610754565b50506000910152565b60008251610787818460208701610751565b9190910192915050565b60208152600082518060208401526107b0816040850160208701610751565b601f01601f1916919091016040019291505056fe416464726573733a206c6f772d6c6576656c2064656c65676174652063616c6c206661696c6564a264697066735822122013e4be7fbb9448379ca283101ef1037ca99a17f6ad00269fe32f79bcefab6e1864736f6c63430008140033b53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103416464726573733a206c6f772d6c6576656c2064656c65676174652063616c6c206661696c6564a2646970667358221220f7eab1ca665847bc4018294f96a153d69cce361a3d5f12cfd1bc2273590d44a364736f6c63430008140033", + "balance": "0x0" + }, + "0x455B9Bc4d78992D3c215AA37dEa16820d407b4c3": { + "contractName": "LibBridgeRetry", + "storage": {}, + "code": "0x73000000000000000000000000000000000000000030146080604052600080fdfea2646970667358221220c21ca915ccc921edec3de901a4d0348cf4bc5bff9797f582b0cf946ba041f74364736f6c63430008140033", + "balance": "0x0" + }, + "0xe1f32A7D3C6C23aA32B903E6518C5cEDa1233dE1": { + "contractName": "LibBridgeProcess", + "storage": {}, + "code": "0x73000000000000000000000000000000000000000030146080604052600080fdfea264697066735822122035fc1d40b735b2ee73e7108c8c67c328cd61e0193243acbff8377126b576539064736f6c63430008140033", + "balance": "0x0" + }, + "0x0000777700000000000000000000000000000006": { + "contractName": "ProxiedAddressManager", + "storage": {}, + "code": "0x608060405234801561001057600080fd5b50600436106100625760003560e01c8063656b06a414610067578063715018a6146100b75780638da5cb5b146100c1578063decd8e39146100d2578063e1c7392a146100e5578063f2fde38b146100ed575b600080fd5b61009b610075366004610466565b60009182526065602090815260408084209284529190529020546001600160a01b031690565b6040516001600160a01b03909116815260200160405180910390f35b6100bf610100565b005b6033546001600160a01b031661009b565b6100bf6100e03660046104a4565b610114565b6100bf6101d4565b6100bf6100fb3660046104d9565b6102ea565b610108610360565b61011260006103ba565b565b61011c610360565b6001600160a01b0381163b15801561013c57506001600160a01b03811633145b1561015a57604051630532024960e01b815260040160405180910390fd5b600083815260656020908152604080832085845282529182902080546001600160a01b038581166001600160a01b0319831681179093558451928352169181018290529091849186917fe41a6e8584d6e19a0dfc5f9331be4ebe61b5f025d45da164c9ca6ee9b837cea9910160405180910390a350505050565b600054610100900460ff16158080156101f45750600054600160ff909116105b8061020e5750303b15801561020e575060005460ff166001145b6102765760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b60648201526084015b60405180910390fd5b6000805460ff191660011790558015610299576000805461ff0019166101001790555b6102a161040c565b80156102e7576000805461ff0019169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b50565b6102f2610360565b6001600160a01b0381166103575760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b606482015260840161026d565b6102e7816103ba565b6033546001600160a01b031633146101125760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015260640161026d565b603380546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b600054610100900460ff166104335760405162461bcd60e51b815260040161026d906104fb565b610112600054610100900460ff1661045d5760405162461bcd60e51b815260040161026d906104fb565b610112336103ba565b6000806040838503121561047957600080fd5b50508035926020909101359150565b80356001600160a01b038116811461049f57600080fd5b919050565b6000806000606084860312156104b957600080fd5b83359250602084013591506104d060408501610488565b90509250925092565b6000602082840312156104eb57600080fd5b6104f482610488565b9392505050565b6020808252602b908201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960408201526a6e697469616c697a696e6760a81b60608201526080019056fea26469706673582212209632508c2a715b76d0a2d3aa58ee92c804730127c9ce52ca1746b6dd53e3493564736f6c63430008140033", + "balance": "0x0" + }, + "0x1000777700000000000000000000000000000006": { + "contractName": "AddressManagerProxy", + "storage": { + "0x0000000000000000000000000000000000000000000000000000000000000000": "0x0000000000000000000000000000000000000000000000000000000000000001", + "0x0000000000000000000000000000000000000000000000000000000000000033": "0x00000000000000000000000019b4f9c381c7927fe33d853e48b560141a380c44", + "0xb1e89ee2bb78a419041fe24e740013159340b56d268f604f33f3c055e32347b5": "0x0000000000000000000000001000777700000000000000000000000000000001", + "0x13f577b9913c89bd350f4a404ebd8d505e1c9a69978cbcc8529fdd540bc949f3": "0x0000000000000000000000001000777700000000000000000000000000000004", + "0xd38903d6274a6db84688a349e4b3b67ae5c236d486bf6a62bd09314bf30ba140": "0x0000000000000000000000001000777700000000000000000000000000000002", + "0xbafc6b13b2f0c6eb23ba53cc40dafc5b57926d1acd46063721f26d168d8ac8e6": "0x0000000000000000000000001000777700000000000000000000000000000008", + "0xc278a37e264ab267ad37b6ee48041a93f8cea8fcfcaf9b7fd59d772e0ec551f1": "0x0000000000000000000000001000777700000000000000000000000000000009", + "0x72e9081aff0e8fea1bb15ead8a2c76d8049574549467dd79a558ba6534aacfed": "0x0000000000000000000000001000777700000000000000000000000000000003", + "0x03daec7c59de2c9cb8db9482af6aa07e46780a7bf4f7aa548e6a50a0b38b544d": "0x0000000000000000000000001000777700000000000000000000000000000007", + "0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103": "0x113cE23c9e0cc50F4D41d7cE6DA02dCAFf8BFF85", + "0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc": "0x0000777700000000000000000000000000000006" + }, + "code": "0x60806040526004361061004e5760003560e01c80633659cfe6146100655780634f1ef286146100855780635c60da1b146100985780638f283970146100c9578063f851a440146100e95761005d565b3661005d5761005b6100fe565b005b61005b6100fe565b34801561007157600080fd5b5061005b6100803660046106b3565b610118565b61005b6100933660046106ce565b610155565b3480156100a457600080fd5b506100ad6101bc565b6040516001600160a01b03909116815260200160405180910390f35b3480156100d557600080fd5b5061005b6100e43660046106b3565b6101ed565b3480156100f557600080fd5b506100ad61020d565b61010661022e565b6101166101116102c3565b6102cd565b565b6101206102f1565b6001600160a01b0316330361014d5761014a81604051806020016040528060008152506000610324565b50565b61014a6100fe565b61015d6102f1565b6001600160a01b031633036101b4576101af8383838080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525060019250610324915050565b505050565b6101af6100fe565b60006101c66102f1565b6001600160a01b031633036101e2576101dd6102c3565b905090565b6101ea6100fe565b90565b6101f56102f1565b6001600160a01b0316330361014d5761014a8161034f565b60006102176102f1565b6001600160a01b031633036101e2576101dd6102f1565b6102366102f1565b6001600160a01b031633036101165760405162461bcd60e51b815260206004820152604260248201527f5472616e73706172656e745570677261646561626c6550726f78793a2061646d60448201527f696e2063616e6e6f742066616c6c6261636b20746f2070726f78792074617267606482015261195d60f21b608482015260a4015b60405180910390fd5b60006101dd6103a3565b3660008037600080366000845af43d6000803e8080156102ec573d6000f35b3d6000fd5b60007fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035b546001600160a01b0316919050565b61032d836103cb565b60008251118061033a5750805b156101af57610349838361040b565b50505050565b7f7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f6103786102f1565b604080516001600160a01b03928316815291841660208301520160405180910390a161014a81610437565b60007f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc610315565b6103d4816104e0565b6040516001600160a01b038216907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b90600090a250565b606061043083836040518060600160405280602781526020016107c560279139610574565b9392505050565b6001600160a01b03811661049c5760405162461bcd60e51b815260206004820152602660248201527f455243313936373a206e65772061646d696e20697320746865207a65726f206160448201526564647265737360d01b60648201526084016102ba565b807fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035b80546001600160a01b0319166001600160a01b039290921691909117905550565b6001600160a01b0381163b61054d5760405162461bcd60e51b815260206004820152602d60248201527f455243313936373a206e657720696d706c656d656e746174696f6e206973206e60448201526c1bdd08184818dbdb9d1c9858dd609a1b60648201526084016102ba565b807f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc6104bf565b6060600080856001600160a01b0316856040516105919190610775565b600060405180830381855af49150503d80600081146105cc576040519150601f19603f3d011682016040523d82523d6000602084013e6105d1565b606091505b50915091506105e2868383876105ec565b9695505050505050565b6060831561065b578251600003610654576001600160a01b0385163b6106545760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e747261637400000060448201526064016102ba565b5081610665565b610665838361066d565b949350505050565b81511561067d5781518083602001fd5b8060405162461bcd60e51b81526004016102ba9190610791565b80356001600160a01b03811681146106ae57600080fd5b919050565b6000602082840312156106c557600080fd5b61043082610697565b6000806000604084860312156106e357600080fd5b6106ec84610697565b9250602084013567ffffffffffffffff8082111561070957600080fd5b818601915086601f83011261071d57600080fd5b81358181111561072c57600080fd5b87602082850101111561073e57600080fd5b6020830194508093505050509250925092565b60005b8381101561076c578181015183820152602001610754565b50506000910152565b60008251610787818460208701610751565b9190910192915050565b60208152600082518060208401526107b0816040850160208701610751565b601f01601f1916919091016040019291505056fe416464726573733a206c6f772d6c6576656c2064656c65676174652063616c6c206661696c6564a264697066735822122013e4be7fbb9448379ca283101ef1037ca99a17f6ad00269fe32f79bcefab6e1864736f6c63430008140033", + "balance": "0x0" + }, + "0x0000777700000000000000000000000000000001": { + "contractName": "ProxiedTaikoL2", + "storage": {}, + "code": "0x608060405234801561001057600080fd5b50600436106101375760003560e01c8063715018a6116100b8578063bdd6bc361161007c578063bdd6bc36146102f3578063c7b9690814610306578063da69d3db14610320578063dac5df7814610333578063f2fde38b1461033c578063f535bd561461034f57600080fd5b8063715018a61461029b5780638da5cb5b146102a35780639ee512f2146102b4578063a7e022d1146102cd578063a86f9d9e146102e057600080fd5b80634e755573116100ff5780634e755573146101d6578063539b8ade14610218578063591aad8a146102435780635c82e9c2146102755780636c6563f61461028857600080fd5b80630599d2941461013c5780630652b57a1461016257806310da37381461017757806323ac71361461019e5780633ab76e9f146101b1575b600080fd5b61014f61014a36600461171c565b610369565b6040519081526020015b60405180910390f35b61017561017036600461174c565b6103b7565b005b61014f7f92954368afd3caa1f3ce3ead0069c1af414054aefe1ef9aeacc1bf426222ce3881565b61014f6101ac36600461171c565b610430565b6097546001600160a01b03165b6040516001600160a01b039091168152602001610159565b6101de6104aa565b6040805182516001600160801b031681526020808401516001600160401b0316908201529181015163ffffffff1690820152606001610159565b60cd5461022b906001600160401b031681565b6040516001600160401b039091168152602001610159565b610256610251366004611769565b61050d565b6040805160ff9094168452602084019290925290820152606001610159565b61017561028336600461179f565b610748565b6101be6102963660046117f0565b610b04565b610175610b1b565b6065546001600160a01b03166101be565b6101be71777735367b36bc9b61c50022d9d0700db4ec81565b61014f6102db366004611839565b610b2f565b6101be6102ee36600461186c565b610b54565b61014f61030136600461171c565b610b6a565b60cd5461022b90600160401b90046001600160401b031681565b61017561032e36600461188f565b610bb5565b61014f60cb5481565b61017561034a36600461174c565b610e1e565b60cd5461022b90600160801b90046001600160401b031681565b6000806001600160401b038316156103815782610395565b60cd54600160401b90046001600160401b03165b6001600160401b0316600090815260ca60205260409020600101549392505050565b6103bf610e97565b6001600160a01b0381166103e657604051634d084d8560e11b815260040160405180910390fd5b609780546001600160a01b0319166001600160a01b0383169081179091556040517f399ded90cb5ed8d89ef7e76ff4af65c373f06d3bf5d7eef55f4228e7b702a18b90600090a250565b600043826001600160401b03161061044a57506000919050565b43826001600160401b03161080156104765750610469610100436118eb565b826001600160401b031610155b1561048957506001600160401b03164090565b506001600160401b0316600090815260c9602052604090205490565b919050565b6040805160608101825260008082526020820181905291810191909152506040805160608101825260cc546001600160801b0381168252600160801b81046001600160401b03166020830152600160c01b900463ffffffff169181019190915290565b60008060008360ff1660011415801561052a57508360ff16600214155b156105485760405163bcd2d90d60e01b815260040160405180910390fd5b8360ff16600114610579577fc6047f9441ed7d6d3045406e95c07cd85c778e4b8cef3ca7abac09b95c709ee561059b565b7f79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f817985b915060008460ff166001146105d0577fad77eceea844778cb4376153fc8f06f12f1695df4585bf75bfb17ec19ce908186105f2565b7fb4a95509ce05fe8d45987859a067780d16a367c0e2cacf79cd301b93fb7179405b905060008560ff16600114610627577f71620584f61c57e688bbd3fd7a39a036e588d962c4c830f3dacbc15c917e02f2610649565b7f45b59254b0320fd853f3f38ac574999e91bd75fd5e6cab9c22c5e71fc6d276e45b82880192831001905060ff86166001036106835761067c8282600170014551231950b75fc4402da1732fc9bebe19610ef1565b92506106f2565b6106cb7f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a16106c68484600170014551231950b75fc4402da1732fc9bebe19610ef1565b610f40565b90925090506106ef8282600170014551231950b75fc4402da1732fc9bebe19610ef1565b92505b7f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a083111561073f576107368370014551231950b75fc4402da1732fc9bebe196118eb565b92506001851894505b50509250925092565b600054610100900460ff16158080156107685750600054600160ff909116105b806107825750303b158015610782575060005460ff166001145b6107ea5760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b60648201526084015b60405180910390fd5b6000805460ff19166001179055801561080d576000805461ff0019166101001790555b600146111580610821575063ffffffff4610155b1561083f576040516306cffa2760e01b815260040160405180910390fd5b600143111561086157604051635a0f9e4160e11b815260040160405180910390fd5b61087160408301602084016118fe565b63ffffffff1615610a6057610889602083018361171c565b6001600160401b031615806108b457506108a9606083016040840161171c565b6001600160401b0316155b806108d557506108ca608083016060840161171c565b6001600160401b0316155b806108f657506108eb60a083016080840161171c565b6001600160401b0316155b1561091457604051639cc448b560e01b815260040160405180910390fd5b60008061095c61092a606086016040870161171c565b610937602087018761171c565b610947608088016060890161171c565b61095760a0890160808a0161171c565b610f5f565b91509150816001600160801b03166000148061098857506001600160401b036001600160801b03831610155b8061099a57506001600160801b038116155b156109b857604051639cc448b560e01b815260040160405180910390fd5b60cc80546001600160401b038416600160801b026001600160c01b03199091166001600160801b038416171790556109f660408501602086016118fe565b60cc805463ffffffff92909216600160c01b0263ffffffff60c01b199092169190911790556002610a2d606086016040870161171c565b610a37919061192f565b60cd60106101000a8154816001600160401b0302191690836001600160401b0316021790555050505b60cd805467ffffffffffffffff1916426001600160401b0316179055610a858361105e565b610a8e43611077565b5060cb554315610ab9576000610aa56001436118eb565b600081815260c96020526040902090409055505b8015610aff576000805461ff0019169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b505050565b6000610b1184848461110a565b90505b9392505050565b610b23610e97565b610b2d60006111be565b565b6000610b4c610b3c6104aa565b846001600160401b031684611210565b509392505050565b6000610b6146848461110a565b90505b92915050565b6000806001600160401b03831615610b825782610b96565b60cd54600160401b90046001600160401b03165b6001600160401b0316600090815260ca60205260409020549392505050565b3371777735367b36bc9b61c50022d9d0700db4ec14610be757604051636494e9f760e01b815260040160405180910390fd5b6000610bf46001436118eb565b90508040600080610c0484611077565b915091508160cb5414610c385760cb54604051636340d9fb60e11b81526004810191909152602481018390526044016107e1565b60cb819055600084815260c96020908152604080832086905560cd80546fffffffffffffffff00000000000000001916600160401b6001600160401b038c1690810291909117909155815180830183528c81528084018c815282865260ca8552948390209051815593516001949094019390935580518b81529182018a90527e4ce985b8852a486571d0545799251fd671adcf33b7854a5f0f6a6a2431a555910160405180910390a2600080610cec6104aa565b9050806040015163ffffffff16600014610d505760cd54610d22908290610d1c906001600160401b0316426118eb565b89611210565b60cd80546001600160401b03909216600160801b0267ffffffffffffffff60801b1990921691909117905591505b814814610d8357604051634083acad60e01b81526001600160401b038084166004830152481660248201526044016107e1565b60cd80546001600160401b0342811667ffffffffffffffff19909216821790925560408051438416815292851660208401524563ffffffff908116848301526060840192909252608083018890524460a08401524160c08401524690911660e0830152517ff5e89a4a67ffebdbc23df567479d3096c1dba4169c6bbf20ffc6b24d7f6e6e70918190036101000190a150505050505050505050565b610e26610e97565b6001600160a01b038116610e8b5760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b60648201526084016107e1565b610e94816111be565b50565b6065546001600160a01b03163314610b2d5760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657260448201526064016107e1565b600060405160408152602080820152602060408201528460608201528560808201528360a08201528260c082015260208160e08360056107d05a03fa610f3657600080fd5b5195945050505050565b6000806000198385098385029250828110838203039150509250929050565b600080856001600160401b0316600003610f7b57610f7b611955565b6000610f8860028861192f565b9050610fa66001600160401b038816680755bf798b4a1bf1e461196b565b9250610fc5610fc084886001600160401b031684896112ad565b61136c565b91506000610fd5848484896112ad565b90506000610fef858585610fea8b6002611985565b6112ad565b9050600082611000836127106119b0565b61100a91906119c7565b9050806001600160401b0316876001600160401b03161461105157604051631530943760e11b81526001600160401b038089166004830152821660248201526044016107e1565b5050505094509492505050565b6110666113d9565b61106e611408565b610e9481611437565b6000806110826116e5565b60005b60ff811080156110985750806001018510155b156110ca576000198186030180408360ff830661010081106110bc576110bc6119db565b602002015250600101611085565b5046611fe0820152612000812092508340816110e760ff876119f1565b61010081106110f8576110f86119db565b60200201526120009020919391925050565b60975460405163195ac1a960e21b815260048101859052602481018490526000916001600160a01b03169063656b06a490604401602060405180830381865afa15801561115b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061117f9190611a05565b90508115801561119657506001600160a01b038116155b15610b1457604051631467050360e21b815260048101859052602481018490526044016107e1565b606580546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b6000806000856040015163ffffffff1685029050600061125f828663ffffffff1660cd60109054906101000a90046001600160401b03166001600160401b03160161148090919063ffffffff16565b90506112748282036001600160401b03611496565b9250505061129685602001516001600160401b031686600001518360006112ad565b9150816000036112a557600191505b935093915050565b60006001600160801b038516158015906112cf57506001600160801b03841615155b6112db576112db611955565b60006001600160401b038316156112f257826112f5565b60015b9050600061130c856001600160401b0316886114ab565b9050600061132c61131d8488611a22565b6001600160401b0316896114ab565b90506001600160801b0387166001600160401b03841661134c84846118eb565b61135691906119c7565b61136091906119c7565b98975050505050505050565b60006001600160801b038211156113d55760405162461bcd60e51b815260206004820152602760248201527f53616665436173743a2076616c756520646f65736e27742066697420696e20316044820152663238206269747360c81b60648201526084016107e1565b5090565b600054610100900460ff166114005760405162461bcd60e51b81526004016107e190611a49565b610b2d6114fd565b600054610100900460ff1661142f5760405162461bcd60e51b81526004016107e190611a49565b610b2d61152a565b6001600160a01b03811661145e57604051634d084d8560e11b815260040160405180910390fd5b609780546001600160a01b0319166001600160a01b0392909216919091179055565b600081831161148f5781610b61565b5090919050565b60008183116114a55782610b61565b50919050565b6000806114c16001600160801b038416856119b0565b9050680755bf798b4a1bf1e481106114ec5760405163576ff4f160e01b815260040160405180910390fd5b6114f58161155a565b949350505050565b600054610100900460ff166115245760405162461bcd60e51b81526004016107e190611a49565b60018055565b600054610100900460ff166115515760405162461bcd60e51b81526004016107e190611a49565b610b2d336111be565b6000680248ce36a70cb26b3e19821361157557506000919050565b680755bf798b4a1bf1e5821261159e57604051631a93c68960e11b815260040160405180910390fd5b6503782dace9d9604e83901b059150600060606bb17217f7d1cf79abc9e3b39884821b056001605f1b01901d6bb17217f7d1cf79abc9e3b39881029093036c240c330e9fb2d9cbaf0fd5aafb1981018102606090811d6d0277594991cfc85f6e2461837cd9018202811d6d1a521255e34f6a5061b25ef1c9c319018202811d6db1bbb201f443cf962f1a1d3db4a5018202811d6e02c72388d9f74f51a9331fed693f1419018202811d6e05180bb14799ab47a8a8cb2a527d57016d02d16720577bd19bf614176fe9ea6c10fe68e7fd37d0007b713f765084018402831d9081019084016d01d3967ed30fc4f89c02bab5708119010290911d6e0587f503bb6ea29d25fcb740196450019091026d360d7aeea093263ecc6e0ecb291760621b010574029d9dc38563c32e5c2f6dc192ee70ef65f9978af30260c3939093039290921c92915050565b604051806120000160405280610100906020820280368337509192915050565b80356001600160401b03811681146104a557600080fd5b60006020828403121561172e57600080fd5b610b6182611705565b6001600160a01b0381168114610e9457600080fd5b60006020828403121561175e57600080fd5b8135610b1481611737565b6000806040838503121561177c57600080fd5b82359150602083013560ff8116811461179457600080fd5b809150509250929050565b60008082840360c08112156117b357600080fd5b83356117be81611737565b925060a0601f19820112156117d257600080fd5b506020830190509250929050565b803580151581146104a557600080fd5b60008060006060848603121561180557600080fd5b833592506020840135915061181c604085016117e0565b90509250925092565b803563ffffffff811681146104a557600080fd5b6000806040838503121561184c57600080fd5b61185583611705565b915061186360208401611825565b90509250929050565b6000806040838503121561187f57600080fd5b82359150611863602084016117e0565b600080600080608085870312156118a557600080fd5b84359350602085013592506118bc60408601611705565b91506118ca60608601611825565b905092959194509250565b634e487b7160e01b600052601160045260246000fd5b81810381811115610b6457610b646118d5565b60006020828403121561191057600080fd5b610b6182611825565b634e487b7160e01b600052601260045260246000fd5b60006001600160401b038084168061194957611949611919565b92169190910492915050565b634e487b7160e01b600052600160045260246000fd5b60006001600160801b038084168061194957611949611919565b6001600160401b038181168382160280821691908281146119a8576119a86118d5565b505092915050565b8082028115828204841417610b6457610b646118d5565b6000826119d6576119d6611919565b500490565b634e487b7160e01b600052603260045260246000fd5b600082611a0057611a00611919565b500690565b600060208284031215611a1757600080fd5b8151610b1481611737565b6001600160401b03818116838216019080821115611a4257611a426118d5565b5092915050565b6020808252602b908201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960408201526a6e697469616c697a696e6760a81b60608201526080019056fea26469706673582212205f4efdbc77034498385a78f6fb0b8114f654cc25350f8d3ca6d3701f54f91fd464736f6c63430008140033", + "balance": "0x0" + }, + "0x1000777700000000000000000000000000000001": { + "contractName": "TaikoL2Proxy", + "storage": { + "0x00000000000000000000000000000000000000000000000000000000000000cb": "0x39d135ad4110ebf27f74d4b2e044581f2a2c91345cd1f81f6c0f3ab5e769f35f", + "0x00000000000000000000000000000000000000000000000000000000000000cc": "0x000000000028b0aa000000019fe2e7a60000001532d76dedb5e5af7fbea79f5e", + "0x00000000000000000000000000000000000000000000000000000000000000cd": "0x00000000000000000000000241ed2e8800000000000000000000000065001f60", + "0x0000000000000000000000000000000000000000000000000000000000000097": "0x0000000000000000000000001000777700000000000000000000000000000006", + "0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103": "0x113cE23c9e0cc50F4D41d7cE6DA02dCAFf8BFF85", + "0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc": "0x0000777700000000000000000000000000000001" + }, + "code": "0x60806040526004361061004e5760003560e01c80633659cfe6146100655780634f1ef286146100855780635c60da1b146100985780638f283970146100c9578063f851a440146100e95761005d565b3661005d5761005b6100fe565b005b61005b6100fe565b34801561007157600080fd5b5061005b6100803660046106b3565b610118565b61005b6100933660046106ce565b610155565b3480156100a457600080fd5b506100ad6101bc565b6040516001600160a01b03909116815260200160405180910390f35b3480156100d557600080fd5b5061005b6100e43660046106b3565b6101ed565b3480156100f557600080fd5b506100ad61020d565b61010661022e565b6101166101116102c3565b6102cd565b565b6101206102f1565b6001600160a01b0316330361014d5761014a81604051806020016040528060008152506000610324565b50565b61014a6100fe565b61015d6102f1565b6001600160a01b031633036101b4576101af8383838080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525060019250610324915050565b505050565b6101af6100fe565b60006101c66102f1565b6001600160a01b031633036101e2576101dd6102c3565b905090565b6101ea6100fe565b90565b6101f56102f1565b6001600160a01b0316330361014d5761014a8161034f565b60006102176102f1565b6001600160a01b031633036101e2576101dd6102f1565b6102366102f1565b6001600160a01b031633036101165760405162461bcd60e51b815260206004820152604260248201527f5472616e73706172656e745570677261646561626c6550726f78793a2061646d60448201527f696e2063616e6e6f742066616c6c6261636b20746f2070726f78792074617267606482015261195d60f21b608482015260a4015b60405180910390fd5b60006101dd6103a3565b3660008037600080366000845af43d6000803e8080156102ec573d6000f35b3d6000fd5b60007fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035b546001600160a01b0316919050565b61032d836103cb565b60008251118061033a5750805b156101af57610349838361040b565b50505050565b7f7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f6103786102f1565b604080516001600160a01b03928316815291841660208301520160405180910390a161014a81610437565b60007f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc610315565b6103d4816104e0565b6040516001600160a01b038216907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b90600090a250565b606061043083836040518060600160405280602781526020016107c560279139610574565b9392505050565b6001600160a01b03811661049c5760405162461bcd60e51b815260206004820152602660248201527f455243313936373a206e65772061646d696e20697320746865207a65726f206160448201526564647265737360d01b60648201526084016102ba565b807fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035b80546001600160a01b0319166001600160a01b039290921691909117905550565b6001600160a01b0381163b61054d5760405162461bcd60e51b815260206004820152602d60248201527f455243313936373a206e657720696d706c656d656e746174696f6e206973206e60448201526c1bdd08184818dbdb9d1c9858dd609a1b60648201526084016102ba565b807f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc6104bf565b6060600080856001600160a01b0316856040516105919190610775565b600060405180830381855af49150503d80600081146105cc576040519150601f19603f3d011682016040523d82523d6000602084013e6105d1565b606091505b50915091506105e2868383876105ec565b9695505050505050565b6060831561065b578251600003610654576001600160a01b0385163b6106545760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e747261637400000060448201526064016102ba565b5081610665565b610665838361066d565b949350505050565b81511561067d5781518083602001fd5b8060405162461bcd60e51b81526004016102ba9190610791565b80356001600160a01b03811681146106ae57600080fd5b919050565b6000602082840312156106c557600080fd5b61043082610697565b6000806000604084860312156106e357600080fd5b6106ec84610697565b9250602084013567ffffffffffffffff8082111561070957600080fd5b818601915086601f83011261071d57600080fd5b81358181111561072c57600080fd5b87602082850101111561073e57600080fd5b6020830194508093505050509250925092565b60005b8381101561076c578181015183820152602001610754565b50506000910152565b60008251610787818460208701610751565b9190910192915050565b60208152600082518060208401526107b0816040850160208701610751565b601f01601f1916919091016040019291505056fe416464726573733a206c6f772d6c6576656c2064656c65676174652063616c6c206661696c6564a264697066735822122013e4be7fbb9448379ca283101ef1037ca99a17f6ad00269fe32f79bcefab6e1864736f6c63430008140033", + "balance": "0x0" + }, + "0x0000777700000000000000000000000000000004": { + "contractName": "ProxiedBridge", + "storage": {}, + "code": "0x60806040526004361061012e5760003560e01c8063620c23fb116100ab578063a86f9d9e1161006f578063a86f9d9e14610354578063ce70f39b14610374578063d0496d6a14610394578063ec9b312114610403578063f21be36f14610423578063f2fde38b1461044357600080fd5b8063620c23fb146102c15780636c6563f6146102e1578063715018a6146103015780638da5cb5b14610316578063a4444efd1461033457600080fd5b80634f5f9772116100f25780634f5f9772146101f45780635075a9d414610234578063540be6a3146102615780635d0bd98614610281578063606b5b74146102a157600080fd5b80630652b57a1461013a57806319ab453c1461015c578063263463c81461017c5780633ab76e9f146101af5780634c1888bc146101e157600080fd5b3661013557005b600080fd5b34801561014657600080fd5b5061015a610155366004612a0c565b610463565b005b34801561016857600080fd5b5061015a610177366004612a0c565b6104dc565b34801561018857600080fd5b5061019c610197366004612a42565b6105f4565b6040519081526020015b60405180910390f35b3480156101bb57600080fd5b506097546001600160a01b03165b6040516001600160a01b0390911681526020016101a6565b61019c6101ef366004612a42565b61060d565b34801561020057600080fd5b5061022461020f366004612a76565b600090815260cd602052604090205460ff1690565b60405190151581526020016101a6565b34801561024057600080fd5b5061025461024f366004612a76565b61063b565b6040516101a69190612ac7565b34801561026d57600080fd5b5061022461027c366004612a76565b610646565b34801561028d57600080fd5b5061022461029c366004612a76565b610652565b3480156102ad57600080fd5b5061019c6102bc366004612a76565b610665565b3480156102cd57600080fd5b5061015a6102dc366004612b1d565b610670565b3480156102ed57600080fd5b506101c96102fc366004612b93565b610696565b34801561030d57600080fd5b5061015a6106ad565b34801561032257600080fd5b506065546001600160a01b03166101c9565b34801561034057600080fd5b5061022461034f366004612bcc565b6106c1565b34801561036057600080fd5b506101c961036f366004612c1e565b6106d9565b34801561038057600080fd5b5061022461038f366004612bcc565b6106e6565b3480156103a057600080fd5b50604080516060808201835260008083526020808401829052928401528251808201845260ca5480825260cb546001600160a01b0390811683860190815260cc5493870193845286519283525116938101939093525192820192909252016101a6565b34801561040f57600080fd5b5061015a61041e366004612b1d565b6106f5565b34801561042f57600080fd5b5061015a61043e366004612c4e565b61070d565b34801561044f57600080fd5b5061015a61045e366004612a0c565b61072b565b61046b6107a4565b6001600160a01b03811661049257604051634d084d8560e11b815260040160405180910390fd5b609780546001600160a01b0319166001600160a01b0383169081179091556040517f399ded90cb5ed8d89ef7e76ff4af65c373f06d3bf5d7eef55f4228e7b702a18b90600090a250565b600054610100900460ff16158080156104fc5750600054600160ff909116105b806105165750303b158015610516575060005460ff166001145b61057e5760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b60648201526084015b60405180910390fd5b6000805460ff1916600117905580156105a1576000805461ff0019166101001790555b6105aa826107fe565b80156105f0576000805461ff0019169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b5050565b600061060761060283612da4565b610817565b92915050565b6000610617610847565b61062b60c93061062685612da4565b6108a0565b905061063660018055565b919050565b600061060782610b71565b60006106073083610b9c565b600061065e3083610c7d565b5092915050565b600061060782610d06565b610678610847565b61068860c9308585856001610d41565b61069160018055565b505050565b60006106a3848484610fbe565b90505b9392505050565b6106b56107a4565b6106bf6000611072565b565b60006106d030868686866110c4565b95945050505050565b60006106a6468484610fbe565b60006106d03086868686611227565b6106fd610847565b61068860c93085858560016114ac565b610715610847565b61072260c930848461197f565b6105f060018055565b6107336107a4565b6001600160a01b0381166107985760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b6064820152608401610575565b6107a181611072565b50565b6065546001600160a01b031633146106bf5760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610575565b610806611b55565b61080e611b84565b6107a181611bb3565b60008160405160200161082a9190612eea565b604051602081830303815290604052805190602001209050919050565b6002600154036108995760405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c006044820152606401610575565b6002600155565b60808101516000906001600160a01b03166108ce576040516398fc91f160e01b815260040160405180910390fd5b6000806108df858560600151610c7d565b915091508115806108f35750468460600151145b156109115760405163e822b48d60e01b815260040160405180910390fd5b60a08401516001600160a01b031615806109405750806001600160a01b03168460a001516001600160a01b0316145b1561095e5760405163b9ad6a0f60e01b815260040160405180910390fd5b60008461010001518560e001516109759190612fed565b905034811461099757604051632609a19760e21b815260040160405180910390fd5b604051635437cecf60e11b81526000906001600160a01b0388169063a86f9d9e906109c790600190600401613000565b602060405180830381865afa1580156109e4573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a08919061301f565b9050610a1d6001600160a01b03821683611bfc565b8754886000610a2b8361303c565b909155508652336020870152466040870152610a4686610817565b604051635437cecf60e11b81529095506001600160a01b0388169063a86f9d9e90610a7690600090600401613055565b602060405180830381865afa158015610a93573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ab7919061301f565b6001600160a01b03166366ca2bc0866040518263ffffffff1660e01b8152600401610ae491815260200190565b6020604051808303816000875af1158015610b03573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b279190613077565b50847f238646a410b383b664b8d2fe57d2895c1ecd3464a3159cae73a93a9f21a4335587604051610b589190612eea565b60405180910390a2505050509392505050565b60018055565b600080610b7d83610d06565b8054909150806003811115610b9457610b94612a8f565b949350505050565b604051635437cecf60e11b81526000906001600160a01b0384169063a86f9d9e90610bcb908490600401613055565b602060405180830381865afa158015610be8573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c0c919061301f565b604051631933b5e360e11b8152306004820152602481018490526001600160a01b0391909116906332676bc690604401602060405180830381865afa158015610c59573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906106a69190613090565b600080836001600160a01b0316636c6563f68460016040518363ffffffff1660e01b8152600401610caf9291906130ad565b602060405180830381865afa158015610ccc573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610cf0919061301f565b6001600160a01b03811615159590945092505050565b60006040518060400160405280600e81526020016d4d4553534147455f53544154555360901b8152508260405160200161082a9291906130cc565b6000610d4f61060286612da4565b600081815260048901602052604090205490915060ff1615610d845760405163bd7e9a9d60e01b815260040160405180910390fd5b818015610d9f5750610d9d868287606001358787611227565b155b15610dbd5760405163498b0b1d60e01b815260040160405180910390fd5b600081815260048089016020526040808320805460ff191660019081179091559051635437cecf60e11b81526001600160a01b038a169263a86f9d9e92610e0692909101613000565b602060405180830381865afa158015610e23573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e47919061301f565b90506001600160a01b03811615610ebc5760405163ba0bbd9560e01b815230600482015260e087013560248201526001600160a01b0382169063ba0bbd9590604401600060405180830381600087803b158015610ea357600080fd5b505af1158015610eb7573d6000803e3d6000fd5b505050505b610ee6631953216560e11b610ed76040890160208a01612a0c565b6001600160a01b031690611cb2565b15610f6257610efb6040870160208801612a0c565b6001600160a01b03166332a642ca8760e00135886040518363ffffffff1660e01b8152600401610f2b919061315c565b6000604051808303818588803b158015610f4457600080fd5b505af1158015610f58573d6000803e3d6000fd5b5050505050610f89565b610f8960e0870135610f7a60a0890160808a01612a0c565b6001600160a01b031690611bfc565b60405182907fc6fbc1fa0145a394c9c414b2ae7bd634eb50dd888938bcd75692ae427b680fa290600090a25050505050505050565b60975460405163195ac1a960e21b815260048101859052602481018490526000916001600160a01b03169063656b06a490604401602060405180830381865afa15801561100f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611033919061301f565b90508115801561104a57506001600160a01b038116155b156106a657604051631467050360e21b81526004810185905260248101849052604401610575565b606580546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b600080866001600160a01b0316636c6563f68660006040518363ffffffff1660e01b81526004016110f69291906130ad565b602060405180830381865afa158015611113573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611137919061301f565b604051635437cecf60e11b81529091506001600160a01b0388169063a86f9d9e9061116790600090600401613055565b602060405180830381865afa158015611184573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111a8919061301f565b6001600160a01b0316635221f61386838988886040518663ffffffff1660e01b81526004016111db959493929190613262565b602060405180830381865afa1580156111f8573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061121c9190613090565b979650505050505050565b60004684036112495760405163e822b48d60e01b815260040160405180910390fd5b600085900361126b5760405163a6407c9360e01b815260040160405180910390fd5b60006112798385018561332b565b604051635437cecf60e11b8152647461696b6f60d81b60048201526000602482018190529192506001600160a01b0389169063a86f9d9e90604401602060405180830381865afa1580156112d1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112f5919061301f565b82516101000151604051635eeb5e1b60e11b81526001600160401b0390911660048201526001600160a01b03919091169063bdd6bc3690602401602060405180830381865afa15801561134c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906113709190613077565b90508015806113895750815161138590611d2b565b8114155b15611399576000925050506106d0565b815160600151604051633632b1fb60e11b8152738a9f79C3dc6158E58484ceEd46d93c4B0bAD082491636892abdc916001600160a01b038c1690636c6563f6906113ea908c906000906004016130ad565b602060405180830381865afa158015611407573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061142b919061301f565b6114348b610d06565b602087015160405160e086901b6001600160e01b031916815261145f949392916003916004016134cf565b602060405180830381865af415801561147c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906114a09190613090565b98975050505050505050565b6101208401351580156114e057506114ca60a0850160808601612a0c565b6001600160a01b0316336001600160a01b031614155b156114fe5760405163398b635960e21b815260040160405180910390fd5b468460600135146115225760405163e822b48d60e01b815260040160405180910390fd5b600061153061060286612da4565b9050600061153d82610b71565b600381111561154e5761154e612a8f565b1461156c57604051630cfafbf960e01b815260040160405180910390fd5b6000866001600160a01b0316636c6563f6876040013560006040518363ffffffff1660e01b81526004016115a19291906130ad565b602060405180830381865afa1580156115be573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906115e2919061301f565b90508280156116d45750604051635437cecf60e11b81526001600160a01b0388169063a86f9d9e9061161990600090600401613055565b602060405180830381865afa158015611636573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061165a919061301f565b6001600160a01b0316635221f6138760400135838589896040518663ffffffff1660e01b8152600401611691959493929190613262565b602060405180830381865afa1580156116ae573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906116d29190613090565b155b156116f2576040516314504c7360e31b815260040160405180910390fd5b604051635437cecf60e11b81526000906001600160a01b0389169063a86f9d9e9061172290600190600401613000565b602060405180830381865afa15801561173f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611763919061301f565b90506001600160a01b038116156117f6576001600160a01b03811663ba0bbd95306117976101008b013560e08c0135612fed565b6040516001600160e01b031960e085901b1681526001600160a01b0390921660048301526024820152604401600060405180830381600087803b1580156117dd57600080fd5b505af11580156117f1573d6000803e3d6000fd5b505050505b6000803061180a60c08b0160a08c01612a0c565b6001600160a01b031614806118375750600061182c60c08b0160a08c01612a0c565b6001600160a01b0316145b1561184b57506002905060e08801356118c1565b600061185d60a08b0160808c01612a0c565b6001600160a01b0316336001600160a01b03161461188057896101200135611882565b5a5b905060006118928d8c8985611d50565b905080156118a357600293506118be565b600193506118be6001600160a01b03861660e08d0135611bfc565b50505b6118cb8583611ea7565b6000806118de60e08c0160c08d01612a0c565b6001600160a01b031614611901576118fc60e08b0160c08c01612a0c565b611911565b61191160a08b0160808c01612a0c565b90506001600160a01b038116330361194f576000611934836101008d0135612fed565b90506119496001600160a01b03831682611bfc565b50611971565b61195e336101008c0135611bfc565b6119716001600160a01b03821683611bfc565b505050505050505050505050565b610120820135158061198e5750805b156119d4576119a360a0830160808401612a0c565b6001600160a01b0316336001600160a01b0316146119d45760405163d7f4fc9f60e01b815260040160405180910390fd5b60006119e261060284612da4565b905060016119ef82610b71565b6003811115611a0057611a00612a8f565b14611a1e57604051631f6646b560e01b815260040160405180910390fd5b604051635437cecf60e11b81526000906001600160a01b0386169063a86f9d9e90611a4e90600190600401613000565b602060405180830381865afa158015611a6b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611a8f919061301f565b90506001600160a01b03811615611b045760405163ba0bbd9560e01b815230600482015260e085013560248201526001600160a01b0382169063ba0bbd9590604401600060405180830381600087803b158015611aeb57600080fd5b505af1158015611aff573d6000803e3d6000fd5b505050505b6000611b128786855a611d50565b90508015611b2a57611b25836002611ea7565b611b4c565b611b35836003611ea7565b611b4c6001600160a01b03831660e0870135611bfc565b50505050505050565b600054610100900460ff16611b7c5760405162461bcd60e51b815260040161057590613502565b6106bf611f20565b600054610100900460ff16611bab5760405162461bcd60e51b815260040161057590613502565b6106bf611f47565b6001600160a01b038116611bda57604051634d084d8560e11b815260040160405180910390fd5b609780546001600160a01b0319166001600160a01b0392909216919091179055565b801580611c1057506001600160a01b038216155b15611c19575050565b6000826001600160a01b03168260405160006040518083038185875af1925050503d8060008114611c66576040519150601f19603f3d011682016040523d82523d6000602084013e611c6b565b606091505b50509050806106915760405162461bcd60e51b8152602060048201526013602482015272115512081d1c985b9cd9995c8819985a5b1959606a1b6044820152606401610575565b6040516301ffc9a760e01b81526001600160e01b0319821660048201526000906001600160a01b038416906301ffc9a790602401602060405180830381865afa925050508015611d1f575060408051601f3d908101601f19168201909252611d1c91810190613090565b60015b15610607579392505050565b600080611d41611d3c846000611f77565b612398565b80516020909101209392505050565b600081600003611d7357604051637f0e960960e11b815260040160405180910390fd5b6040518060600160405280848152602001856020016020810190611d979190612a0c565b6001600160a01b039081168252604087810135602093840152835160018a0155918301516002890180546001600160a01b0319169190921617905501516003860155611de960c0850160a08601612a0c565b6001600160a01b03168260e0860135611e0661014088018861354d565b604051611e14929190613593565b600060405180830381858888f193505050503d8060008114611e52576040519150601f19603f3d011682016040523d82523d6000602084013e611e57565b606091505b505060408051606081018252600180825260208201819052600019919092018190528782018290556002880180546001600160a01b03191690921790915560039096019590955550929392505050565b806003811115611eb957611eb9612a8f565b611ec283610b71565b6003811115611ed357611ed3612a8f565b146105f057611ee282826123dc565b817f0af4d5247f6a4028d6699afb62871a76b398da1d1a626c8a9b90e0bd5f54c73c8233604051611f149291906135a3565b60405180910390a25050565b600054610100900460ff16610b6b5760405162461bcd60e51b815260040161057590613502565b600054610100900460ff16611f6e5760405162461bcd60e51b815260040161057590613502565b6106bf33611072565b61020082015160609015611fe257611f90826011612fed565b6001600160401b03811115611fa757611fa7612c94565b604051908082528060200260200182016040528015611fda57816020015b6060815260200190600190039081611fc55790505b509050612051565b6101e083015115611ff857611f90826010612fed565b61200382600f612fed565b6001600160401b0381111561201a5761201a612c94565b60405190808252806020026020018201604052801561204d57816020015b60608152602001906001900390816120385790505b5090505b825161205c90612405565b8160008151811061206f5761206f6135c9565b60200260200101819052506120878360200151612405565b8160018151811061209a5761209a6135c9565b60200260200101819052506120b28360400151612418565b816002815181106120c5576120c56135c9565b60200260200101819052506120dd8360600151612405565b816003815181106120f0576120f06135c9565b60200260200101819052506121088360800151612405565b8160048151811061211b5761211b6135c9565b60200260200101819052506121338360a00151612405565b81600581518110612146576121466135c9565b602002602001018190525061217d8360c0015160405160200161216991906135df565b604051602081830303815290604052612441565b81600681518110612190576121906135c9565b60200260200101819052506121a88360e001516124b0565b816007815181106121bb576121bb6135c9565b60200260200101819052506121dd8361010001516001600160801b03166124b0565b816008815181106121f0576121f06135c9565b60200260200101819052506122098361012001516124be565b8160098151811061221c5761221c6135c9565b60200260200101819052506122358361014001516124be565b81600a81518110612248576122486135c9565b60200260200101819052506122618361016001516124be565b81600b81518110612274576122746135c9565b602002602001018190525061228d836101800151612441565b81600c815181106122a0576122a06135c9565b60200260200101819052506122b9836101a00151612405565b81600d815181106122cc576122cc6135c9565b6020026020010181905250612303836101c00151604051602001612169919060c09190911b6001600160c01b031916815260080190565b81600e81518110612316576123166135c9565b6020026020010181905250826101e0015160001461235b5761233c836101e001516124b0565b81600f8151811061234f5761234f6135c9565b60200260200101819052505b6102008301511561060757612374836102000151612405565b81601081518110612387576123876135c9565b602002602001018190525092915050565b606060006123a5836124d5565b90506123b3815160c061260a565b816040516020016123c5929190613614565b604051602081830303815290604052915050919050565b60006123e783610d06565b905060008260038111156123fd576123fd612a8f565b909155505050565b6060610607612413836127b3565b612441565b604051606082811b6bffffffffffffffffffffffff191660208301529061060790603401612169565b6060808251600114801561246f5750608083600081518110612465576124656135c9565b016020015160f81c105b1561247b575081610607565b6124878351608061260a565b83604051602001612499929190613614565b604051602081830303815290604052905092915050565b606061060761241383612865565b6060610607612413836001600160401b0316612865565b606081516000036124f657604080516000808252602082019092529061065e565b6000805b835181101561253b57838181518110612515576125156135c9565b602002602001015151826125299190612fed565b91506125348161303c565b90506124fa565b6000826001600160401b0381111561255557612555612c94565b6040519080825280601f01601f19166020018201604052801561257f576020820181803683370190505b50600092509050602081015b85518310156126015760008684815181106125a8576125a86135c9565b6020026020010151905060006020820190506125c68382845161298f565b8785815181106125d8576125d86135c9565b602002602001015151836125ec9190612fed565b92505050826125fa9061303c565b925061258b565b50949350505050565b6060806038841015612671576040805160018082528183019092529060208201818036833701905050905061263f8385613643565b60f81b81600081518110612655576126556135c9565b60200101906001600160f81b031916908160001a9053506106a6565b600060015b6126808187613672565b156126a35761268e8261303c565b915061269c61010082613686565b9050612676565b6126ae826001612fed565b6001600160401b038111156126c5576126c5612c94565b6040519080825280601f01601f1916602001820160405280156126ef576020820181803683370190505b5092506126fc8583613643565b612707906037613643565b60f81b8360008151811061271d5761271d6135c9565b60200101906001600160f81b031916908160001a905350600190505b8181116127a95761010061274d828461369d565b61275990610100613794565b6127639088613672565b61276d91906137a0565b60f81b838281518110612782576127826135c9565b60200101906001600160f81b031916908160001a9053506127a28161303c565b9050612739565b5050905092915050565b60606000826040516020016127ca91815260200190565b60408051808303601f1901815260208084528383019092529250600091829160208201818036833701905050905060005b815181101561260157838361280f8161303c565b945081518110612821576128216135c9565b602001015160f81c60f81b82828151811061283e5761283e6135c9565b60200101906001600160f81b031916908160001a90535061285e8161303c565b90506127fb565b606060008260405160200161287c91815260200190565b604051602081830303815290604052905060005b60208110156128d1578181815181106128ab576128ab6135c9565b01602001516001600160f81b0319166000036128d1576128ca8161303c565b9050612890565b60006128de82602061369d565b6001600160401b038111156128f5576128f5612c94565b6040519080825280601f01601f19166020018201604052801561291f576020820181803683370190505b50905060005b81518110156126015783836129398161303c565b94508151811061294b5761294b6135c9565b602001015160f81c60f81b828281518110612968576129686135c9565b60200101906001600160f81b031916908160001a9053506129888161303c565b9050612925565b8282825b602081106129cb57815183526129aa602084612fed565b92506129b7602083612fed565b91506129c460208261369d565b9050612993565b905182516020929092036101000a6000190180199091169116179052505050565b6001600160a01b03811681146107a157600080fd5b8035610636816129ec565b600060208284031215612a1e57600080fd5b81356106a6816129ec565b60006101808284031215612a3c57600080fd5b50919050565b600060208284031215612a5457600080fd5b81356001600160401b03811115612a6a57600080fd5b610b9484828501612a29565b600060208284031215612a8857600080fd5b5035919050565b634e487b7160e01b600052602160045260246000fd5b60048110612ac357634e487b7160e01b600052602160045260246000fd5b9052565b602081016106078284612aa5565b60008083601f840112612ae757600080fd5b5081356001600160401b03811115612afe57600080fd5b602083019150836020828501011115612b1657600080fd5b9250929050565b600080600060408486031215612b3257600080fd5b83356001600160401b0380821115612b4957600080fd5b612b5587838801612a29565b94506020860135915080821115612b6b57600080fd5b50612b7886828701612ad5565b9497909650939450505050565b80151581146107a157600080fd5b600080600060608486031215612ba857600080fd5b83359250602084013591506040840135612bc181612b85565b809150509250925092565b60008060008060608587031215612be257600080fd5b843593506020850135925060408501356001600160401b03811115612c0657600080fd5b612c1287828801612ad5565b95989497509550505050565b60008060408385031215612c3157600080fd5b823591506020830135612c4381612b85565b809150509250929050565b60008060408385031215612c6157600080fd5b82356001600160401b03811115612c7757600080fd5b612c8385828601612a29565b9250506020830135612c4381612b85565b634e487b7160e01b600052604160045260246000fd5b60405161018081016001600160401b0381118282101715612ccd57612ccd612c94565b60405290565b604080519081016001600160401b0381118282101715612ccd57612ccd612c94565b60405161022081016001600160401b0381118282101715612ccd57612ccd612c94565b600082601f830112612d2957600080fd5b81356001600160401b0380821115612d4357612d43612c94565b604051601f8301601f19908116603f01168101908282118183101715612d6b57612d6b612c94565b81604052838152866020858801011115612d8457600080fd5b836020870160208301376000602085830101528094505050505092915050565b60006101808236031215612db757600080fd5b612dbf612caa565b82358152612dcf60208401612a01565b60208201526040830135604082015260608301356060820152612df460808401612a01565b6080820152612e0560a08401612a01565b60a0820152612e1660c08401612a01565b60c082015260e0838101359082015261010080840135908201526101208084013590820152610140808401356001600160401b0380821115612e5757600080fd5b612e6336838801612d18565b83850152610160925082860135915080821115612e7f57600080fd5b50612e8c36828701612d18565b918301919091525092915050565b60005b83811015612eb5578181015183820152602001612e9d565b50506000910152565b60008151808452612ed6816020860160208601612e9a565b601f01601f19169290920160200192915050565b602081528151602082015260006020830151612f1160408401826001600160a01b03169052565b5060408301516060830152606083015160808301526080830151612f4060a08401826001600160a01b03169052565b5060a08301516001600160a01b03811660c08401525060c08301516001600160a01b03811660e08401525060e0830151610100838101919091528301516101208084019190915283015161014080840191909152830151610180610160808501829052612fb16101a0860184612ebe565b90860151858203601f190183870152909250612fcd8382612ebe565b9695505050505050565b634e487b7160e01b600052601160045260246000fd5b8082018082111561060757610607612fd7565b6a195d1a195c97dd985d5b1d60aa1b8152901515602082015260400190565b60006020828403121561303157600080fd5b81516106a6816129ec565b60006001820161304e5761304e612fd7565b5060010190565b6d7369676e616c5f7365727669636560901b8152901515602082015260400190565b60006020828403121561308957600080fd5b5051919050565b6000602082840312156130a257600080fd5b81516106a681612b85565b9182526562726964676560d01b60208301521515604082015260600190565b600083516130de818460208801612e9a565b9190910191825250602001919050565b6000808335601e1984360301811261310557600080fd5b83016020810192503590506001600160401b0381111561312457600080fd5b803603821315612b1657600080fd5b81835281816020850137506000828201602090810191909152601f909101601f19169091010190565b6020815281356020820152600061317560208401612a01565b6001600160a01b03811660408401525060408301356060830152606083013560808301526131a560808401612a01565b6001600160a01b03811660a0840152506131c160a08401612a01565b6001600160a01b03811660c0840152506131dd60c08401612a01565b6001600160a01b03811660e08401525061010060e0840135818401526101208185013581850152610140915080850135828501525061321e818501856130ee565b9150610180610160818187015261323a6101a087018585613133565b9350613248818801886130ee565b878603601f1901848901529350905061121c848483613133565b85815260018060a01b038516602082015283604082015260806060820152600061121c608083018486613133565b600082601f8301126132a157600080fd5b6040516101008082018281106001600160401b03821117156132c5576132c5612c94565b604052830181858211156132d857600080fd5b845b828110156132f25780358252602091820191016132da565b509195945050505050565b80356001600160801b038116811461063657600080fd5b80356001600160401b038116811461063657600080fd5b60006020828403121561333d57600080fd5b81356001600160401b038082111561335457600080fd5b908301906040828603121561336857600080fd5b613370612cd3565b82358281111561337f57600080fd5b8301610300818803121561339257600080fd5b61339a612cf5565b81358152602082013560208201526133b460408301612a01565b6040820152606082013560608201526080820135608082015260a082013560a08201526133e48860c08401613290565b60c08201526101c08083013560e08301526101e06134038185016132fd565b610100840152610200613417818601613314565b61012085015261342a6102208601613314565b61014085015261343d6102408601613314565b6101608501526102608501358781111561345657600080fd5b6134628c828801612d18565b610180860152506102808501356101a08501526134826102a08601613314565b838501526102c0850135828501526102e08501358185015250505080835250506020830135828111156134b457600080fd5b6134c087828601612d18565b60208301525095945050505050565b85815260018060a01b038516602082015283604082015282606082015260a06080820152600061121c60a0830184612ebe565b6020808252602b908201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960408201526a6e697469616c697a696e6760a81b606082015260800190565b6000808335601e1984360301811261356457600080fd5b8301803591506001600160401b0382111561357e57600080fd5b602001915036819003821315612b1657600080fd5b8183823760009101908152919050565b604081016135b18285612aa5565b6001600160a01b039290921660209190910152919050565b634e487b7160e01b600052603260045260246000fd5b60008183825b60088110156136045781518352602092830192909101906001016135e5565b5050506101008201905092915050565b60008351613626818460208801612e9a565b83519083019061363a818360208801612e9a565b01949350505050565b60ff818116838216019081111561060757610607612fd7565b634e487b7160e01b600052601260045260246000fd5b6000826136815761368161365c565b500490565b808202811582820484141761060757610607612fd7565b8181038181111561060757610607612fd7565b600181815b808511156136eb5781600019048211156136d1576136d1612fd7565b808516156136de57918102915b93841c93908002906136b5565b509250929050565b60008261370257506001610607565b8161370f57506000610607565b8160018114613725576002811461372f5761374b565b6001915050610607565b60ff84111561374057613740612fd7565b50506001821b610607565b5060208310610133831016604e8410600b841016171561376e575081810a610607565b61377883836136b0565b806000190482111561378c5761378c612fd7565b029392505050565b60006106a683836136f3565b6000826137af576137af61365c565b50069056fea26469706673582212204997777a1031b83fdf2e825630d2f95588a7e236b52b64399419b4df680ff6ee64736f6c63430008140033", + "balance": "0x0" + }, + "0x1000777700000000000000000000000000000004": { + "contractName": "BridgeProxy", + "storage": { + "0x0000000000000000000000000000000000000000000000000000000000000000": "0x0000000000000000000000000000000000000000000000000000000000000001", + "0x0000000000000000000000000000000000000000000000000000000000000001": "0x0000000000000000000000000000000000000000000000000000000000000001", + "0x0000000000000000000000000000000000000000000000000000000000000065": "0x00000000000000000000000019b4f9c381c7927fe33d853e48b560141a380c44", + "0x0000000000000000000000000000000000000000000000000000000000000097": "0x0000000000000000000000001000777700000000000000000000000000000006", + "0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103": "0x113cE23c9e0cc50F4D41d7cE6DA02dCAFf8BFF85", + "0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc": "0x0000777700000000000000000000000000000004" + }, + "code": "0x60806040526004361061004e5760003560e01c80633659cfe6146100655780634f1ef286146100855780635c60da1b146100985780638f283970146100c9578063f851a440146100e95761005d565b3661005d5761005b6100fe565b005b61005b6100fe565b34801561007157600080fd5b5061005b6100803660046106b3565b610118565b61005b6100933660046106ce565b610155565b3480156100a457600080fd5b506100ad6101bc565b6040516001600160a01b03909116815260200160405180910390f35b3480156100d557600080fd5b5061005b6100e43660046106b3565b6101ed565b3480156100f557600080fd5b506100ad61020d565b61010661022e565b6101166101116102c3565b6102cd565b565b6101206102f1565b6001600160a01b0316330361014d5761014a81604051806020016040528060008152506000610324565b50565b61014a6100fe565b61015d6102f1565b6001600160a01b031633036101b4576101af8383838080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525060019250610324915050565b505050565b6101af6100fe565b60006101c66102f1565b6001600160a01b031633036101e2576101dd6102c3565b905090565b6101ea6100fe565b90565b6101f56102f1565b6001600160a01b0316330361014d5761014a8161034f565b60006102176102f1565b6001600160a01b031633036101e2576101dd6102f1565b6102366102f1565b6001600160a01b031633036101165760405162461bcd60e51b815260206004820152604260248201527f5472616e73706172656e745570677261646561626c6550726f78793a2061646d60448201527f696e2063616e6e6f742066616c6c6261636b20746f2070726f78792074617267606482015261195d60f21b608482015260a4015b60405180910390fd5b60006101dd6103a3565b3660008037600080366000845af43d6000803e8080156102ec573d6000f35b3d6000fd5b60007fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035b546001600160a01b0316919050565b61032d836103cb565b60008251118061033a5750805b156101af57610349838361040b565b50505050565b7f7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f6103786102f1565b604080516001600160a01b03928316815291841660208301520160405180910390a161014a81610437565b60007f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc610315565b6103d4816104e0565b6040516001600160a01b038216907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b90600090a250565b606061043083836040518060600160405280602781526020016107c560279139610574565b9392505050565b6001600160a01b03811661049c5760405162461bcd60e51b815260206004820152602660248201527f455243313936373a206e65772061646d696e20697320746865207a65726f206160448201526564647265737360d01b60648201526084016102ba565b807fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035b80546001600160a01b0319166001600160a01b039290921691909117905550565b6001600160a01b0381163b61054d5760405162461bcd60e51b815260206004820152602d60248201527f455243313936373a206e657720696d706c656d656e746174696f6e206973206e60448201526c1bdd08184818dbdb9d1c9858dd609a1b60648201526084016102ba565b807f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc6104bf565b6060600080856001600160a01b0316856040516105919190610775565b600060405180830381855af49150503d80600081146105cc576040519150601f19603f3d011682016040523d82523d6000602084013e6105d1565b606091505b50915091506105e2868383876105ec565b9695505050505050565b6060831561065b578251600003610654576001600160a01b0385163b6106545760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e747261637400000060448201526064016102ba565b5081610665565b610665838361066d565b949350505050565b81511561067d5781518083602001fd5b8060405162461bcd60e51b81526004016102ba9190610791565b80356001600160a01b03811681146106ae57600080fd5b919050565b6000602082840312156106c557600080fd5b61043082610697565b6000806000604084860312156106e357600080fd5b6106ec84610697565b9250602084013567ffffffffffffffff8082111561070957600080fd5b818601915086601f83011261071d57600080fd5b81358181111561072c57600080fd5b87602082850101111561073e57600080fd5b6020830194508093505050509250925092565b60005b8381101561076c578181015183820152602001610754565b50506000910152565b60008251610787818460208701610751565b9190910192915050565b60208152600082518060208401526107b0816040850160208701610751565b601f01601f1916919091016040019291505056fe416464726573733a206c6f772d6c6576656c2064656c65676174652063616c6c206661696c6564a264697066735822122013e4be7fbb9448379ca283101ef1037ca99a17f6ad00269fe32f79bcefab6e1864736f6c63430008140033", + "balance": "0x0" + }, + "0x0000777700000000000000000000000000000002": { + "contractName": "ProxiedERC20Vault", + "storage": {}, + "code": "0x608060405260043610620000fb5760003560e01c8063715018a61162000095578063c287e5781162000060578063c287e57814620002e0578063cb03d23c1462000314578063e2dc9033146200032b578063f2fde38b146200034257600080fd5b8063715018a6146200024b5780638da5cb5b14620002635780639aa8605c1462000283578063a86f9d9e14620002bb57600080fd5b806332a642ca11620000d657806332a642ca14620001965780633ab76e9f14620001ad57806367090ccf14620001e15780636c6563f6146200022657600080fd5b806301ffc9a714620001005780630652b57a146200014a57806319ab453c1462000171575b600080fd5b3480156200010d57600080fd5b50620001356200011f36600462002156565b6001600160e01b031916631953216560e11b1490565b60405190151581526020015b60405180910390f35b3480156200015757600080fd5b506200016f62000169366004620021a5565b62000367565b005b3480156200017e57600080fd5b506200016f62000190366004620021a5565b620003e3565b6200016f620001a7366004620021c5565b62000503565b348015620001ba57600080fd5b506097546001600160a01b03165b6040516001600160a01b03909116815260200162000141565b348015620001ee57600080fd5b50620001c86200020036600462002204565b60cb6020908152600092835260408084209091529082529020546001600160a01b031681565b3480156200023357600080fd5b50620001c86200024536600462002246565b620007b5565b3480156200025857600080fd5b506200016f620007ce565b3480156200027057600080fd5b506065546001600160a01b0316620001c8565b3480156200029057600080fd5b50620002a8620002a2366004620021a5565b620007e6565b60405162000141959493929190620022d6565b348015620002c857600080fd5b50620001c8620002da3660046200232b565b62000947565b348015620002ed57600080fd5b5062000135620002ff366004620021a5565b60c96020526000908152604090205460ff1681565b6200016f6200032536600462002353565b6200095f565b6200016f6200033c366004620023c9565b62000c0f565b3480156200034f57600080fd5b506200016f62000361366004620021a5565b62000fb4565b6200037162001030565b6001600160a01b0381166200039957604051634d084d8560e11b815260040160405180910390fd5b609780546001600160a01b0319166001600160a01b0383169081179091556040517f399ded90cb5ed8d89ef7e76ff4af65c373f06d3bf5d7eef55f4228e7b702a18b90600090a250565b600054610100900460ff1615808015620004045750600054600160ff909116105b80620004205750303b15801562000420575060005460ff166001145b620004895760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b60648201526084015b60405180910390fd5b6000805460ff191660011790558015620004ad576000805461ff0019166101001790555b620004b8826200108c565b8015620004ff576000805461ff0019169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b5050565b6200050d620010ab565b6562726964676560d01b6200052481600162000947565b6001600160a01b0316336001600160a01b0316146200055657604051630d85cccf60e11b815260040160405180910390fd5b60006200056e6562726964676560d01b600062000947565b90506000816001600160a01b031663263463c8856040518263ffffffff1660e01b8152600401620005a0919062002481565b602060405180830381865afa158015620005be573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620005e49190620025a2565b9050600080620005f9610140870187620025bc565b6200060991600490829062002606565b8101906200061891906200273f565b919450909250506001600160a01b038316905062000649576040516303f8a7d360e01b815260040160405180910390fd5b801562000739576001600160a01b038216600090815260c9602052604090205460ff1680620006a357506200068e6a3a30b4b5b7afba37b5b2b760a91b600162000947565b6001600160a01b0316826001600160a01b0316145b156200071157604051632770a7eb60e21b8152306004820152602481018290526001600160a01b03831690639dc29fac90604401600060405180830381600087803b158015620006f257600080fd5b505af115801562000707573d6000803e3d6000fd5b5050505062000739565b620007396200072760a0880160808901620021a5565b6001600160a01b038416908362001106565b6200074b60a0870160808801620021a5565b6001600160a01b0316837f75c5fedbd5fff6123ad9b70827e9742ea1eee996583d6e14249f1429fc4fd99384846040516200079b9291906001600160a01b03929092168252602082015260400190565b60405180910390a35050505050620007b260018055565b50565b6000620007c484848462001165565b90505b9392505050565b620007d862001030565b620007e460006200121f565b565b60ca6020526000908152604090208054600182015460028301805492936001600160a01b03831693600160a01b90930460ff169290919062000828906200282d565b80601f016020809104026020016040519081016040528092919081815260200182805462000856906200282d565b8015620008a75780601f106200087b57610100808354040283529160200191620008a7565b820191906000526020600020905b8154815290600101906020018083116200088957829003601f168201915b505050505090806003018054620008be906200282d565b80601f0160208091040260200160405190810160405280929190818152602001828054620008ec906200282d565b80156200093d5780601f1062000911576101008083540402835291602001916200093d565b820191906000526020600020905b8154815290600101906020018083116200091f57829003601f168201915b5050505050905085565b60006200095646848462001165565b90505b92915050565b62000969620010ab565b6562726964676560d01b6200098081600162000947565b6001600160a01b0316336001600160a01b031614620009b257604051630d85cccf60e11b815260040160405180910390fd5b60405163881107d960e01b81526a195c98cc8c17dd985d5b1d60aa1b600482015230602482015260009073b2Bcd028F53637a4FC4E06C52d247F38f44cBe4d9063881107d990604401606060405180830381865af415801562000a19573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062000a3f919062002869565b905060004687350362000b1a5762000a5e6040880160208901620021a5565b905062000a7b6a3a30b4b5b7afba37b5b2b760a91b600162000947565b6001600160a01b0316816001600160a01b03160362000afe576040516340c10f1960e01b81526001600160a01b038681166004830152602482018690528216906340c10f1990604401600060405180830381600087803b15801562000adf57600080fd5b505af115801562000af4573d6000803e3d6000fd5b5050505062000b8e565b62000b146001600160a01b038216868662001106565b62000b8e565b62000b258762001271565b6040516340c10f1960e01b81526001600160a01b03878116600483015260248201879052919250908216906340c10f1990604401600060405180830381600087803b15801562000b7457600080fd5b505af115801562000b89573d6000803e3d6000fd5b505050505b62000ba36001600160a01b03861634620012d0565b815160408084015181519081526001600160a01b0384811660208301529181018790528188169291891691907f883b72735ca0ee2cdd2a462a393658b1a0b36ebd8756e4c22b7509a92ff86a029060600160405180910390a450505062000c0960018055565b50505050565b62000c19620010ab565b80356a195c98cc8c17dd985d5b1d60aa1b62000c3c6040840160208501620021a5565b62000c4e6060850160408601620021a5565b6001600160a01b038216158062000c83575062000c6e84846000620007b5565b6001600160a01b0316826001600160a01b0316145b1562000ca25760405163def9481360e01b815260040160405180910390fd5b6001600160a01b03811662000cca576040516303f8a7d360e01b815260040160405180910390fd5b846060013560000362000cf057604051634299323b60e11b815260040160405180910390fd5b600062000d7b6040518061018001604052806000815260200160006001600160a01b03168152602001600081526020016000815260200160006001600160a01b0316815260200160006001600160a01b0316815260200160006001600160a01b0316815260200160008152602001600081526020016000815260200160608152602001606081525090565b608081015162000db49062000d9760608a0160408b01620021a5565b62000da960408b0160208c01620021a5565b8a606001356200138c565b61014083019190915287356060830181905233608084015290925062000deb906a195c98cc8c17dd985d5b1d60aa1b6000620007b5565b6001600160a01b031660a080830191909152608088013561012083015262000e179088013534620028d1565b60e08083019190915260a088013561010083015262000e3c90880160c08901620021a5565b6001600160a01b031660c082015262000e5960e0880188620025bc565b8080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201829052506101608601949094525062000eac91506562726964676560d01b90508262000947565b6001600160a01b0316634c1888bc34846040518363ffffffff1660e01b815260040162000eda9190620028f3565b60206040518083038185885af115801562000ef9573d6000803e3d6000fd5b50505050506040513d601f19601f8201168201806040525081019062000f209190620025a2565b905062000f346040890160208a01620021a5565b60808301516001600160a01b039182169116827f91462591aed3d13dcadac8ed73fdc175ec6e79b798ca205822e7ec33dc019e888b3562000f7c60608e0160408f01620021a5565b604080519283526001600160a01b039091166020830152810188905260600160405180910390a450505050505050620007b260018055565b62000fbe62001030565b6001600160a01b038116620010255760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b606482015260840162000480565b620007b2816200121f565b6065546001600160a01b03163314620007e45760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015260640162000480565b62001096620019db565b620010a062001a0f565b620007b28162001a43565b600260015403620010ff5760405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c00604482015260640162000480565b6002600155565b604080516001600160a01b038416602482015260448082018490528251808303909101815260649091019091526020810180516001600160e01b031663a9059cbb60e01b1790526200115a90849062001a8d565b505050565b60018055565b60975460405163195ac1a960e21b815260048101859052602481018490526000916001600160a01b03169063656b06a490604401602060405180830381865afa158015620011b7573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620011dd9190620029e6565b905081158015620011f557506001600160a01b038116155b15620007c757604051631467050360e21b8152600481018590526024810184905260440162000480565b606580546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b8035600090815260cb602090815260408083209183916200129891908601908601620021a5565b6001600160a01b03908116825260208201929092526040016000205416905080620012cb57620012c88262001b66565b90505b919050565b801580620012e557506001600160a01b038216155b15620012ef575050565b6000826001600160a01b03168260405160006040518083038185875af1925050503d80600081146200133e576040519150601f19603f3d011682016040523d82523d6000602084013e62001343565b606091505b50509050806200115a5760405162461bcd60e51b8152602060048201526013602482015272115512081d1c985b9cd9995c8819985a5b1959606a1b604482015260640162000480565b60606000620013cf6040518060a001604052806000815260200160006001600160a01b03168152602001600060ff16815260200160608152602001606081525090565b6001600160a01b038616600090815260c9602052604090205460ff161562001603576001600160a01b03868116600090815260ca6020908152604091829020825160a08101845281548152600182015494851692810192909252600160a01b90930460ff169181019190915260028201805491929160608401919062001455906200282d565b80601f016020809104026020016040519081016040528092919081815260200182805462001483906200282d565b8015620014d45780601f10620014a857610100808354040283529160200191620014d4565b820191906000526020600020905b815481529060010190602001808311620014b657829003601f168201915b50505050508152602001600382018054620014ef906200282d565b80601f01602080910402602001604051908101604052809291908181526020018280546200151d906200282d565b80156200156e5780601f1062001542576101008083540402835291602001916200156e565b820191906000526020600020905b8154815290600101906020018083116200155057829003601f168201915b5050509190925250505060208101519091506001600160a01b031662001598576200159862002a06565b604051632770a7eb60e21b8152336004820152602481018590526001600160a01b03871690639dc29fac90604401600060405180830381600087803b158015620015e157600080fd5b505af1158015620015f6573d6000803e3d6000fd5b505050508391506200197a565b60008690506040518060a00160405280468152602001886001600160a01b03168152602001826001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa15801562001667573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200168d919062002a1c565b60ff168152602001826001600160a01b03166395d89b416040518163ffffffff1660e01b8152600401600060405180830381865afa158015620016d4573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052620016fe919081019062002a3c565b8152602001826001600160a01b03166306fdde036040518163ffffffff1660e01b8152600401600060405180830381865afa15801562001742573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526200176c919081019062002a3c565b905291506200178b6a3a30b4b5b7afba37b5b2b760a91b600162000947565b6001600160a01b0316876001600160a01b0316036200180f57604051632770a7eb60e21b8152336004820152602481018690526001600160a01b03881690639dc29fac90604401600060405180830381600087803b158015620017ed57600080fd5b505af115801562001802573d6000803e3d6000fd5b5050505084925062001978565b6040516370a0823160e01b81523060048201526000906001600160a01b038316906370a0823190602401602060405180830381865afa15801562001857573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200187d9190620025a2565b6040516323b872dd60e01b8152336004820152306024820152604481018890529091506001600160a01b038316906323b872dd906064016020604051808303816000875af1158015620018d4573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620018fa919062002abc565b506040516370a0823160e01b815230600482015281906001600160a01b038416906370a0823190602401602060405180830381865afa15801562001942573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620019689190620025a2565b620019749190620028d1565b9350505b505b6040516332c0f48f60e21b906200199c9083908a908990879060240162002adc565b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b0319909316929092179091529791965090945050505050565b600054610100900460ff1662001a055760405162461bcd60e51b8152600401620004809062002b79565b620007e462001e42565b600054610100900460ff1662001a395760405162461bcd60e51b8152600401620004809062002b79565b620007e462001e6c565b6001600160a01b03811662001a6b57604051634d084d8560e11b815260040160405180910390fd5b609780546001600160a01b0319166001600160a01b0392909216919091179055565b600062001ae4826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b031662001ea19092919063ffffffff16565b8051909150156200115a578080602001905181019062001b05919062002abc565b6200115a5760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6044820152691bdd081cdd58d8d9595960b21b606482015260840162000480565b60008062001bc360008460405160200162001b82919062002bc4565b604051602081830303815290604052805190602001206040518060200162001baa9062002148565b601f1982820381018352601f9091011660405262001eb2565b905073b2Bcd028F53637a4FC4E06C52d247F38f44cBe4d6378adc0d68262001bf36065546001600160a01b031690565b609754636c0db62b60e01b906001600160a01b031662001c1a60408a0160208b01620021a5565b893562001c2e60608c0160408d0162002c5c565b62001c3d60608d018d620025bc565b62001c4c60808f018f620025bc565b60405160200162001c6598979695949392919062002c7c565b60408051601f198184030181529082905262001c85929160200162002cdf565b6040516020818303038152906040526040518463ffffffff1660e01b815260040162001cb49392919062002d12565b602060405180830381865af415801562001cd2573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062001cf89190620029e6565b6001600160a01b038116600090815260c960209081526040808320805460ff1916600117905560ca9091529020909250839062001d36828262002e60565b50508235600090815260cb6020908152604080832085939092909162001d6291908801908801620021a5565b6001600160a01b03166001600160a01b0316815260200190815260200160002060006101000a8154816001600160a01b0302191690836001600160a01b03160217905550816001600160a01b031683602001602081019062001dc59190620021a5565b6001600160a01b031684357fb6b427556e8cb0ebf9175da4bc48c64c4f56e44cfaf8c3ab5ebf8e2ea130907962001e006060880188620025bc565b62001e0f60808a018a620025bc565b62001e2160608c0160408d0162002c5c565b60405162001e3495949392919062002ef3565b60405180910390a450919050565b600054610100900460ff166200115f5760405162461bcd60e51b8152600401620004809062002b79565b600054610100900460ff1662001e965760405162461bcd60e51b8152600401620004809062002b79565b620007e4336200121f565b6060620007c4848460008562001fbc565b60008347101562001f065760405162461bcd60e51b815260206004820152601d60248201527f437265617465323a20696e73756666696369656e742062616c616e6365000000604482015260640162000480565b815160000362001f595760405162461bcd60e51b815260206004820181905260248201527f437265617465323a2062797465636f6465206c656e677468206973207a65726f604482015260640162000480565b8282516020840186f590506001600160a01b038116620007c75760405162461bcd60e51b815260206004820152601960248201527f437265617465323a204661696c6564206f6e206465706c6f7900000000000000604482015260640162000480565b6060824710156200201f5760405162461bcd60e51b815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f6044820152651c8818d85b1b60d21b606482015260840162000480565b600080866001600160a01b031685876040516200203d919062002f34565b60006040518083038185875af1925050503d80600081146200207c576040519150601f19603f3d011682016040523d82523d6000602084013e62002081565b606091505b50915091506200209487838387620020a1565b925050505b949350505050565b60608315620021155782516000036200210d576001600160a01b0385163b6200210d5760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e7472616374000000604482015260640162000480565b508162002099565b6200209983838151156200212c5781518083602001fd5b8060405162461bcd60e51b815260040162000480919062002f52565b6119788062002f6883390190565b6000602082840312156200216957600080fd5b81356001600160e01b031981168114620007c757600080fd5b6001600160a01b0381168114620007b257600080fd5b8035620012cb8162002182565b600060208284031215620021b857600080fd5b8135620007c78162002182565b600060208284031215620021d857600080fd5b813567ffffffffffffffff811115620021f057600080fd5b82016101808185031215620007c757600080fd5b600080604083850312156200221857600080fd5b8235915060208301356200222c8162002182565b809150509250929050565b8015158114620007b257600080fd5b6000806000606084860312156200225c57600080fd5b83359250602084013591506040840135620022778162002237565b809150509250925092565b60005b838110156200229f57818101518382015260200162002285565b50506000910152565b60008151808452620022c281602086016020860162002282565b601f01601f19169290920160200192915050565b8581526001600160a01b038516602082015260ff8416604082015260a0606082018190526000906200230b90830185620022a8565b82810360808401526200231f8185620022a8565b98975050505050505050565b600080604083850312156200233f57600080fd5b8235915060208301356200222c8162002237565b600080600080608085870312156200236a57600080fd5b843567ffffffffffffffff8111156200238257600080fd5b850160a081880312156200239557600080fd5b93506020850135620023a78162002182565b92506040850135620023b98162002182565b9396929550929360600135925050565b600060208284031215620023dc57600080fd5b813567ffffffffffffffff811115620023f457600080fd5b82016101008185031215620007c757600080fd5b6000808335601e198436030181126200242057600080fd5b830160208101925035905067ffffffffffffffff8111156200244157600080fd5b8036038213156200245157600080fd5b9250929050565b81835281816020850137506000828201602090810191909152601f909101601f19169091010190565b602081528135602082015260006200249c6020840162002198565b6001600160a01b0381166040840152506040830135606083015260608301356080830152620024ce6080840162002198565b6001600160a01b03811660a084015250620024ec60a0840162002198565b6001600160a01b03811660c0840152506200250a60c0840162002198565b6001600160a01b03811660e08401525061010060e084013581840152610120818501358185015261014091508085013582850152506200254d8185018562002408565b915061018061016081818701526200256b6101a08701858562002458565b93506200257b8188018862002408565b878603601f190184890152935090506200259784848362002458565b979650505050505050565b600060208284031215620025b557600080fd5b5051919050565b6000808335601e19843603018112620025d457600080fd5b83018035915067ffffffffffffffff821115620025f057600080fd5b6020019150368190038213156200245157600080fd5b600080858511156200261757600080fd5b838611156200262557600080fd5b5050820193919092039150565b634e487b7160e01b600052604160045260246000fd5b60405160a0810167ffffffffffffffff811182821017156200266e576200266e62002632565b60405290565b604051601f8201601f1916810167ffffffffffffffff81118282101715620026a057620026a062002632565b604052919050565b60ff81168114620007b257600080fd5b600067ffffffffffffffff821115620026d557620026d562002632565b50601f01601f191660200190565b600082601f830112620026f557600080fd5b81356200270c6200270682620026b8565b62002674565b8181528460208386010111156200272257600080fd5b816020850160208301376000918101602001919091529392505050565b600080600080608085870312156200275657600080fd5b843567ffffffffffffffff808211156200276f57600080fd5b9086019060a082890312156200278457600080fd5b6200278e62002648565b823581526020830135620027a28162002182565b60208201526040830135620027b781620026a8565b6040820152606083013582811115620027cf57600080fd5b620027dd8a828601620026e3565b606083015250608083013582811115620027f657600080fd5b620028048a828601620026e3565b60808301525095506200281d9150506020860162002198565b9250620023b96040860162002198565b600181811c908216806200284257607f821691505b6020821081036200286357634e487b7160e01b600052602260045260246000fd5b50919050565b6000606082840312156200287c57600080fd5b6040516060810181811067ffffffffffffffff82111715620028a257620028a262002632565b604052825181526020830151620028b98162002182565b60208201526040928301519281019290925250919050565b818103818111156200095957634e487b7160e01b600052601160045260246000fd5b6020815281516020820152600060208301516200291b60408401826001600160a01b03169052565b50604083015160608301526060830151608083015260808301516200294b60a08401826001600160a01b03169052565b5060a08301516001600160a01b03811660c08401525060c08301516001600160a01b03811660e08401525060e0830151610100838101919091528301516101208084019190915283015161014080840191909152830151610180610160808501829052620029be6101a0860184620022a8565b90860151858203601f190183870152909250620029dc8382620022a8565b9695505050505050565b600060208284031215620029f957600080fd5b8151620007c78162002182565b634e487b7160e01b600052600160045260246000fd5b60006020828403121562002a2f57600080fd5b8151620007c781620026a8565b60006020828403121562002a4f57600080fd5b815167ffffffffffffffff81111562002a6757600080fd5b8201601f8101841362002a7957600080fd5b805162002a8a6200270682620026b8565b81815285602083850101111562002aa057600080fd5b62002ab382602083016020860162002282565b95945050505050565b60006020828403121562002acf57600080fd5b8151620007c78162002237565b60808152845160808201526000602086015160018060a01b0380821660a085015260ff60408901511660c08501526060880151915060a060e085015262002b28610120850183620022a8565b91506080880151607f198584030161010086015262002b488382620022a8565b9188166020860152506001600160a01b0386166040850152915062002b6a9050565b82606083015295945050505050565b6020808252602b908201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960408201526a6e697469616c697a696e6760a81b606082015260800190565b60208152813560208201526000602083013562002be18162002182565b6001600160a01b031660408381019190915283013562002c0181620026a8565b60ff811660608401525062002c1a606084018462002408565b60a0608085015262002c3160c08501828462002458565b91505062002c43608085018562002408565b848303601f190160a0860152620029dc83828462002458565b60006020828403121562002c6f57600080fd5b8135620007c781620026a8565b6001600160a01b038981168252881660208201526040810187905260ff8616606082015260c06080820181905260009062002cbb908301868862002458565b82810360a084015262002cd081858762002458565b9b9a5050505050505050505050565b6001600160e01b031983168152815160009062002d0481600485016020870162002282565b919091016004019392505050565b6001600160a01b0384811682528316602082015260606040820181905260009062002ab390830184620022a8565b601f8211156200115a57600081815260208120601f850160051c8101602086101562002d695750805b601f850160051c820191505b8181101562002d8a5782815560010162002d75565b505050505050565b67ffffffffffffffff83111562002dad5762002dad62002632565b62002dc58362002dbe83546200282d565b8362002d40565b6000601f84116001811462002dfc576000851562002de35750838201355b600019600387901b1c1916600186901b17835562002e59565b600083815260209020601f19861690835b8281101562002e2f578685013582556020948501946001909201910162002e0d565b508682101562002e4d5760001960f88860031b161c19848701351681555b505060018560011b0183555b5050505050565b8135815560018101602083013562002e788162002182565b8154604085013562002e8a81620026a8565b60ff60a01b60a09190911b166001600160a01b03929092166001600160a81b0319919091161717905562002ec26060830183620025bc565b62002ed281836002860162002d92565b505062002ee36080830183620025bc565b62000c0981836003860162002d92565b60608152600062002f0960608301878962002458565b828103602084015262002f1e81868862002458565b91505060ff831660408301529695505050505050565b6000825162002f4881846020870162002282565b9190910192915050565b602081526000620009566020830184620022a856fe608060405234801561001057600080fd5b5061001961001e565b6100de565b600054610100900460ff161561008a5760405162461bcd60e51b815260206004820152602760248201527f496e697469616c697a61626c653a20636f6e747261637420697320696e697469604482015266616c697a696e6760c81b606482015260840160405180910390fd5b60005460ff90811610156100dc576000805460ff191660ff9081179091556040519081527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b565b61188b806100ed6000396000f3fe608060405234801561001057600080fd5b50600436106101585760003560e01c80636c6563f6116100c35780639dc29fac1161007c5780639dc29fac146102fa578063a457c2d71461030d578063a86f9d9e14610320578063a9059cbb14610333578063dd62ed3e14610346578063f2fde38b1461035957600080fd5b80636c6563f61461028a57806370a082311461029d578063715018a6146102c65780637cf8ed0d146102ce5780638da5cb5b146102e157806395d89b41146102f257600080fd5b8063313ce56711610115578063313ce5671461020e57806339509351146102235780633ab76e9f1461023657806340c10f191461025b57806349d126051461026e5780636c0db62b1461027757600080fd5b80630652b57a1461015d57806306fdde0314610172578063095ea7b31461019057806318160ddd146101b357806323b872dd146101c557806326afaadd146101d8575b600080fd5b61017061016b366004611349565b61036c565b005b61017a6103e5565b604051610187919061138a565b60405180910390f35b6101a361019e3660046113bd565b61041f565b6040519015158152602001610187565b60cb545b604051908152602001610187565b6101a36101d33660046113e9565b610439565b6101ef60fb5460fc546001600160a01b0390911691565b604080516001600160a01b039093168352602083019190915201610187565b60fd5460405160ff9091168152602001610187565b6101a36102313660046113bd565b610479565b6097546001600160a01b03165b6040516001600160a01b039091168152602001610187565b6101706102693660046113bd565b61049b565b6101b760fc5481565b6101706102853660046114cd565b610558565b61024361029836600461158c565b6106fe565b6101b76102ab366004611349565b6001600160a01b0316600090815260c9602052604090205490565b61017061070b565b60fb54610243906001600160a01b031681565b6065546001600160a01b0316610243565b61017a61071f565b6101706103083660046113bd565b6107b1565b6101a361031b3660046113bd565b61083b565b61024361032e3660046115c1565b6108c1565b6101a36103413660046113bd565b6108ce565b6101b76103543660046115ed565b610903565b610170610367366004611349565b61092e565b6103746109a7565b6001600160a01b03811661039b57604051634d084d8560e11b815260040160405180910390fd5b609780546001600160a01b0319166001600160a01b0383169081179091556040517f399ded90cb5ed8d89ef7e76ff4af65c373f06d3bf5d7eef55f4228e7b702a18b90600090a250565b60606103ef610a01565b6103fa60fc54610a10565b60405160200161040b929190611626565b604051602081830303815290604052905090565b60003361042d818585610aa3565b60019150505b92915050565b6000306001600160a01b0384160361046457604051636cfe544760e01b815260040160405180910390fd5b61046f848484610bbf565b90505b9392505050565b60003361042d81858561048c8383610903565b6104969190611664565b610aa3565b6a195c98cc8c17dd985d5b1d60aa1b647461696b6f60d81b6104be8260016108c1565b6001600160a01b0316336001600160a01b0316141580156104fb57506104e58160016108c1565b6001600160a01b0316336001600160a01b031614155b1561051957604051630d85cccf60e11b815260040160405180910390fd5b6105238484610bd8565b6040518381526001600160a01b038516906000906000805160206118368339815191529060200160405180910390a350505050565b600054610100900460ff16158080156105785750600054600160ff909116105b806105925750303b158015610592575060005460ff166001145b6105fa5760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b60648201526084015b60405180910390fd5b6000805460ff19166001179055801561061d576000805461ff0019166101001790555b6001600160a01b0386161580610631575084155b8061063b57504685145b8061064557508251155b8061064f57508151155b1561066d57604051635d061ab760e11b815260040160405180910390fd5b61067687610c88565b6106808284610ca1565b60fb80546001600160a01b0319166001600160a01b03881617905560fc85905560fd805460ff191660ff861617905580156106f5576000805461ff0019169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b50505050505050565b600061046f848484610cd2565b6107136109a7565b61071d6000610d86565b565b606060cd805461072e90611685565b80601f016020809104026020016040519081016040528092919081815260200182805461075a90611685565b80156107a75780601f1061077c576101008083540402835291602001916107a7565b820191906000526020600020905b81548152906001019060200180831161078a57829003601f168201915b5050505050905090565b6a195c98cc8c17dd985d5b1d60aa1b6107cb8160016108c1565b6001600160a01b0316336001600160a01b0316146107fc57604051630d85cccf60e11b815260040160405180910390fd5b6108068383610dd8565b6040518281526000906001600160a01b03851690600080516020611836833981519152906020015b60405180910390a3505050565b600033816108498286610903565b9050838110156108a95760405162461bcd60e51b815260206004820152602560248201527f45524332303a2064656372656173656420616c6c6f77616e63652062656c6f77604482015264207a65726f60d81b60648201526084016105f1565b6108b68286868403610aa3565b506001949350505050565b6000610472468484610cd2565b6000306001600160a01b038416036108f957604051636cfe544760e01b815260040160405180910390fd5b6104728383610ef7565b6001600160a01b03918216600090815260ca6020908152604080832093909416825291909152205490565b6109366109a7565b6001600160a01b03811661099b5760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b60648201526084016105f1565b6109a481610d86565b50565b6065546001600160a01b0316331461071d5760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657260448201526064016105f1565b606060cc805461072e90611685565b60606000610a1d83610f05565b600101905060008167ffffffffffffffff811115610a3d57610a3d61142a565b6040519080825280601f01601f191660200182016040528015610a67576020820181803683370190505b5090508181016020015b600019016f181899199a1a9b1b9c1cb0b131b232b360811b600a86061a8153600a8504945084610a7157509392505050565b6001600160a01b038316610b055760405162461bcd60e51b8152602060048201526024808201527f45524332303a20617070726f76652066726f6d20746865207a65726f206164646044820152637265737360e01b60648201526084016105f1565b6001600160a01b038216610b665760405162461bcd60e51b815260206004820152602260248201527f45524332303a20617070726f766520746f20746865207a65726f206164647265604482015261737360f01b60648201526084016105f1565b6001600160a01b03838116600081815260ca602090815260408083209487168084529482529182902085905590518481527f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925910161082e565b600033610bcd858285610fdd565b6108b6858585611057565b6001600160a01b038216610c2e5760405162461bcd60e51b815260206004820152601f60248201527f45524332303a206d696e7420746f20746865207a65726f20616464726573730060448201526064016105f1565b8060cb6000828254610c409190611664565b90915550506001600160a01b038216600081815260c96020908152604080832080548601905551848152600080516020611836833981519152910160405180910390a35b5050565b610c906111f0565b610c9861121f565b6109a48161124e565b600054610100900460ff16610cc85760405162461bcd60e51b81526004016105f1906116bf565b610c848282611297565b60975460405163195ac1a960e21b815260048101859052602481018490526000916001600160a01b03169063656b06a490604401602060405180830381865afa158015610d23573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d47919061170a565b905081158015610d5e57506001600160a01b038116155b1561047257604051631467050360e21b815260048101859052602481018490526044016105f1565b606580546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b6001600160a01b038216610e385760405162461bcd60e51b815260206004820152602160248201527f45524332303a206275726e2066726f6d20746865207a65726f206164647265736044820152607360f81b60648201526084016105f1565b6001600160a01b038216600090815260c9602052604090205481811015610eac5760405162461bcd60e51b815260206004820152602260248201527f45524332303a206275726e20616d6f756e7420657863656564732062616c616e604482015261636560f01b60648201526084016105f1565b6001600160a01b038316600081815260c960209081526040808320868603905560cb8054879003905551858152919291600080516020611836833981519152910161082e565b505050565b60003361042d818585611057565b60008072184f03e93ff9f4daa797ed6e38ed64bf6a1f0160401b8310610f445772184f03e93ff9f4daa797ed6e38ed64bf6a1f0160401b830492506040015b6d04ee2d6d415b85acef81000000008310610f70576d04ee2d6d415b85acef8100000000830492506020015b662386f26fc100008310610f8e57662386f26fc10000830492506010015b6305f5e1008310610fa6576305f5e100830492506008015b6127108310610fba57612710830492506004015b60648310610fcc576064830492506002015b600a83106104335760010192915050565b6000610fe98484610903565b9050600019811461105157818110156110445760405162461bcd60e51b815260206004820152601d60248201527f45524332303a20696e73756666696369656e7420616c6c6f77616e636500000060448201526064016105f1565b6110518484848403610aa3565b50505050565b6001600160a01b0383166110bb5760405162461bcd60e51b815260206004820152602560248201527f45524332303a207472616e736665722066726f6d20746865207a65726f206164604482015264647265737360d81b60648201526084016105f1565b6001600160a01b03821661111d5760405162461bcd60e51b815260206004820152602360248201527f45524332303a207472616e7366657220746f20746865207a65726f206164647260448201526265737360e81b60648201526084016105f1565b6001600160a01b038316600090815260c96020526040902054818110156111955760405162461bcd60e51b815260206004820152602660248201527f45524332303a207472616e7366657220616d6f756e7420657863656564732062604482015265616c616e636560d01b60648201526084016105f1565b6001600160a01b03808516600081815260c960205260408082208686039055928616808252908390208054860190559151600080516020611836833981519152906111e39086815260200190565b60405180910390a3611051565b600054610100900460ff166112175760405162461bcd60e51b81526004016105f1906116bf565b61071d6112d7565b600054610100900460ff166112465760405162461bcd60e51b81526004016105f1906116bf565b61071d611304565b6001600160a01b03811661127557604051634d084d8560e11b815260040160405180910390fd5b609780546001600160a01b0319166001600160a01b0392909216919091179055565b600054610100900460ff166112be5760405162461bcd60e51b81526004016105f1906116bf565b60cc6112ca8382611775565b5060cd610ef28282611775565b600054610100900460ff166112fe5760405162461bcd60e51b81526004016105f1906116bf565b60018055565b600054610100900460ff1661132b5760405162461bcd60e51b81526004016105f1906116bf565b61071d33610d86565b6001600160a01b03811681146109a457600080fd5b60006020828403121561135b57600080fd5b813561047281611334565b60005b83811015611381578181015183820152602001611369565b50506000910152565b60208152600082518060208401526113a9816040850160208701611366565b601f01601f19169190910160400192915050565b600080604083850312156113d057600080fd5b82356113db81611334565b946020939093013593505050565b6000806000606084860312156113fe57600080fd5b833561140981611334565b9250602084013561141981611334565b929592945050506040919091013590565b634e487b7160e01b600052604160045260246000fd5b600082601f83011261145157600080fd5b813567ffffffffffffffff8082111561146c5761146c61142a565b604051601f8301601f19908116603f011681019082821181831017156114945761149461142a565b816040528381528660208588010111156114ad57600080fd5b836020870160208301376000602085830101528094505050505092915050565b60008060008060008060c087890312156114e657600080fd5b86356114f181611334565b9550602087013561150181611334565b945060408701359350606087013560ff8116811461151e57600080fd5b9250608087013567ffffffffffffffff8082111561153b57600080fd5b6115478a838b01611440565b935060a089013591508082111561155d57600080fd5b5061156a89828a01611440565b9150509295509295509295565b8035801515811461158757600080fd5b919050565b6000806000606084860312156115a157600080fd5b83359250602084013591506115b860408501611577565b90509250925092565b600080604083850312156115d457600080fd5b823591506115e460208401611577565b90509250929050565b6000806040838503121561160057600080fd5b823561160b81611334565b9150602083013561161b81611334565b809150509250929050565b60008351611638818460208801611366565b6241c55b60e71b9083019081528351611658816004840160208801611366565b01600401949350505050565b8082018082111561043357634e487b7160e01b600052601160045260246000fd5b600181811c9082168061169957607f821691505b6020821081036116b957634e487b7160e01b600052602260045260246000fd5b50919050565b6020808252602b908201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960408201526a6e697469616c697a696e6760a81b606082015260800190565b60006020828403121561171c57600080fd5b815161047281611334565b601f821115610ef257600081815260208120601f850160051c8101602086101561174e5750805b601f850160051c820191505b8181101561176d5782815560010161175a565b505050505050565b815167ffffffffffffffff81111561178f5761178f61142a565b6117a38161179d8454611685565b84611727565b602080601f8311600181146117d857600084156117c05750858301515b600019600386901b1c1916600185901b17855561176d565b600085815260208120601f198616915b82811015611807578886015182559484019460019091019084016117e8565b50858210156118255787850151600019600388901b60f8161c191681555b5050505050600190811b0190555056feddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3efa264697066735822122084c55b31f1ca31a63eb2f494abc3a7a53871a4d74e8f1a0d4a8487fc410374b564736f6c63430008140033a2646970667358221220fb6838adab59caf0c87ea98c1d46d8afdd628bcbc80e276935e7eb4856c7485964736f6c63430008140033", + "balance": "0x0" + }, + "0x1000777700000000000000000000000000000002": { + "contractName": "ERC20VaultProxy", + "storage": { + "0x0000000000000000000000000000000000000000000000000000000000000000": "0x0000000000000000000000000000000000000000000000000000000000000001", + "0x0000000000000000000000000000000000000000000000000000000000000001": "0x0000000000000000000000000000000000000000000000000000000000000001", + "0x0000000000000000000000000000000000000000000000000000000000000065": "0x00000000000000000000000019b4f9c381c7927fe33d853e48b560141a380c44", + "0x0000000000000000000000000000000000000000000000000000000000000097": "0x0000000000000000000000001000777700000000000000000000000000000006", + "0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103": "0x113cE23c9e0cc50F4D41d7cE6DA02dCAFf8BFF85", + "0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc": "0x0000777700000000000000000000000000000002" + }, + "code": "0x60806040526004361061004e5760003560e01c80633659cfe6146100655780634f1ef286146100855780635c60da1b146100985780638f283970146100c9578063f851a440146100e95761005d565b3661005d5761005b6100fe565b005b61005b6100fe565b34801561007157600080fd5b5061005b6100803660046106b3565b610118565b61005b6100933660046106ce565b610155565b3480156100a457600080fd5b506100ad6101bc565b6040516001600160a01b03909116815260200160405180910390f35b3480156100d557600080fd5b5061005b6100e43660046106b3565b6101ed565b3480156100f557600080fd5b506100ad61020d565b61010661022e565b6101166101116102c3565b6102cd565b565b6101206102f1565b6001600160a01b0316330361014d5761014a81604051806020016040528060008152506000610324565b50565b61014a6100fe565b61015d6102f1565b6001600160a01b031633036101b4576101af8383838080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525060019250610324915050565b505050565b6101af6100fe565b60006101c66102f1565b6001600160a01b031633036101e2576101dd6102c3565b905090565b6101ea6100fe565b90565b6101f56102f1565b6001600160a01b0316330361014d5761014a8161034f565b60006102176102f1565b6001600160a01b031633036101e2576101dd6102f1565b6102366102f1565b6001600160a01b031633036101165760405162461bcd60e51b815260206004820152604260248201527f5472616e73706172656e745570677261646561626c6550726f78793a2061646d60448201527f696e2063616e6e6f742066616c6c6261636b20746f2070726f78792074617267606482015261195d60f21b608482015260a4015b60405180910390fd5b60006101dd6103a3565b3660008037600080366000845af43d6000803e8080156102ec573d6000f35b3d6000fd5b60007fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035b546001600160a01b0316919050565b61032d836103cb565b60008251118061033a5750805b156101af57610349838361040b565b50505050565b7f7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f6103786102f1565b604080516001600160a01b03928316815291841660208301520160405180910390a161014a81610437565b60007f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc610315565b6103d4816104e0565b6040516001600160a01b038216907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b90600090a250565b606061043083836040518060600160405280602781526020016107c560279139610574565b9392505050565b6001600160a01b03811661049c5760405162461bcd60e51b815260206004820152602660248201527f455243313936373a206e65772061646d696e20697320746865207a65726f206160448201526564647265737360d01b60648201526084016102ba565b807fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035b80546001600160a01b0319166001600160a01b039290921691909117905550565b6001600160a01b0381163b61054d5760405162461bcd60e51b815260206004820152602d60248201527f455243313936373a206e657720696d706c656d656e746174696f6e206973206e60448201526c1bdd08184818dbdb9d1c9858dd609a1b60648201526084016102ba565b807f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc6104bf565b6060600080856001600160a01b0316856040516105919190610775565b600060405180830381855af49150503d80600081146105cc576040519150601f19603f3d011682016040523d82523d6000602084013e6105d1565b606091505b50915091506105e2868383876105ec565b9695505050505050565b6060831561065b578251600003610654576001600160a01b0385163b6106545760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e747261637400000060448201526064016102ba565b5081610665565b610665838361066d565b949350505050565b81511561067d5781518083602001fd5b8060405162461bcd60e51b81526004016102ba9190610791565b80356001600160a01b03811681146106ae57600080fd5b919050565b6000602082840312156106c557600080fd5b61043082610697565b6000806000604084860312156106e357600080fd5b6106ec84610697565b9250602084013567ffffffffffffffff8082111561070957600080fd5b818601915086601f83011261071d57600080fd5b81358181111561072c57600080fd5b87602082850101111561073e57600080fd5b6020830194508093505050509250925092565b60005b8381101561076c578181015183820152602001610754565b50506000910152565b60008251610787818460208701610751565b9190910192915050565b60208152600082518060208401526107b0816040850160208701610751565b601f01601f1916919091016040019291505056fe416464726573733a206c6f772d6c6576656c2064656c65676174652063616c6c206661696c6564a264697066735822122013e4be7fbb9448379ca283101ef1037ca99a17f6ad00269fe32f79bcefab6e1864736f6c63430008140033", + "balance": "0x0" + }, + "0x0000777700000000000000000000000000000008": { + "contractName": "ProxiedERC721Vault", + "storage": {}, + "code": "0x6080604052600436106200011f5760003560e01c80636c6563f611620000a15780639aa8605c116200006c5780639aa8605c1462000342578063a86f9d9e1462000379578063a9976baf146200039e578063c287e57814620003b5578063f2fde38b14620003e957600080fd5b80636c6563f614620002ce578063715018a614620002f357806373339643146200030b5780638da5cb5b146200032257600080fd5b80632ca069a511620000ee5780632ca069a5146200020457806332a642ca14620002215780633ab76e9f146200023857806359f4a907146200026c57806367090ccf146200028957600080fd5b806301ffc9a714620001245780630652b57a146200016e578063150b7a02146200019557806319ab453c14620001df575b600080fd5b3480156200013157600080fd5b50620001596200014336600462002112565b6001600160e01b031916631953216560e11b1490565b60405190151581526020015b60405180910390f35b3480156200017b57600080fd5b50620001936200018d36600462002161565b6200040e565b005b348015620001a257600080fd5b50620001c5620001b436600462002181565b630a85bd0160e11b95945050505050565b6040516001600160e01b0319909116815260200162000165565b348015620001ec57600080fd5b5062000193620001fe36600462002161565b6200048a565b3480156200021157600080fd5b50620001c5636cdb3d1360e11b81565b620001936200023236600462002228565b620005aa565b3480156200024557600080fd5b506097546001600160a01b03165b6040516001600160a01b03909116815260200162000165565b3480156200027957600080fd5b50620001c56380ac58cd60e01b81565b3480156200029657600080fd5b5062000253620002a836600462002266565b60cb6020908152600092835260408084209091529082529020546001600160a01b031681565b348015620002db57600080fd5b5062000253620002ed366004620022a8565b620009cd565b3480156200030057600080fd5b5062000193620009e6565b620001936200031c366004620022e4565b620009fe565b3480156200032f57600080fd5b506065546001600160a01b031662000253565b3480156200034f57600080fd5b50620003676200036136600462002161565b62000eaa565b60405162000165949392919062002376565b3480156200038657600080fd5b506200025362000398366004620023c1565b62000ffd565b62000193620003af366004620024af565b62001015565b348015620003c257600080fd5b5062000159620003d436600462002161565b60c96020526000908152604090205460ff1681565b348015620003f657600080fd5b50620001936200040836600462002161565b62001336565b62000418620013b2565b6001600160a01b0381166200044057604051634d084d8560e11b815260040160405180910390fd5b609780546001600160a01b0319166001600160a01b0383169081179091556040517f399ded90cb5ed8d89ef7e76ff4af65c373f06d3bf5d7eef55f4228e7b702a18b90600090a250565b600054610100900460ff1615808015620004ab5750600054600160ff909116105b80620004c75750303b158015620004c7575060005460ff166001145b620005305760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b60648201526084015b60405180910390fd5b6000805460ff19166001179055801562000554576000805461ff0019166101001790555b6200055f826200140e565b8015620005a6576000805461ff0019169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b5050565b620005b46200142d565b6562726964676560d01b620005cb81600162000ffd565b6001600160a01b0316336001600160a01b031614620005fd57604051630d85cccf60e11b815260040160405180910390fd5b60006200061160a084016080850162002161565b6001600160a01b031603620006395760405163016a294f60e41b815260040160405180910390fd5b468260400135146200065e57604051630a15fbb960e01b815260040160405180910390fd5b600080620006716101408501856200254d565b620006819160049082906200259d565b81019062000690919062002704565b935050509150600073b2Bcd028F53637a4FC4E06C52d247F38f44cBe4d632c6a56af86620006c96562726964676560d01b600062000ffd565b86602001516040518463ffffffff1660e01b8152600401620006ee93929190620027c6565b602060405180830381865af41580156200070c573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062000732919062002920565b6020808501516001600160a01b0316600090815260c9909152604090205490915060ff1615620008245760005b82518110156200081d5760208401516001600160a01b03166340c10f196200078e60a0890160808a0162002161565b858481518110620007a357620007a36200293a565b60200260200101516040518363ffffffff1660e01b8152600401620007dd9291906001600160a01b03929092168252602082015260400190565b600060405180830381600087803b158015620007f857600080fd5b505af11580156200080d573d6000803e3d6000fd5b505050508060010190506200075f565b50620008ee565b60005b8251811015620008ec5760208401516001600160a01b03166342842e0e306200085760a08a0160808b0162002161565b8685815181106200086c576200086c6200293a565b60209081029190910101516040516001600160e01b031960e086901b1681526001600160a01b0393841660048201529290911660248301526044820152606401600060405180830381600087803b158015620008c757600080fd5b505af1158015620008dc573d6000803e3d6000fd5b5050505080600101905062000827565b505b6200091960e08601356200090960a088016080890162002161565b6001600160a01b03169062001488565b6200092b60a086016080870162002161565b6001600160a01b0316817fe8449897bd3c926a272780c39ba13e77bf7a2c823479a75bfbc13ef631183dfd85602001518560006001600160401b03811115620009785762000978620023e9565b604051908082528060200260200182016040528015620009a2578160200160208202803683370190505b50604051620009b4939291906200298d565b60405180910390a350505050620009ca60018055565b50565b6000620009dc8484846200154f565b90505b9392505050565b620009f0620013b2565b620009fc600062001609565b565b62000a086200142d565b73b2Bcd028F53637a4FC4E06C52d247F38f44cBe4d63c0619cc262000a316080840184620029d1565b62000a406060860186620029d1565b60016040518663ffffffff1660e01b815260040162000a6495949392919062002a50565b60006040518083038186803b15801562000a7d57600080fd5b505af415801562000a92573d6000803e3d6000fd5b5050505073b2Bcd028F53637a4FC4E06C52d247F38f44cBe4d6393522e3e62000ad183600001356b195c98cdcc8c57dd985d5b1d60a21b6000620009cd565b62000ae3604085016020860162002161565b62000af5606086016040870162002161565b60405160e085901b6001600160e01b03191681526001600160a01b0393841660048201529183166024830152909116604482015260640160006040518083038186803b15801562000b4557600080fd5b505af415801562000b5a573d6000803e3d6000fd5b5062000b8f92506380ac58cd60e01b915062000b7f9050606084016040850162002161565b6001600160a01b0316906200165b565b62000bad57604051633ee915f560e11b815260040160405180910390fd5b600062000bbe6080830183620029d1565b80806020026020016040519081016040528093929190818152602001838360200280828437600092018290525093945062000c0492505050606084016040850162002161565b9050600062000c176060850185620029d1565b80806020026020016040519081016040528093929190818152602001838360200280828437600092018290525060408051610180810182528281526020810183905290810182905260608082018390526080820183905260a0820183905260c0820183905260e082018390526101008201839052610120820192909252610140810182905261016081019190915293945062000cb292505050565b8435606082015262000cc53386620016d8565b610140820152336080820152606081015162000cf3906b195c98cdcc8c57dd985d5b1d60a21b6000620009cd565b6001600160a01b031660a08083019190915285013561012082015262000d1e60c08601353462002a90565b60e08083019190915260c08601356101008084019190915262000d479190870190870162002161565b6001600160a01b031660c082015262000d656101008601866200254d565b8080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201829052506101608601949094525062000db891506562726964676560d01b90508262000ffd565b6001600160a01b0316634c1888bc34846040518363ffffffff1660e01b815260040162000de6919062002ab2565b60206040518083038185885af115801562000e05573d6000803e3d6000fd5b50505050506040513d601f19601f8201168201806040525081019062000e2c919062002920565b905062000e40604087016020880162002161565b6001600160a01b031682608001516001600160a01b0316827f5e54276405062454e6226625b28a6fea0a838d6b054e38955667234afb3345a3856060015188888b60405162000e93949392919062002b9b565b60405180910390a45050505050620009ca60018055565b60ca6020526000908152604090208054600182015460028301805492936001600160a01b039092169262000ede9062002bdb565b80601f016020809104026020016040519081016040528092919081815260200182805462000f0c9062002bdb565b801562000f5d5780601f1062000f315761010080835404028352916020019162000f5d565b820191906000526020600020905b81548152906001019060200180831162000f3f57829003601f168201915b50505050509080600301805462000f749062002bdb565b80601f016020809104026020016040519081016040528092919081815260200182805462000fa29062002bdb565b801562000ff35780601f1062000fc75761010080835404028352916020019162000ff3565b820191906000526020600020905b81548152906001019060200180831162000fd557829003601f168201915b5050505050905084565b60006200100c4684846200154f565b90505b92915050565b6200101f6200142d565b6562726964676560d01b6200103681600162000ffd565b6001600160a01b0316336001600160a01b0316146200106857604051630d85cccf60e11b815260040160405180910390fd5b60405163881107d960e01b81526b195c98cdcc8c57dd985d5b1d60a21b600482015230602482015260009073b2Bcd028F53637a4FC4E06C52d247F38f44cBe4d9063881107d990604401606060405180830381865af4158015620010d0573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620010f6919062002c17565b9050600046873503620011d15762001115604088016020890162002161565b905060005b8451811015620011ca57816001600160a01b03166323b872dd30888885815181106200114a576200114a6200293a565b60209081029190910101516040516001600160e01b031960e086901b1681526001600160a01b0393841660048201529290911660248301526044820152606401600060405180830381600087803b158015620011a557600080fd5b505af1158015620011ba573d6000803e3d6000fd5b505050508060010190506200111a565b506200128c565b620011dc8762001c07565b905060005b84518110156200128a57816001600160a01b03166340c10f19878784815181106200121057620012106200293a565b60200260200101516040518363ffffffff1660e01b81526004016200124a9291906001600160a01b03929092168252602082015260400190565b600060405180830381600087803b1580156200126557600080fd5b505af11580156200127a573d6000803e3d6000fd5b50505050806001019050620011e1565b505b620012a16001600160a01b0386163462001488565b815160408301516001600160a01b0380881692908916917f0f60c37489e435ed8490c30b01c1fa57e62510e88b351b75796ad3d95babe6b1908589600060405190808252806020026020018201604052801562001308578160200160208202803683370190505b506040516200131b949392919062002b9b565b60405180910390a45050506200133060018055565b50505050565b62001340620013b2565b6001600160a01b038116620013a75760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b606482015260840162000527565b620009ca8162001609565b6065546001600160a01b03163314620009fc5760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015260640162000527565b6200141862001c70565b6200142262001ca4565b620009ca8162001cd8565b600260015403620014815760405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c00604482015260640162000527565b6002600155565b8015806200149d57506001600160a01b038216155b15620014a7575050565b6000826001600160a01b03168260405160006040518083038185875af1925050503d8060008114620014f6576040519150601f19603f3d011682016040523d82523d6000602084013e620014fb565b606091505b5050905080620015445760405162461bcd60e51b8152602060048201526013602482015272115512081d1c985b9cd9995c8819985a5b1959606a1b604482015260640162000527565b505050565b60018055565b60975460405163195ac1a960e21b815260048101859052602481018490526000916001600160a01b03169063656b06a490604401602060405180830381865afa158015620015a1573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620015c7919062002c7e565b905081158015620015df57506001600160a01b038116155b15620009df57604051631467050360e21b8152600481018590526024810184905260440162000527565b606580546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b6040516301ffc9a760e01b81526001600160e01b0319821660048201526000906001600160a01b038416906301ffc9a790602401602060405180830381865afa925050508015620016cb575060408051601f3d908101601f19168201909252620016c89181019062002c9e565b60015b156200100f579392505050565b6040805160808101825260008082526020820152606091810182905280820182905260c9600062001710606086016040870162002161565b6001600160a01b0316815260208101919091526040016000205460ff1615620019985760ca600062001749606086016040870162002161565b6001600160a01b0390811682526020808301939093526040918201600020825160808101845281548152600182015490921693820193909352600283018054919392840191620017999062002bdb565b80601f0160208091040260200160405190810160405280929190818152602001828054620017c79062002bdb565b8015620018185780601f10620017ec5761010080835404028352916020019162001818565b820191906000526020600020905b815481529060010190602001808311620017fa57829003601f168201915b50505050508152602001600382018054620018339062002bdb565b80601f0160208091040260200160405190810160405280929190818152602001828054620018619062002bdb565b8015620018b25780601f106200188657610100808354040283529160200191620018b2565b820191906000526020600020905b8154815290600101906020018083116200189457829003601f168201915b505050505081525050905060005b620018cf6060850185620029d1565b90508110156200199157620018eb606085016040860162002161565b6001600160a01b0316639dc29fac86620019096060880188620029d1565b858181106200191c576200191c6200293a565b6040516001600160e01b031960e087901b1681526001600160a01b0390941660048501526020029190910135602483015250604401600060405180830381600087803b1580156200196c57600080fd5b505af115801562001981573d6000803e3d6000fd5b50505050806001019050620018c0565b5062001b8c565b6000620019ac606085016040860162002161565b90506040518060800160405280468152602001856040016020810190620019d4919062002161565b6001600160a01b03168152602001826001600160a01b03166395d89b416040518163ffffffff1660e01b8152600401600060405180830381865afa15801562001a21573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405262001a4b919081019062002cbe565b8152602001826001600160a01b03166306fdde036040518163ffffffff1660e01b8152600401600060405180830381865afa15801562001a8f573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405262001ab9919081019062002cbe565b9052915060005b62001acf6060860186620029d1565b905081101562001b89576001600160a01b0382166323b872dd873062001af960608a018a620029d1565b8681811062001b0c5762001b0c6200293a565b6040516001600160e01b031960e088901b1681526001600160a01b03958616600482015294909316602485015250602090910201356044820152606401600060405180830381600087803b15801562001b6457600080fd5b505af115801562001b79573d6000803e3d6000fd5b5050505080600101905062001ac0565b50505b63a9976baf60e01b818562001ba8604087016020880162002161565b62001bb76060880188620029d1565b60405160240162001bcd95949392919062002d8b565b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b031990931692909217909152949350505050565b8035600090815260cb6020908152604080832091839162001c2e9190860190860162002161565b6001600160a01b0390811682526020820192909252604001600020541690508062001c6b5762001c6862001c628362002dd8565b62001d22565b90505b919050565b600054610100900460ff1662001c9a5760405162461bcd60e51b8152600401620005279062002de6565b620009fc62001f9b565b600054610100900460ff1662001cce5760405162461bcd60e51b8152600401620005279062002de6565b620009fc62001fc5565b6001600160a01b03811662001d0057604051634d084d8560e11b815260040160405180910390fd5b609780546001600160a01b0319166001600160a01b0392909216919091179055565b60008062001d7f60008460405160200162001d3e919062002e31565b604051602081830303815290604052805190602001206040518060200162001d669062002104565b601f1982820381018352601f9091011660405262001ffa565b905073b2Bcd028F53637a4FC4E06C52d247F38f44cBe4d6378adc0d68262001daf6065546001600160a01b031690565b60975460208089015189516040808c015160608d0151915163689ccd8d60e11b9662001deb966001600160a01b03909116959493910162002e46565b60408051601f198184030181529082905262001e0b929160200162002e8f565b6040516020818303038152906040526040518463ffffffff1660e01b815260040162001e3a9392919062002ec2565b602060405180830381865af415801562001e58573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062001e7e919062002c7e565b6001600160a01b03818116600090815260c9602090815260408083208054600160ff19909116811790915560ca835292819020885181559188015192820180546001600160a01b03191693909416929092179092558501519193508491600282019062001eec908262002f42565b506060820151600382019062001f03908262002f42565b50508351600090815260cb6020908152604080832082880180516001600160a01b039081168652919093529281902080546001600160a01b031916878516908117909155915187518289015160608a015193519496509190941693927f2da3c4d305298f6df3653c23d98b4c055f72f7e6f981b2c477ccbec92b1ee5799262001f8d92916200300e565b60405180910390a450919050565b600054610100900460ff16620015495760405162461bcd60e51b8152600401620005279062002de6565b600054610100900460ff1662001fef5760405162461bcd60e51b8152600401620005279062002de6565b620009fc3362001609565b6000834710156200204e5760405162461bcd60e51b815260206004820152601d60248201527f437265617465323a20696e73756666696369656e742062616c616e6365000000604482015260640162000527565b8151600003620020a15760405162461bcd60e51b815260206004820181905260248201527f437265617465323a2062797465636f6465206c656e677468206973207a65726f604482015260640162000527565b8282516020840186f590506001600160a01b038116620009df5760405162461bcd60e51b815260206004820152601960248201527f437265617465323a204661696c6564206f6e206465706c6f7900000000000000604482015260640162000527565b611f55806200303883390190565b6000602082840312156200212557600080fd5b81356001600160e01b0319811681146200100c57600080fd5b6001600160a01b0381168114620009ca57600080fd5b803562001c6b816200213e565b6000602082840312156200217457600080fd5b81356200100c816200213e565b6000806000806000608086880312156200219a57600080fd5b8535620021a7816200213e565b94506020860135620021b9816200213e565b93506040860135925060608601356001600160401b0380821115620021dd57600080fd5b818801915088601f830112620021f257600080fd5b8135818111156200220257600080fd5b8960208285010111156200221557600080fd5b9699959850939650602001949392505050565b6000602082840312156200223b57600080fd5b81356001600160401b038111156200225257600080fd5b820161018081850312156200100c57600080fd5b600080604083850312156200227a57600080fd5b8235915060208301356200228e816200213e565b809150509250929050565b8015158114620009ca57600080fd5b600080600060608486031215620022be57600080fd5b83359250602084013591506040840135620022d98162002299565b809150509250925092565b600060208284031215620022f757600080fd5b81356001600160401b038111156200230e57600080fd5b820161012081850312156200100c57600080fd5b60005b838110156200233f57818101518382015260200162002325565b50506000910152565b600081518084526200236281602086016020860162002322565b601f01601f19169290920160200192915050565b8481526001600160a01b0384166020820152608060408201819052600090620023a29083018562002348565b8281036060840152620023b6818562002348565b979650505050505050565b60008060408385031215620023d557600080fd5b8235915060208301356200228e8162002299565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f191681016001600160401b03811182821017156200242a576200242a620023e9565b604052919050565b600082601f8301126200244457600080fd5b813560206001600160401b03821115620024625762002462620023e9565b8160051b62002473828201620023ff565b92835284810182019282810190878511156200248e57600080fd5b83870192505b84831015620023b65782358252918301919083019062002494565b60008060008060808587031215620024c657600080fd5b84356001600160401b0380821115620024de57600080fd5b9086019060808289031215620024f357600080fd5b90945060208601359062002507826200213e565b9093506040860135906200251b826200213e565b909250606086013590808211156200253257600080fd5b50620025418782880162002432565b91505092959194509250565b6000808335601e198436030181126200256557600080fd5b8301803591506001600160401b038211156200258057600080fd5b6020019150368190038213156200259657600080fd5b9250929050565b60008085851115620025ae57600080fd5b83861115620025bc57600080fd5b5050820193919092039150565b60006001600160401b03821115620025e557620025e5620023e9565b50601f01601f191660200190565b600082601f8301126200260557600080fd5b81356200261c6200261682620025c9565b620023ff565b8181528460208386010111156200263257600080fd5b816020850160208301376000918101602001919091529392505050565b6000608082840312156200266257600080fd5b604051608081016001600160401b038282108183111715620026885762002688620023e9565b816040528293508435835260208501359150620026a5826200213e565b8160208401526040850135915080821115620026c057600080fd5b620026ce86838701620025f3565b60408401526060850135915080821115620026e857600080fd5b50620026f785828601620025f3565b6060830152505092915050565b600080600080608085870312156200271b57600080fd5b84356001600160401b03808211156200273357600080fd5b62002741888389016200264f565b95506020870135915062002507826200213e565b6000808335601e198436030181126200276d57600080fd5b83016020810192503590506001600160401b038111156200278d57600080fd5b8036038213156200259657600080fd5b81835281816020850137506000828201602090810191909152601f909101601f19169091010190565b60608152833560608201526000620027e16020860162002154565b6001600160a01b038116608084015250604085013560a0830152606085013560c0830152620028136080860162002154565b6001600160a01b031660e08301526200282f60a0860162002154565b61010062002847818501836001600160a01b03169052565b6200285560c0880162002154565b91506101206200286f818601846001600160a01b03169052565b610140925060e088013583860152610160828901358187015261018092508189013583870152620028a3848a018a62002755565b94509150826101a0870152620028bf6101e0870185846200279d565b9350620028cf818a018a62002755565b9350915050605f19858403016101c0860152620028ee8383836200279d565b93505050506200290960208301856001600160a01b03169052565b6001600160a01b0383166040830152949350505050565b6000602082840312156200293357600080fd5b5051919050565b634e487b7160e01b600052603260045260246000fd5b600081518084526020808501945080840160005b83811015620029825781518752958201959082019060010162002964565b509495945050505050565b6001600160a01b0384168152606060208201819052600090620029b39083018562002950565b8281036040840152620029c7818562002950565b9695505050505050565b6000808335601e19843603018112620029e957600080fd5b8301803591506001600160401b0382111562002a0457600080fd5b6020019150600581901b36038213156200259657600080fd5b81835260006001600160fb1b0383111562002a3757600080fd5b8260051b80836020870137939093016020019392505050565b60608152600062002a6660608301878962002a1d565b828103602084015262002a7b81868862002a1d565b91505082151560408301529695505050505050565b818103818111156200100f57634e487b7160e01b600052601160045260246000fd5b60208152815160208201526000602083015162002ada60408401826001600160a01b03169052565b506040830151606083015260608301516080830152608083015162002b0a60a08401826001600160a01b03169052565b5060a08301516001600160a01b03811660c08401525060c08301516001600160a01b03811660e08401525060e083015161010083810191909152830151610120808401919091528301516101408084019190915283015161018061016080850182905262002b7d6101a086018462002348565b90860151858203601f190183870152909250620029c7838262002348565b8481526001600160a01b038416602082015260806040820181905260009062002bc79083018562002950565b8281036060840152620023b6818562002950565b600181811c9082168062002bf057607f821691505b60208210810362002c1157634e487b7160e01b600052602260045260246000fd5b50919050565b60006060828403121562002c2a57600080fd5b604051606081018181106001600160401b038211171562002c4f5762002c4f620023e9565b60405282518152602083015162002c66816200213e565b60208201526040928301519281019290925250919050565b60006020828403121562002c9157600080fd5b81516200100c816200213e565b60006020828403121562002cb157600080fd5b81516200100c8162002299565b60006020828403121562002cd157600080fd5b81516001600160401b0381111562002ce857600080fd5b8201601f8101841362002cfa57600080fd5b805162002d0b6200261682620025c9565b81815285602083850101111562002d2157600080fd5b62002d3482602083016020860162002322565b95945050505050565b8051825260018060a01b036020820151166020830152600060408201516080604085015262002d70608085018262002348565b90506060830151848203606086015262002d34828262002348565b60808152600062002da0608083018862002d3d565b6001600160a01b03878116602085015286166040840152828103606084015262002dcc81858762002a1d565b98975050505050505050565b600062001c6836836200264f565b6020808252602b908201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960408201526a6e697469616c697a696e6760a81b606082015260800190565b6020815260006200100c602083018462002d3d565b6001600160a01b038681168252851660208201526040810184905260a06060820181905260009062002e7b9083018562002348565b828103608084015262002dcc818562002348565b6001600160e01b031983168152815160009062002eb481600485016020870162002322565b919091016004019392505050565b6001600160a01b0384811682528316602082015260606040820181905260009062002d349083018462002348565b601f8211156200154457600081815260208120601f850160051c8101602086101562002f195750805b601f850160051c820191505b8181101562002f3a5782815560010162002f25565b505050505050565b81516001600160401b0381111562002f5e5762002f5e620023e9565b62002f768162002f6f845462002bdb565b8462002ef0565b602080601f83116001811462002fae576000841562002f955750858301515b600019600386901b1c1916600185901b17855562002f3a565b600085815260208120601f198616915b8281101562002fdf5788860151825594840194600190910190840162002fbe565b508582101562002ffe5787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b60408152600062003023604083018562002348565b828103602084015262002d3481856200234856fe608060405234801561001057600080fd5b5061001961001e565b6100de565b600054610100900460ff161561008a5760405162461bcd60e51b815260206004820152602760248201527f496e697469616c697a61626c653a20636f6e747261637420697320696e697469604482015266616c697a696e6760c81b606482015260840160405180910390fd5b60005460ff90811610156100dc576000805460ff191660ff9081179091556040519081527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b565b611e68806100ed6000396000f3fe608060405234801561001057600080fd5b506004361061018e5760003560e01c806370a08231116100de578063a22cb46511610097578063c87b56dd11610071578063c87b56dd14610377578063d1399b1a14610398578063e985e9c5146103ab578063f2fde38b146103e857600080fd5b8063a22cb4651461033e578063a86f9d9e14610351578063b88d4fde1461036457600080fd5b806370a08231146102e3578063715018a6146102f65780637cf8ed0d146102fe5780638da5cb5b1461031257806395d89b41146103235780639dc29fac1461032b57600080fd5b80633ab76e9f1161014b57806349d126051161012557806349d126051461026d5780636352211e1461028557806367e828bf146102985780636c6563f6146102d057600080fd5b80633ab76e9f1461023657806340c10f191461024757806342842e0e1461025a57600080fd5b806301ffc9a7146101935780630652b57a146101bb57806306fdde03146101d0578063081812fc146101e5578063095ea7b31461021057806323b872dd14610223575b600080fd5b6101a66101a136600461171c565b6103fb565b60405190151581526020015b60405180910390f35b6101ce6101c936600461174e565b61044d565b005b6101d86104c6565b6040516101b291906117bb565b6101f86101f33660046117ce565b610501565b6040516001600160a01b0390911681526020016101b2565b6101ce61021e3660046117e7565b610528565b6101ce610231366004611813565b610642565b6097546001600160a01b03166101f8565b6101ce6102553660046117e7565b610676565b6101ce610268366004611813565b6106f7565b61027761012e5481565b6040519081526020016101b2565b6101f86102933660046117ce565b610712565b6102b161012d5461012e546001600160a01b0390911691565b604080516001600160a01b0390931683526020830191909152016101b2565b6101f86102de366004611869565b610772565b6102776102f136600461174e565b610789565b6101ce61080f565b61012d546101f8906001600160a01b031681565b6065546001600160a01b03166101f8565b6101d8610823565b6101ce6103393660046117e7565b6108b5565b6101ce61034c36600461189e565b61096f565b6101f861035f3660046118d3565b61097e565b6101ce610372366004611982565b61098b565b6101d86103853660046117ce565b5060408051602081019091526000815290565b6101ce6103a6366004611a22565b6109c3565b6101a66103b9366004611ab5565b6001600160a01b0391821660009081526101006020908152604080832093909416825291909152205460ff1690565b6101ce6103f636600461174e565b610b56565b60006001600160e01b031982166380ac58cd60e01b148061042c57506001600160e01b03198216635b5e139f60e01b145b8061044757506301ffc9a760e01b6001600160e01b03198316145b92915050565b610455610bcf565b6001600160a01b03811661047c57604051634d084d8560e11b815260040160405180910390fd5b609780546001600160a01b0319166001600160a01b0383169081179091556040517f399ded90cb5ed8d89ef7e76ff4af65c373f06d3bf5d7eef55f4228e7b702a18b90600090a250565b60606104d0610c29565b6104dc61012e54610c38565b6040516020016104ed929190611aee565b604051602081830303815290604052905090565b600061050c82610ccb565b50600090815260ff60205260409020546001600160a01b031690565b600061053382610712565b9050806001600160a01b0316836001600160a01b0316036105a55760405162461bcd60e51b815260206004820152602160248201527f4552433732313a20617070726f76616c20746f2063757272656e74206f776e656044820152603960f91b60648201526084015b60405180910390fd5b336001600160a01b03821614806105c157506105c181336103b9565b6106335760405162461bcd60e51b815260206004820152603d60248201527f4552433732313a20617070726f76652063616c6c6572206973206e6f7420746f60448201527f6b656e206f776e6572206f7220617070726f76656420666f7220616c6c000000606482015260840161059c565b61063d8383610d2a565b505050565b306001600160a01b0383160361066b57604051636cfe544760e01b815260040160405180910390fd5b61063d838383610d98565b6b195c98cdcc8c57dd985d5b1d60a21b61069181600161097e565b6001600160a01b0316336001600160a01b0316146106c257604051630d85cccf60e11b815260040160405180910390fd5b6106cc8383610dc9565b60405182906001600160a01b03851690600090600080516020611e13833981519152908290a4505050565b61063d8383836040518060200160405280600081525061098b565b600081815260fd60205260408120546001600160a01b0316806104475760405162461bcd60e51b8152602060048201526018602482015277115490cdcc8c4e881a5b9d985b1a59081d1bdad95b88125160421b604482015260640161059c565b600061077f848484610f42565b90505b9392505050565b60006001600160a01b0382166107f35760405162461bcd60e51b815260206004820152602960248201527f4552433732313a2061646472657373207a65726f206973206e6f7420612076616044820152683634b21037bbb732b960b91b606482015260840161059c565b506001600160a01b0316600090815260fe602052604090205490565b610817610bcf565b6108216000610ff6565b565b606060fc805461083290611b2c565b80601f016020809104026020016040519081016040528092919081815260200182805461085e90611b2c565b80156108ab5780601f10610880576101008083540402835291602001916108ab565b820191906000526020600020905b81548152906001019060200180831161088e57829003601f168201915b5050505050905090565b6b195c98cdcc8c57dd985d5b1d60a21b6108d081600161097e565b6001600160a01b0316336001600160a01b03161461090157604051630d85cccf60e11b815260040160405180910390fd5b826001600160a01b031661091483610712565b6001600160a01b03161461093b576040516302dca79760e41b815260040160405180910390fd5b61094482611048565b60405182906000906001600160a01b03861690600080516020611e13833981519152908390a4505050565b61097a3383836110cb565b5050565b6000610782468484610f42565b610995338361119a565b6109b15760405162461bcd60e51b815260040161059c90611b66565b6109bd8484848461121a565b50505050565b600054610100900460ff16158080156109e35750600054600160ff909116105b806109fd5750303b1580156109fd575060005460ff166001145b610a605760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b606482015260840161059c565b6000805460ff191660011790558015610a83576000805461ff0019166101001790555b6001600160a01b0385161580610a97575083155b80610aa157504684145b80610aab57508251155b80610ab557508151155b15610ad357604051635d061ab760e11b815260040160405180910390fd5b610adc8661124d565b610ae68284611266565b61012d80546001600160a01b0319166001600160a01b03871617905561012e8490558015610b4e576000805461ff0019169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b505050505050565b610b5e610bcf565b6001600160a01b038116610bc35760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b606482015260840161059c565b610bcc81610ff6565b50565b6065546001600160a01b031633146108215760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015260640161059c565b606060fb805461083290611b2c565b60606000610c4583611297565b600101905060008167ffffffffffffffff811115610c6557610c656118f6565b6040519080825280601f01601f191660200182016040528015610c8f576020820181803683370190505b5090508181016020015b600019016f181899199a1a9b1b9c1cb0b131b232b360811b600a86061a8153600a8504945084610c9957509392505050565b600081815260fd60205260409020546001600160a01b0316610bcc5760405162461bcd60e51b8152602060048201526018602482015277115490cdcc8c4e881a5b9d985b1a59081d1bdad95b88125160421b604482015260640161059c565b600081815260ff6020526040902080546001600160a01b0319166001600160a01b0384169081179091558190610d5f82610712565b6001600160a01b03167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92560405160405180910390a45050565b610da2338261119a565b610dbe5760405162461bcd60e51b815260040161059c90611b66565b61063d83838361136f565b6001600160a01b038216610e1f5760405162461bcd60e51b815260206004820181905260248201527f4552433732313a206d696e7420746f20746865207a65726f2061646472657373604482015260640161059c565b600081815260fd60205260409020546001600160a01b031615610e845760405162461bcd60e51b815260206004820152601c60248201527f4552433732313a20746f6b656e20616c7265616479206d696e74656400000000604482015260640161059c565b600081815260fd60205260409020546001600160a01b031615610ee95760405162461bcd60e51b815260206004820152601c60248201527f4552433732313a20746f6b656e20616c7265616479206d696e74656400000000604482015260640161059c565b6001600160a01b038216600081815260fe602090815260408083208054600101905584835260fd90915280822080546001600160a01b031916841790555183929190600080516020611e13833981519152908290a45050565b60975460405163195ac1a960e21b815260048101859052602481018490526000916001600160a01b03169063656b06a490604401602060405180830381865afa158015610f93573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610fb79190611bb3565b905081158015610fce57506001600160a01b038116155b1561078257604051631467050360e21b8152600481018590526024810184905260440161059c565b606580546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b600061105382610712565b905061105e82610712565b600083815260ff6020908152604080832080546001600160a01b03199081169091556001600160a01b03851680855260fe8452828520805460001901905587855260fd90935281842080549091169055519293508492600080516020611e13833981519152908390a45050565b816001600160a01b0316836001600160a01b03160361112c5760405162461bcd60e51b815260206004820152601960248201527f4552433732313a20617070726f766520746f2063616c6c657200000000000000604482015260640161059c565b6001600160a01b0383811660008181526101006020908152604080832094871680845294825291829020805460ff191686151590811790915591519182527f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c31910160405180910390a3505050565b6000806111a683610712565b9050806001600160a01b0316846001600160a01b031614806111ee57506001600160a01b038082166000908152610100602090815260408083209388168352929052205460ff165b806112125750836001600160a01b031661120784610501565b6001600160a01b0316145b949350505050565b61122584848461136f565b611231848484846114c1565b6109bd5760405162461bcd60e51b815260040161059c90611bd0565b6112556115c2565b61125d6115f1565b610bcc81611620565b600054610100900460ff1661128d5760405162461bcd60e51b815260040161059c90611c22565b61097a8282611669565b60008072184f03e93ff9f4daa797ed6e38ed64bf6a1f0160401b83106112d65772184f03e93ff9f4daa797ed6e38ed64bf6a1f0160401b830492506040015b6d04ee2d6d415b85acef81000000008310611302576d04ee2d6d415b85acef8100000000830492506020015b662386f26fc10000831061132057662386f26fc10000830492506010015b6305f5e1008310611338576305f5e100830492506008015b612710831061134c57612710830492506004015b6064831061135e576064830492506002015b600a83106104475760010192915050565b826001600160a01b031661138282610712565b6001600160a01b0316146113a85760405162461bcd60e51b815260040161059c90611c6d565b6001600160a01b03821661140a5760405162461bcd60e51b8152602060048201526024808201527f4552433732313a207472616e7366657220746f20746865207a65726f206164646044820152637265737360e01b606482015260840161059c565b826001600160a01b031661141d82610712565b6001600160a01b0316146114435760405162461bcd60e51b815260040161059c90611c6d565b600081815260ff6020908152604080832080546001600160a01b03199081169091556001600160a01b0387811680865260fe855283862080546000190190559087168086528386208054600101905586865260fd9094528285208054909216841790915590518493600080516020611e1383398151915291a4505050565b60006001600160a01b0384163b156115b757604051630a85bd0160e11b81526001600160a01b0385169063150b7a0290611505903390899088908890600401611cb2565b6020604051808303816000875af1925050508015611540575060408051601f3d908101601f1916820190925261153d91810190611cef565b60015b61159d573d80801561156e576040519150601f19603f3d011682016040523d82523d6000602084013e611573565b606091505b5080516000036115955760405162461bcd60e51b815260040161059c90611bd0565b805181602001fd5b6001600160e01b031916630a85bd0160e11b149050611212565b506001949350505050565b600054610100900460ff166115e95760405162461bcd60e51b815260040161059c90611c22565b6108216116a9565b600054610100900460ff166116185760405162461bcd60e51b815260040161059c90611c22565b6108216116d6565b6001600160a01b03811661164757604051634d084d8560e11b815260040160405180910390fd5b609780546001600160a01b0319166001600160a01b0392909216919091179055565b600054610100900460ff166116905760405162461bcd60e51b815260040161059c90611c22565b60fb61169c8382611d52565b5060fc61063d8282611d52565b600054610100900460ff166116d05760405162461bcd60e51b815260040161059c90611c22565b60018055565b600054610100900460ff166116fd5760405162461bcd60e51b815260040161059c90611c22565b61082133610ff6565b6001600160e01b031981168114610bcc57600080fd5b60006020828403121561172e57600080fd5b813561078281611706565b6001600160a01b0381168114610bcc57600080fd5b60006020828403121561176057600080fd5b813561078281611739565b60005b8381101561178657818101518382015260200161176e565b50506000910152565b600081518084526117a781602086016020860161176b565b601f01601f19169290920160200192915050565b602081526000610782602083018461178f565b6000602082840312156117e057600080fd5b5035919050565b600080604083850312156117fa57600080fd5b823561180581611739565b946020939093013593505050565b60008060006060848603121561182857600080fd5b833561183381611739565b9250602084013561184381611739565b929592945050506040919091013590565b8035801515811461186457600080fd5b919050565b60008060006060848603121561187e57600080fd5b833592506020840135915061189560408501611854565b90509250925092565b600080604083850312156118b157600080fd5b82356118bc81611739565b91506118ca60208401611854565b90509250929050565b600080604083850312156118e657600080fd5b823591506118ca60208401611854565b634e487b7160e01b600052604160045260246000fd5b600067ffffffffffffffff80841115611927576119276118f6565b604051601f8501601f19908116603f0116810190828211818310171561194f5761194f6118f6565b8160405280935085815286868601111561196857600080fd5b858560208301376000602087830101525050509392505050565b6000806000806080858703121561199857600080fd5b84356119a381611739565b935060208501356119b381611739565b925060408501359150606085013567ffffffffffffffff8111156119d657600080fd5b8501601f810187136119e757600080fd5b6119f68782356020840161190c565b91505092959194509250565b600082601f830112611a1357600080fd5b6107828383356020850161190c565b600080600080600060a08688031215611a3a57600080fd5b8535611a4581611739565b94506020860135611a5581611739565b935060408601359250606086013567ffffffffffffffff80821115611a7957600080fd5b611a8589838a01611a02565b93506080880135915080821115611a9b57600080fd5b50611aa888828901611a02565b9150509295509295909350565b60008060408385031215611ac857600080fd5b8235611ad381611739565b91506020830135611ae381611739565b809150509250929050565b60008351611b0081846020880161176b565b6241c55b60e71b9083019081528351611b2081600484016020880161176b565b01600401949350505050565b600181811c90821680611b4057607f821691505b602082108103611b6057634e487b7160e01b600052602260045260246000fd5b50919050565b6020808252602d908201527f4552433732313a2063616c6c6572206973206e6f7420746f6b656e206f776e6560408201526c1c881bdc88185c1c1c9bdd9959609a1b606082015260800190565b600060208284031215611bc557600080fd5b815161078281611739565b60208082526032908201527f4552433732313a207472616e7366657220746f206e6f6e20455243373231526560408201527131b2b4bb32b91034b6b83632b6b2b73a32b960711b606082015260800190565b6020808252602b908201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960408201526a6e697469616c697a696e6760a81b606082015260800190565b60208082526025908201527f4552433732313a207472616e736665722066726f6d20696e636f72726563742060408201526437bbb732b960d91b606082015260800190565b6001600160a01b0385811682528416602082015260408101839052608060608201819052600090611ce59083018461178f565b9695505050505050565b600060208284031215611d0157600080fd5b815161078281611706565b601f82111561063d57600081815260208120601f850160051c81016020861015611d335750805b601f850160051c820191505b81811015610b4e57828155600101611d3f565b815167ffffffffffffffff811115611d6c57611d6c6118f6565b611d8081611d7a8454611b2c565b84611d0c565b602080601f831160018114611db55760008415611d9d5750858301515b600019600386901b1c1916600185901b178555610b4e565b600085815260208120601f198616915b82811015611de457888601518255948401946001909101908401611dc5565b5085821015611e025787850151600019600388901b60f8161c191681555b5050505050600190811b0190555056feddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3efa2646970667358221220982ed42a531dac25c2cd2d24df34757ecf10be7c97db68448affe62cbba75e9764736f6c63430008140033a2646970667358221220fee14084f7c8b84170ddb74bcefdd41ccd4dfdb6fcb6f2b4715d9e5da996604564736f6c63430008140033", + "balance": "0x0" + }, + "0x1000777700000000000000000000000000000008": { + "contractName": "ERC721VaultProxy", + "storage": { + "0x0000000000000000000000000000000000000000000000000000000000000000": "0x0000000000000000000000000000000000000000000000000000000000000001", + "0x0000000000000000000000000000000000000000000000000000000000000001": "0x0000000000000000000000000000000000000000000000000000000000000001", + "0x0000000000000000000000000000000000000000000000000000000000000065": "0x00000000000000000000000019b4f9c381c7927fe33d853e48b560141a380c44", + "0x0000000000000000000000000000000000000000000000000000000000000097": "0x0000000000000000000000001000777700000000000000000000000000000006", + "0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103": "0x113cE23c9e0cc50F4D41d7cE6DA02dCAFf8BFF85", + "0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc": "0x0000777700000000000000000000000000000008" + }, + "code": "0x60806040526004361061004e5760003560e01c80633659cfe6146100655780634f1ef286146100855780635c60da1b146100985780638f283970146100c9578063f851a440146100e95761005d565b3661005d5761005b6100fe565b005b61005b6100fe565b34801561007157600080fd5b5061005b6100803660046106b3565b610118565b61005b6100933660046106ce565b610155565b3480156100a457600080fd5b506100ad6101bc565b6040516001600160a01b03909116815260200160405180910390f35b3480156100d557600080fd5b5061005b6100e43660046106b3565b6101ed565b3480156100f557600080fd5b506100ad61020d565b61010661022e565b6101166101116102c3565b6102cd565b565b6101206102f1565b6001600160a01b0316330361014d5761014a81604051806020016040528060008152506000610324565b50565b61014a6100fe565b61015d6102f1565b6001600160a01b031633036101b4576101af8383838080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525060019250610324915050565b505050565b6101af6100fe565b60006101c66102f1565b6001600160a01b031633036101e2576101dd6102c3565b905090565b6101ea6100fe565b90565b6101f56102f1565b6001600160a01b0316330361014d5761014a8161034f565b60006102176102f1565b6001600160a01b031633036101e2576101dd6102f1565b6102366102f1565b6001600160a01b031633036101165760405162461bcd60e51b815260206004820152604260248201527f5472616e73706172656e745570677261646561626c6550726f78793a2061646d60448201527f696e2063616e6e6f742066616c6c6261636b20746f2070726f78792074617267606482015261195d60f21b608482015260a4015b60405180910390fd5b60006101dd6103a3565b3660008037600080366000845af43d6000803e8080156102ec573d6000f35b3d6000fd5b60007fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035b546001600160a01b0316919050565b61032d836103cb565b60008251118061033a5750805b156101af57610349838361040b565b50505050565b7f7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f6103786102f1565b604080516001600160a01b03928316815291841660208301520160405180910390a161014a81610437565b60007f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc610315565b6103d4816104e0565b6040516001600160a01b038216907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b90600090a250565b606061043083836040518060600160405280602781526020016107c560279139610574565b9392505050565b6001600160a01b03811661049c5760405162461bcd60e51b815260206004820152602660248201527f455243313936373a206e65772061646d696e20697320746865207a65726f206160448201526564647265737360d01b60648201526084016102ba565b807fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035b80546001600160a01b0319166001600160a01b039290921691909117905550565b6001600160a01b0381163b61054d5760405162461bcd60e51b815260206004820152602d60248201527f455243313936373a206e657720696d706c656d656e746174696f6e206973206e60448201526c1bdd08184818dbdb9d1c9858dd609a1b60648201526084016102ba565b807f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc6104bf565b6060600080856001600160a01b0316856040516105919190610775565b600060405180830381855af49150503d80600081146105cc576040519150601f19603f3d011682016040523d82523d6000602084013e6105d1565b606091505b50915091506105e2868383876105ec565b9695505050505050565b6060831561065b578251600003610654576001600160a01b0385163b6106545760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e747261637400000060448201526064016102ba565b5081610665565b610665838361066d565b949350505050565b81511561067d5781518083602001fd5b8060405162461bcd60e51b81526004016102ba9190610791565b80356001600160a01b03811681146106ae57600080fd5b919050565b6000602082840312156106c557600080fd5b61043082610697565b6000806000604084860312156106e357600080fd5b6106ec84610697565b9250602084013567ffffffffffffffff8082111561070957600080fd5b818601915086601f83011261071d57600080fd5b81358181111561072c57600080fd5b87602082850101111561073e57600080fd5b6020830194508093505050509250925092565b60005b8381101561076c578181015183820152602001610754565b50506000910152565b60008251610787818460208701610751565b9190910192915050565b60208152600082518060208401526107b0816040850160208701610751565b601f01601f1916919091016040019291505056fe416464726573733a206c6f772d6c6576656c2064656c65676174652063616c6c206661696c6564a264697066735822122013e4be7fbb9448379ca283101ef1037ca99a17f6ad00269fe32f79bcefab6e1864736f6c63430008140033", + "balance": "0x0" + }, + "0x0000777700000000000000000000000000000009": { + "contractName": "ProxiedERC1155Vault", + "storage": {}, + "code": "0x6080604052600436106200012b5760003560e01c80636c6563f611620000ad578063a86f9d9e116200006c578063a86f9d9e146200035c578063bc197c811462000381578063c287e57814620003b4578063f23a6e6114620003e8578063f2fde38b146200041957600080fd5b80636c6563f614620002b1578063715018a614620002d65780637333964314620002ee5780638da5cb5b14620003055780639aa8605c146200032557600080fd5b80632ca069a511620000fa5780632ca069a514620001cd57806332a642ca14620002045780633ab76e9f146200021b57806359f4a907146200024f57806367090ccf146200026c57600080fd5b806301ffc9a714620001305780630652b57a146200016a57806319ab453c146200019157806320b8155914620001b6575b600080fd5b3480156200013d57600080fd5b50620001556200014f36600462001fcf565b6200043e565b60405190151581526020015b60405180910390f35b3480156200017757600080fd5b506200018f620001893660046200201e565b62000488565b005b3480156200019e57600080fd5b506200018f620001b03660046200201e565b62000504565b6200018f620001c73660046200213b565b62000624565b348015620001da57600080fd5b50620001ea636cdb3d1360e11b81565b6040516001600160e01b0319909116815260200162000161565b6200018f6200021536600462002201565b62000953565b3480156200022857600080fd5b506097546001600160a01b03165b6040516001600160a01b03909116815260200162000161565b3480156200025c57600080fd5b50620001ea6380ac58cd60e01b81565b3480156200027957600080fd5b50620002366200028b3660046200223f565b60cb6020908152600092835260408084209091529082529020546001600160a01b031681565b348015620002be57600080fd5b5062000236620002d036600462002281565b62000cfb565b348015620002e357600080fd5b506200018f62000d14565b6200018f620002ff36600462002343565b62000d2c565b3480156200031257600080fd5b506065546001600160a01b031662000236565b3480156200033257600080fd5b506200034a620003443660046200201e565b620010a7565b604051620001619493929190620024b5565b3480156200036957600080fd5b50620002366200037b366004620024f5565b620011fa565b3480156200038e57600080fd5b50620001ea620003a0366004620025af565b63bc197c8160e01b98975050505050505050565b348015620003c157600080fd5b5062000155620003d33660046200201e565b60c96020526000908152604090205460ff1681565b348015620003f557600080fd5b50620001ea620004073660046200267b565b63f23a6e6160e01b9695505050505050565b3480156200042657600080fd5b506200018f620004383660046200201e565b62001209565b60006001600160e01b031982166301ffc9a760e01b14806200047057506001600160e01b03198216631953216560e11b145b80620004825750620004828262001285565b92915050565b62000492620012bc565b6001600160a01b038116620004ba57604051634d084d8560e11b815260040160405180910390fd5b609780546001600160a01b0319166001600160a01b0383169081179091556040517f399ded90cb5ed8d89ef7e76ff4af65c373f06d3bf5d7eef55f4228e7b702a18b90600090a250565b600054610100900460ff1615808015620005255750600054600160ff909116105b80620005415750303b15801562000541575060005460ff166001145b620005aa5760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b60648201526084015b60405180910390fd5b6000805460ff191660011790558015620005ce576000805461ff0019166101001790555b620005d98262001318565b801562000620576000805461ff0019169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b5050565b6200062e62001337565b6562726964676560d01b62000645816001620011fa565b6001600160a01b0316336001600160a01b0316146200067757604051630d85cccf60e11b815260040160405180910390fd5b60405163881107d960e01b81526c195c98cc4c4d4d57dd985d5b1d609a1b600482015230602482015260009073b2Bcd028F53637a4FC4E06C52d247F38f44cBe4d9063881107d990604401606060405180830381865af4158015620006e0573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620007069190620026fe565b9050600046883503620007e757620007256040890160208a016200201e565b905060005b8551811015620007e057816001600160a01b031663f242432a30898985815181106200075a576200075a62002765565b602002602001015189868151811062000777576200077762002765565b60200260200101516040518563ffffffff1660e01b8152600401620007a094939291906200277b565b600060405180830381600087803b158015620007bb57600080fd5b505af1158015620007d0573d6000803e3d6000fd5b505050508060010190506200072a565b50620008ce565b620007fc620007f68962002868565b62001392565b905060005b8551811015620008cc57816001600160a01b031663156e29f68888848151811062000830576200083062002765565b60200260200101518885815181106200084d576200084d62002765565b60209081029190910101516040516001600160e01b031960e086901b1681526001600160a01b03909316600484015260248301919091526044820152606401600060405180830381600087803b158015620008a757600080fd5b505af1158015620008bc573d6000803e3d6000fd5b5050505080600101905062000801565b505b620008e36001600160a01b03871634620013d3565b856001600160a01b0316876001600160a01b031683600001517f0f60c37489e435ed8490c30b01c1fa57e62510e88b351b75796ad3d95babe6b18560400151858a8a604051620009379493929190620028b3565b60405180910390a45050506200094c60018055565b5050505050565b6200095d62001337565b6562726964676560d01b62000974816001620011fa565b6001600160a01b0316336001600160a01b031614620009a657604051630d85cccf60e11b815260040160405180910390fd5b60008080620009ba610140860186620028f3565b620009ca9160049082906200293c565b810190620009d9919062002968565b9450945050509250600073b2Bcd028F53637a4FC4E06C52d247F38f44cBe4d632c6a56af8762000a146562726964676560d01b6000620011fa565b87602001516040518463ffffffff1660e01b815260040162000a399392919062002a2c565b602060405180830381865af415801562000a57573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062000a7d919062002b86565b6020808601516001600160a01b0316600090815260c9909152604090205490915060ff161562000b915760005b835181101562000b8a5760208501516001600160a01b031663156e29f662000ad960a08a0160808b016200201e565b86848151811062000aee5762000aee62002765565b602002602001015186858151811062000b0b5762000b0b62002765565b60209081029190910101516040516001600160e01b031960e086901b1681526001600160a01b03909316600484015260248301919091526044820152606401600060405180830381600087803b15801562000b6557600080fd5b505af115801562000b7a573d6000803e3d6000fd5b5050505080600101905062000aaa565b5062000c61565b60005b835181101562000c5f5760208501516001600160a01b031663f242432a3062000bc460a08b0160808c016200201e565b87858151811062000bd95762000bd962002765565b602002602001015187868151811062000bf65762000bf662002765565b60200260200101516040518563ffffffff1660e01b815260040162000c1f94939291906200277b565b600060405180830381600087803b15801562000c3a57600080fd5b505af115801562000c4f573d6000803e3d6000fd5b5050505080600101905062000b94565b505b62000c8c60e087013562000c7c60a0890160808a016200201e565b6001600160a01b031690620013d3565b62000c9e60a08701608088016200201e565b6001600160a01b0316817fe8449897bd3c926a272780c39ba13e77bf7a2c823479a75bfbc13ef631183dfd8660200151868660405162000ce19392919062002ba0565b60405180910390a3505050505062000cf860018055565b50565b600062000d0a8484846200149a565b90505b9392505050565b62000d1e620012bc565b62000d2a600062001554565b565b62000d3662001337565b60808101516060820151604051636030ce6160e11b815273b2Bcd028F53637a4FC4E06C52d247F38f44cBe4d9263c0619cc29262000d7a9260009060040162002be4565b60006040518083038186803b15801562000d9357600080fd5b505af415801562000da8573d6000803e3d6000fd5b5050505073b2Bcd028F53637a4FC4E06C52d247F38f44cBe4d6393522e3e62000de883600001516c195c98cc4c4d4d57dd985d5b1d609a1b600062000cfb565b602084015160408086015190516001600160e01b031960e086901b1681526001600160a01b039384166004820152918316602483015291909116604482015260640160006040518083038186803b15801562000e4357600080fd5b505af415801562000e58573d6000803e3d6000fd5b505050604082015162000e7d91506001600160a01b0316636cdb3d1360e11b620015a6565b62000e9b57604051633ee915f560e11b815260040160405180910390fd5b60808082015160408084015160608086015183516101808101855260008082526020820181905294810185905280830185905295860184905260a0860184905260c0860184905260e086018490526101008601849052610120860193909352610140850181905261016085015291928451606082015262000f1d338662001623565b610140820152336080820152606081015162000f4c906c195c98cc4c4d4d57dd985d5b1d609a1b600062000cfb565b6001600160a01b031660a08083019190915285015161012082015260c085015162000f78903462002c20565b60e08083019190915260c08087015161010080850191909152918701516001600160a01b031690830152850151610160820152600062000fc26562726964676560d01b82620011fa565b6001600160a01b0316634c1888bc34846040518363ffffffff1660e01b815260040162000ff0919062002c42565b60206040518083038185885af11580156200100f573d6000803e3d6000fd5b50505050506040513d601f19601f8201168201806040525081019062001036919062002b86565b905085602001516001600160a01b031682608001516001600160a01b0316827f5e54276405062454e6226625b28a6fea0a838d6b054e38955667234afb3345a3856060015188888b604051620010909493929190620028b3565b60405180910390a4505050505062000cf860018055565b60ca6020526000908152604090208054600182015460028301805492936001600160a01b0390921692620010db9062002d2b565b80601f0160208091040260200160405190810160405280929190818152602001828054620011099062002d2b565b80156200115a5780601f106200112e576101008083540402835291602001916200115a565b820191906000526020600020905b8154815290600101906020018083116200113c57829003601f168201915b505050505090806003018054620011719062002d2b565b80601f01602080910402602001604051908101604052809291908181526020018280546200119f9062002d2b565b8015620011f05780601f10620011c457610100808354040283529160200191620011f0565b820191906000526020600020905b815481529060010190602001808311620011d257829003601f168201915b5050505050905084565b600062000d0d4684846200149a565b62001213620012bc565b6001600160a01b0381166200127a5760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b6064820152608401620005a1565b62000cf88162001554565b60006001600160e01b03198216630271189760e51b14806200048257506301ffc9a760e01b6001600160e01b031983161462000482565b6065546001600160a01b0316331462000d2a5760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401620005a1565b6200132262001b2d565b6200132c62001b61565b62000cf88162001b95565b6002600154036200138b5760405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c006044820152606401620005a1565b6002600155565b8051600090815260cb60209081526040808320828501516001600160a01b0390811685529252909120541680620013ce57620004828262001bdf565b919050565b801580620013e857506001600160a01b038216155b15620013f2575050565b6000826001600160a01b03168260405160006040518083038185875af1925050503d806000811462001441576040519150601f19603f3d011682016040523d82523d6000602084013e62001446565b606091505b50509050806200148f5760405162461bcd60e51b8152602060048201526013602482015272115512081d1c985b9cd9995c8819985a5b1959606a1b6044820152606401620005a1565b505050565b60018055565b60975460405163195ac1a960e21b815260048101859052602481018490526000916001600160a01b03169063656b06a490604401602060405180830381865afa158015620014ec573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062001512919062002d67565b9050811580156200152a57506001600160a01b038116155b1562000d0d57604051631467050360e21b81526004810185905260248101849052604401620005a1565b606580546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b6040516301ffc9a760e01b81526001600160e01b0319821660048201526000906001600160a01b038416906301ffc9a790602401602060405180830381865afa92505050801562001616575060408051601f3d908101601f19168201909252620016139181019062002d87565b60015b1562000482579392505050565b604080516080810182526000808252602082015260609181018290528082018290526040808401516001600160a01b0316600090815260c9602052205460ff1615620018c7576040808401516001600160a01b03908116600090815260ca6020908152908390208351608081018552815481526001820154909316918301919091526002810180549293919291840191620016be9062002d2b565b80601f0160208091040260200160405190810160405280929190818152602001828054620016ec9062002d2b565b80156200173d5780601f1062001711576101008083540402835291602001916200173d565b820191906000526020600020905b8154815290600101906020018083116200171f57829003601f168201915b50505050508152602001600382018054620017589062002d2b565b80601f0160208091040260200160405190810160405280929190818152602001828054620017869062002d2b565b8015620017d75780601f10620017ab57610100808354040283529160200191620017d7565b820191906000526020600020905b815481529060010190602001808311620017b957829003601f168201915b505050505081525050905060005b836060015151811015620018c05783604001516001600160a01b031663f5298aca868660600151848151811062001820576200182062002765565b60200260200101518760800151858151811062001841576200184162002765565b60209081029190910101516040516001600160e01b031960e086901b1681526001600160a01b03909316600484015260248301919091526044820152606401600060405180830381600087803b1580156200189b57600080fd5b505af1158015620018b0573d6000803e3d6000fd5b50505050806001019050620017e5565b5062001ac6565b604051806080016040528046815260200184604001516001600160a01b03168152602001604051806020016040528060008152508152602001604051806020016040528060008152508152509050600083604001519050806001600160a01b03166306fdde036040518163ffffffff1660e01b8152600401600060405180830381865afa9250505080156200198057506040513d6000823e601f3d908101601f191682016040526200197d919081019062002da7565b60015b156200198c5760608301525b806001600160a01b03166395d89b416040518163ffffffff1660e01b8152600401600060405180830381865afa925050508015620019ee57506040513d6000823e601f3d908101601f19168201604052620019eb919081019062002da7565b60015b15620019fa5760408301525b60005b84606001515181101562001ac35784604001516001600160a01b031663f242432a33308860600151858151811062001a395762001a3962002765565b60200260200101518960800151868151811062001a5a5762001a5a62002765565b60200260200101516040518563ffffffff1660e01b815260040162001a8394939291906200277b565b600060405180830381600087803b15801562001a9e57600080fd5b505af115801562001ab3573d6000803e3d6000fd5b50505050806001019050620019fd565b50505b6020830151606084015160808501516040516320b8155960e01b9362001af39386938a9360240162002e74565b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b031990931692909217909152949350505050565b600054610100900460ff1662001b575760405162461bcd60e51b8152600401620005a19062002ed6565b62000d2a62001e58565b600054610100900460ff1662001b8b5760405162461bcd60e51b8152600401620005a19062002ed6565b62000d2a62001e82565b6001600160a01b03811662001bbd57604051634d084d8560e11b815260040160405180910390fd5b609780546001600160a01b0319166001600160a01b0392909216919091179055565b60008062001c3c60008460405160200162001bfb919062002f21565b604051602081830303815290604052805190602001206040518060200162001c239062001fc1565b601f1982820381018352601f9091011660405262001eb7565b905073b2Bcd028F53637a4FC4E06C52d247F38f44cBe4d6378adc0d68262001c6c6065546001600160a01b031690565b60975460208089015189516040808c015160608d0151915163689ccd8d60e11b9662001ca8966001600160a01b03909116959493910162002f36565b60408051601f198184030181529082905262001cc8929160200162002f7f565b6040516020818303038152906040526040518463ffffffff1660e01b815260040162001cf79392919062002fb2565b602060405180830381865af415801562001d15573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062001d3b919062002d67565b6001600160a01b03818116600090815260c9602090815260408083208054600160ff19909116811790915560ca835292819020885181559188015192820180546001600160a01b03191693909416929092179092558501519193508491600282019062001da9908262003032565b506060820151600382019062001dc0908262003032565b50508351600090815260cb6020908152604080832082880180516001600160a01b039081168652919093529281902080546001600160a01b031916878516908117909155915187518289015160608a015193519496509190941693927f2da3c4d305298f6df3653c23d98b4c055f72f7e6f981b2c477ccbec92b1ee5799262001e4a9291620030fe565b60405180910390a450919050565b600054610100900460ff16620014945760405162461bcd60e51b8152600401620005a19062002ed6565b600054610100900460ff1662001eac5760405162461bcd60e51b8152600401620005a19062002ed6565b62000d2a3362001554565b60008347101562001f0b5760405162461bcd60e51b815260206004820152601d60248201527f437265617465323a20696e73756666696369656e742062616c616e63650000006044820152606401620005a1565b815160000362001f5e5760405162461bcd60e51b815260206004820181905260248201527f437265617465323a2062797465636f6465206c656e677468206973207a65726f6044820152606401620005a1565b8282516020840186f590506001600160a01b03811662000d0d5760405162461bcd60e51b815260206004820152601960248201527f437265617465323a204661696c6564206f6e206465706c6f79000000000000006044820152606401620005a1565b612546806200312883390190565b60006020828403121562001fe257600080fd5b81356001600160e01b03198116811462000d0d57600080fd5b6001600160a01b038116811462000cf857600080fd5b8035620013ce8162001ffb565b6000602082840312156200203157600080fd5b813562000d0d8162001ffb565b634e487b7160e01b600052604160045260246000fd5b60405161012081016001600160401b03811182821017156200207a576200207a6200203e565b60405290565b604051601f8201601f191681016001600160401b0381118282101715620020ab57620020ab6200203e565b604052919050565b600082601f830112620020c557600080fd5b813560206001600160401b03821115620020e357620020e36200203e565b8160051b620020f482820162002080565b92835284810182019282810190878511156200210f57600080fd5b83870192505b84831015620021305782358252918301919083019062002115565b979650505050505050565b600080600080600060a086880312156200215457600080fd5b85356001600160401b03808211156200216c57600080fd5b908701906080828a0312156200218157600080fd5b909550602087013590620021958262001ffb565b909450604087013590620021a98262001ffb565b90935060608701359080821115620021c057600080fd5b620021ce89838a01620020b3565b93506080880135915080821115620021e557600080fd5b50620021f488828901620020b3565b9150509295509295909350565b6000602082840312156200221457600080fd5b81356001600160401b038111156200222b57600080fd5b8201610180818503121562000d0d57600080fd5b600080604083850312156200225357600080fd5b823591506020830135620022678162001ffb565b809150509250929050565b801515811462000cf857600080fd5b6000806000606084860312156200229757600080fd5b83359250602084013591506040840135620022b28162002272565b809150509250925092565b60006001600160401b03821115620022d957620022d96200203e565b50601f01601f191660200190565b600082601f830112620022f957600080fd5b8135620023106200230a82620022bd565b62002080565b8181528460208386010111156200232657600080fd5b816020850160208301376000918101602001919091529392505050565b6000602082840312156200235657600080fd5b81356001600160401b03808211156200236e57600080fd5b9083019061012082860312156200238457600080fd5b6200238e62002054565b82358152620023a06020840162002011565b6020820152620023b36040840162002011565b6040820152606083013582811115620023cb57600080fd5b620023d987828601620020b3565b606083015250608083013582811115620023f257600080fd5b6200240087828601620020b3565b60808301525060a083013560a082015260c083013560c08201526200242860e0840162002011565b60e082015261010080840135838111156200244257600080fd5b6200245088828701620022e7565b918301919091525095945050505050565b60005b838110156200247e57818101518382015260200162002464565b50506000910152565b60008151808452620024a181602086016020860162002461565b601f01601f19169290920160200192915050565b8481526001600160a01b0384166020820152608060408201819052600090620024e19083018562002487565b828103606084015262002130818562002487565b600080604083850312156200250957600080fd5b823591506020830135620022678162002272565b60008083601f8401126200253057600080fd5b5081356001600160401b038111156200254857600080fd5b6020830191508360208260051b85010111156200256457600080fd5b9250929050565b60008083601f8401126200257e57600080fd5b5081356001600160401b038111156200259657600080fd5b6020830191508360208285010111156200256457600080fd5b60008060008060008060008060a0898b031215620025cc57600080fd5b8835620025d98162001ffb565b97506020890135620025eb8162001ffb565b965060408901356001600160401b03808211156200260857600080fd5b620026168c838d016200251d565b909850965060608b01359150808211156200263057600080fd5b6200263e8c838d016200251d565b909650945060808b01359150808211156200265857600080fd5b50620026678b828c016200256b565b999c989b5096995094979396929594505050565b60008060008060008060a087890312156200269557600080fd5b8635620026a28162001ffb565b95506020870135620026b48162001ffb565b9450604087013593506060870135925060808701356001600160401b03811115620026de57600080fd5b620026ec89828a016200256b565b979a9699509497509295939492505050565b6000606082840312156200271157600080fd5b604051606081018181106001600160401b03821117156200273657620027366200203e565b6040528251815260208301516200274d8162001ffb565b60208201526040928301519281019290925250919050565b634e487b7160e01b600052603260045260246000fd5b6001600160a01b0394851681529290931660208301526040820152606081019190915260a06080820181905260009082015260c00190565b600060808284031215620027c657600080fd5b604051608081016001600160401b038282108183111715620027ec57620027ec6200203e565b816040528293508435835260208501359150620028098262001ffb565b81602084015260408501359150808211156200282457600080fd5b6200283286838701620022e7565b604084015260608501359150808211156200284c57600080fd5b506200285b85828601620022e7565b6060830152505092915050565b6000620004823683620027b3565b600081518084526020808501945080840160005b83811015620028a8578151875295820195908201906001016200288a565b509495945050505050565b8481526001600160a01b0384166020820152608060408201819052600090620028df9083018562002876565b828103606084015262002130818562002876565b6000808335601e198436030181126200290b57600080fd5b8301803591506001600160401b038211156200292657600080fd5b6020019150368190038213156200256457600080fd5b600080858511156200294d57600080fd5b838611156200295b57600080fd5b5050820193919092039150565b600080600080600060a086880312156200298157600080fd5b85356001600160401b03808211156200299957600080fd5b620029a789838a01620027b3565b965060208801359150620021958262001ffb565b6000808335601e19843603018112620029d357600080fd5b83016020810192503590506001600160401b03811115620029f357600080fd5b8036038213156200256457600080fd5b81835281816020850137506000828201602090810191909152601f909101601f19169091010190565b6060815283356060820152600062002a476020860162002011565b6001600160a01b038116608084015250604085013560a0830152606085013560c083015262002a796080860162002011565b6001600160a01b031660e083015262002a9560a0860162002011565b61010062002aad818501836001600160a01b03169052565b62002abb60c0880162002011565b915061012062002ad5818601846001600160a01b03169052565b610140925060e08801358386015261016082890135818701526101809250818901358387015262002b09848a018a620029bb565b94509150826101a087015262002b256101e08701858462002a03565b935062002b35818a018a620029bb565b9350915050605f19858403016101c086015262002b5483838362002a03565b935050505062002b6f60208301856001600160a01b03169052565b6001600160a01b0383166040830152949350505050565b60006020828403121562002b9957600080fd5b5051919050565b6001600160a01b038416815260606020820181905260009062002bc69083018562002876565b828103604084015262002bda818562002876565b9695505050505050565b60608152600062002bf9606083018662002876565b828103602084015262002c0d818662002876565b9150508215156040830152949350505050565b818103818111156200048257634e487b7160e01b600052601160045260246000fd5b60208152815160208201526000602083015162002c6a60408401826001600160a01b03169052565b506040830151606083015260608301516080830152608083015162002c9a60a08401826001600160a01b03169052565b5060a08301516001600160a01b03811660c08401525060c08301516001600160a01b03811660e08401525060e083015161010083810191909152830151610120808401919091528301516101408084019190915283015161018061016080850182905262002d0d6101a086018462002487565b90860151858203601f19018387015290925062002bda838262002487565b600181811c9082168062002d4057607f821691505b60208210810362002d6157634e487b7160e01b600052602260045260246000fd5b50919050565b60006020828403121562002d7a57600080fd5b815162000d0d8162001ffb565b60006020828403121562002d9a57600080fd5b815162000d0d8162002272565b60006020828403121562002dba57600080fd5b81516001600160401b0381111562002dd157600080fd5b8201601f8101841362002de357600080fd5b805162002df46200230a82620022bd565b81815285602083850101111562002e0a57600080fd5b62002e1d82602083016020860162002461565b95945050505050565b8051825260018060a01b036020820151166020830152600060408201516080604085015262002e59608085018262002487565b90506060830151848203606086015262002e1d828262002487565b60a08152600062002e8960a083018862002e26565b6001600160a01b03878116602085015286166040840152828103606084015262002eb4818662002876565b9050828103608084015262002eca818562002876565b98975050505050505050565b6020808252602b908201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960408201526a6e697469616c697a696e6760a81b606082015260800190565b60208152600062000d0d602083018462002e26565b6001600160a01b038681168252851660208201526040810184905260a06060820181905260009062002f6b9083018562002487565b828103608084015262002eca818562002487565b6001600160e01b031983168152815160009062002fa481600485016020870162002461565b919091016004019392505050565b6001600160a01b0384811682528316602082015260606040820181905260009062002e1d9083018462002487565b601f8211156200148f57600081815260208120601f850160051c81016020861015620030095750805b601f850160051c820191505b818110156200302a5782815560010162003015565b505050505050565b81516001600160401b038111156200304e576200304e6200203e565b62003066816200305f845462002d2b565b8462002fe0565b602080601f8311600181146200309e5760008415620030855750858301515b600019600386901b1c1916600185901b1785556200302a565b600085815260208120601f198616915b82811015620030cf57888601518255948401946001909101908401620030ae565b5085821015620030ee5787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b60408152600062003113604083018562002487565b828103602084015262002e1d81856200248756fe608060405234801561001057600080fd5b5061001961001e565b6100de565b600054610100900460ff161561008a5760405162461bcd60e51b815260206004820152602760248201527f496e697469616c697a61626c653a20636f6e747261637420697320696e697469604482015266616c697a696e6760c81b606482015260840160405180910390fd5b60005460ff90811610156100dc576000805460ff191660ff9081179091556040519081527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b565b61245880620000ee6000396000f3fe608060405234801561001057600080fd5b50600436106101415760003560e01c8063715018a6116100b8578063a86f9d9e1161007c578063a86f9d9e1461029c578063d1399b1a146102af578063e985e9c5146102c2578063f242432a146102fe578063f2fde38b14610311578063f5298aca1461032457600080fd5b8063715018a6146102545780637cf8ed0d1461025c5780638da5cb5b1461027057806395d89b4114610281578063a22cb4651461028957600080fd5b8063156e29f61161010a578063156e29f6146101cc5780632eb2c2d6146101df5780633ab76e9f146101f257806349d12605146102175780634e1273f4146102215780636c6563f61461024157600080fd5b8062fdd58e1461014657806301ffc9a71461016c5780630652b57a1461018f57806306fdde03146101a45780630e89341c146101b9575b600080fd5b6101596101543660046118e5565b610337565b6040519081526020015b60405180910390f35b61017f61017a366004611927565b6103d2565b6040519015158152602001610163565b6101a261019d366004611944565b610422565b005b6101ac61049b565b60405161016391906119b1565b6101ac6101c73660046119c4565b6104d1565b6101a26101da3660046119dd565b610565565b6101a26101ed366004611b5e565b61061b565b6097546001600160a01b03165b6040516001600160a01b039091168152602001610163565b61015961012e5481565b61023461022f366004611c0c565b610667565b6040516101639190611d14565b6101ff61024f366004611d3c565b610791565b6101a26107a8565b61012d546101ff906001600160a01b031681565b6065546001600160a01b03166101ff565b6101ac6107bc565b6101a2610297366004611d71565b61084b565b6101ff6102aa366004611da6565b61085a565b6101a26102bd366004611dc9565b610867565b61017f6102d0366004611e2c565b6001600160a01b03918216600090815260fc6020908152604080832093909416825291909152205460ff1690565b6101a261030c366004611e65565b610a10565b6101a261031f366004611944565b610a46565b6101a26103323660046119dd565b610abf565b60006001600160a01b0383166103a75760405162461bcd60e51b815260206004820152602a60248201527f455243313135353a2061646472657373207a65726f206973206e6f742061207660448201526930b634b21037bbb732b960b11b60648201526084015b60405180910390fd5b50600081815260fb602090815260408083206001600160a01b03861684529091529020545b92915050565b60006001600160e01b03198216636cdb3d1360e11b148061040357506001600160e01b031982166303a24d0760e21b145b806103cc57506301ffc9a760e01b6001600160e01b03198316146103cc565b61042a610b5b565b6001600160a01b03811661045157604051634d084d8560e11b815260040160405180910390fd5b609780546001600160a01b0319166001600160a01b0383169081179091556040517f399ded90cb5ed8d89ef7e76ff4af65c373f06d3bf5d7eef55f4228e7b702a18b90600090a250565b60606101306104ac61012e54610bb5565b6040516020016104bd929190611f08565b604051602081830303815290604052905090565b606060fd80546104e090611ece565b80601f016020809104026020016040519081016040528092919081815260200182805461050c90611ece565b80156105595780601f1061052e57610100808354040283529160200191610559565b820191906000526020600020905b81548152906001019060200180831161053c57829003601f168201915b50505050509050919050565b6c195c98cc4c4d4d57dd985d5b1d609a1b61058181600161085a565b6001600160a01b0316336001600160a01b0316146105b257604051630d85cccf60e11b815260040160405180910390fd5b6105cd84848460405180602001604052806000815250610c48565b60408051848152602081018490526001600160a01b038616916000917f9ed053bb818ff08b8353cd46f78db1f0799f31c9e4458fdb425c10eccd2efc4491015b60405180910390a350505050565b6001600160a01b038516331480610637575061063785336102d0565b6106535760405162461bcd60e51b815260040161039e90611f9e565b6106608585858585610d5e565b5050505050565b606081518351146106cc5760405162461bcd60e51b815260206004820152602960248201527f455243313135353a206163636f756e747320616e6420696473206c656e677468604482015268040dad2e6dac2e8c6d60bb1b606482015260840161039e565b6000835167ffffffffffffffff8111156106e8576106e8611a12565b604051908082528060200260200182016040528015610711578160200160208202803683370190505b50905060005b84518110156107895761075c85828151811061073557610735611fec565b602002602001015185838151811061074f5761074f611fec565b6020026020010151610337565b82828151811061076e5761076e611fec565b602090810291909101015261078281612018565b9050610717565b509392505050565b600061079e848484610f36565b90505b9392505050565b6107b0610b5b565b6107ba6000610fea565b565b61012f80546107ca90611ece565b80601f01602080910402602001604051908101604052809291908181526020018280546107f690611ece565b80156108435780601f1061081857610100808354040283529160200191610843565b820191906000526020600020905b81548152906001019060200180831161082657829003601f168201915b505050505081565b61085633838361103c565b5050565b60006107a1468484610f36565b600054610100900460ff16158080156108875750600054600160ff909116105b806108a15750303b1580156108a1575060005460ff166001145b6109045760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b606482015260840161039e565b6000805460ff191660011790558015610927576000805461ff0019166101001790555b6001600160a01b038516158061093b575083155b8061094557504684145b1561096357604051635d061ab760e11b815260040160405180910390fd5b61096c8661111c565b61098460405180602001604052806000815250611135565b61012d80546001600160a01b0319166001600160a01b03871617905561012e84905561012f6109b3848261207c565b506101306109c1838261207c565b508015610a08576000805461ff0019169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b505050505050565b306001600160a01b03851603610a3957604051636cfe544760e01b815260040160405180910390fd5b6106608585858585611165565b610a4e610b5b565b6001600160a01b038116610ab35760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b606482015260840161039e565b610abc81610fea565b50565b6c195c98cc4c4d4d57dd985d5b1d609a1b610adb81600161085a565b6001600160a01b0316336001600160a01b031614610b0c57604051630d85cccf60e11b815260040160405180910390fd5b610b178484846111aa565b60408051848152602081018490526000916001600160a01b038716917f9ed053bb818ff08b8353cd46f78db1f0799f31c9e4458fdb425c10eccd2efc44910161060d565b6065546001600160a01b031633146107ba5760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015260640161039e565b60606000610bc283611329565b600101905060008167ffffffffffffffff811115610be257610be2611a12565b6040519080825280601f01601f191660200182016040528015610c0c576020820181803683370190505b5090508181016020015b600019016f181899199a1a9b1b9c1cb0b131b232b360811b600a86061a8153600a8504945084610c1657509392505050565b6001600160a01b038416610ca85760405162461bcd60e51b815260206004820152602160248201527f455243313135353a206d696e7420746f20746865207a65726f206164647265736044820152607360f81b606482015260840161039e565b336000610cb485611401565b90506000610cc185611401565b9050600086815260fb602090815260408083206001600160a01b038b16845290915281208054879290610cf590849061213c565b909155505060408051878152602081018790526001600160a01b03808a1692600092918716917fc3d58168c5ae7397731d063d5bbf3d657854427343f4c083240f7aacaa2d0f62910160405180910390a4610d558360008989898961144c565b50505050505050565b8151835114610dc05760405162461bcd60e51b815260206004820152602860248201527f455243313135353a2069647320616e6420616d6f756e7473206c656e677468206044820152670dad2e6dac2e8c6d60c31b606482015260840161039e565b6001600160a01b038416610de65760405162461bcd60e51b815260040161039e9061214f565b3360005b8451811015610ed0576000858281518110610e0757610e07611fec565b602002602001015190506000858381518110610e2557610e25611fec565b602090810291909101810151600084815260fb835260408082206001600160a01b038e168352909352919091205490915081811015610e765760405162461bcd60e51b815260040161039e90612194565b600083815260fb602090815260408083206001600160a01b038e8116855292528083208585039055908b16825281208054849290610eb590849061213c565b9250508190555050505080610ec990612018565b9050610dea565b50846001600160a01b0316866001600160a01b0316826001600160a01b03167f4a39dc06d4c0dbc64b70af90fd698a233a518aa5d07e595d983b8c0526c8f7fb8787604051610f209291906121de565b60405180910390a4610a088187878787876115a7565b60975460405163195ac1a960e21b815260048101859052602481018490526000916001600160a01b03169063656b06a490604401602060405180830381865afa158015610f87573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610fab919061220c565b905081158015610fc257506001600160a01b038116155b156107a157604051631467050360e21b8152600481018590526024810184905260440161039e565b606580546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b816001600160a01b0316836001600160a01b0316036110af5760405162461bcd60e51b815260206004820152602960248201527f455243313135353a2073657474696e6720617070726f76616c20737461747573604482015268103337b91039b2b63360b91b606482015260840161039e565b6001600160a01b03838116600081815260fc6020908152604080832094871680845294825291829020805460ff191686151590811790915591519182527f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c31910160405180910390a3505050565b611124611662565b61112c611691565b610abc816116c0565b600054610100900460ff1661115c5760405162461bcd60e51b815260040161039e90612229565b610abc81611709565b6001600160a01b038516331480611181575061118185336102d0565b61119d5760405162461bcd60e51b815260040161039e90611f9e565b6106608585858585611739565b6001600160a01b03831661120c5760405162461bcd60e51b815260206004820152602360248201527f455243313135353a206275726e2066726f6d20746865207a65726f206164647260448201526265737360e81b606482015260840161039e565b33600061121884611401565b9050600061122584611401565b604080516020808201835260009182905288825260fb81528282206001600160a01b038b16835290522054909150848110156112af5760405162461bcd60e51b8152602060048201526024808201527f455243313135353a206275726e20616d6f756e7420657863656564732062616c604482015263616e636560e01b606482015260840161039e565b600086815260fb602090815260408083206001600160a01b038b81168086529184528285208a8703905582518b81529384018a90529092908816917fc3d58168c5ae7397731d063d5bbf3d657854427343f4c083240f7aacaa2d0f62910160405180910390a4604080516020810190915260009052610d55565b60008072184f03e93ff9f4daa797ed6e38ed64bf6a1f0160401b83106113685772184f03e93ff9f4daa797ed6e38ed64bf6a1f0160401b830492506040015b6d04ee2d6d415b85acef81000000008310611394576d04ee2d6d415b85acef8100000000830492506020015b662386f26fc1000083106113b257662386f26fc10000830492506010015b6305f5e10083106113ca576305f5e100830492506008015b61271083106113de57612710830492506004015b606483106113f0576064830492506002015b600a83106103cc5760010192915050565b6040805160018082528183019092526060916000919060208083019080368337019050509050828160008151811061143b5761143b611fec565b602090810291909101015292915050565b6001600160a01b0384163b15610a085760405163f23a6e6160e01b81526001600160a01b0385169063f23a6e61906114909089908990889088908890600401612274565b6020604051808303816000875af19250505080156114cb575060408051601f3d908101601f191682019092526114c8918101906122b9565b60015b611577576114d76122d6565b806308c379a00361151057506114eb6122f2565b806114f65750611512565b8060405162461bcd60e51b815260040161039e91906119b1565b505b60405162461bcd60e51b815260206004820152603460248201527f455243313135353a207472616e7366657220746f206e6f6e2d455243313135356044820152732932b1b2b4bb32b91034b6b83632b6b2b73a32b960611b606482015260840161039e565b6001600160e01b0319811663f23a6e6160e01b14610d555760405162461bcd60e51b815260040161039e9061237c565b6001600160a01b0384163b15610a085760405163bc197c8160e01b81526001600160a01b0385169063bc197c81906115eb90899089908890889088906004016123c4565b6020604051808303816000875af1925050508015611626575060408051601f3d908101601f19168201909252611623918101906122b9565b60015b611632576114d76122d6565b6001600160e01b0319811663bc197c8160e01b14610d555760405162461bcd60e51b815260040161039e9061237c565b600054610100900460ff166116895760405162461bcd60e51b815260040161039e90612229565b6107ba611867565b600054610100900460ff166116b85760405162461bcd60e51b815260040161039e90612229565b6107ba611894565b6001600160a01b0381166116e757604051634d084d8560e11b815260040160405180910390fd5b609780546001600160a01b0319166001600160a01b0392909216919091179055565b600054610100900460ff166117305760405162461bcd60e51b815260040161039e90612229565b610abc816118c4565b6001600160a01b03841661175f5760405162461bcd60e51b815260040161039e9061214f565b33600061176b85611401565b9050600061177885611401565b9050600086815260fb602090815260408083206001600160a01b038c168452909152902054858110156117bd5760405162461bcd60e51b815260040161039e90612194565b600087815260fb602090815260408083206001600160a01b038d8116855292528083208985039055908a168252812080548892906117fc90849061213c565b909155505060408051888152602081018890526001600160a01b03808b16928c821692918816917fc3d58168c5ae7397731d063d5bbf3d657854427343f4c083240f7aacaa2d0f62910160405180910390a461185c848a8a8a8a8a61144c565b505050505050505050565b600054610100900460ff1661188e5760405162461bcd60e51b815260040161039e90612229565b60018055565b600054610100900460ff166118bb5760405162461bcd60e51b815260040161039e90612229565b6107ba33610fea565b60fd610856828261207c565b6001600160a01b0381168114610abc57600080fd5b600080604083850312156118f857600080fd5b8235611903816118d0565b946020939093013593505050565b6001600160e01b031981168114610abc57600080fd5b60006020828403121561193957600080fd5b81356107a181611911565b60006020828403121561195657600080fd5b81356107a1816118d0565b60005b8381101561197c578181015183820152602001611964565b50506000910152565b6000815180845261199d816020860160208601611961565b601f01601f19169290920160200192915050565b6020815260006107a16020830184611985565b6000602082840312156119d657600080fd5b5035919050565b6000806000606084860312156119f257600080fd5b83356119fd816118d0565b95602085013595506040909401359392505050565b634e487b7160e01b600052604160045260246000fd5b601f8201601f1916810167ffffffffffffffff81118282101715611a4e57611a4e611a12565b6040525050565b600067ffffffffffffffff821115611a6f57611a6f611a12565b5060051b60200190565b600082601f830112611a8a57600080fd5b81356020611a9782611a55565b604051611aa48282611a28565b83815260059390931b8501820192828101915086841115611ac457600080fd5b8286015b84811015611adf5780358352918301918301611ac8565b509695505050505050565b600082601f830112611afb57600080fd5b813567ffffffffffffffff811115611b1557611b15611a12565b604051611b2c601f8301601f191660200182611a28565b818152846020838601011115611b4157600080fd5b816020850160208301376000918101602001919091529392505050565b600080600080600060a08688031215611b7657600080fd5b8535611b81816118d0565b94506020860135611b91816118d0565b9350604086013567ffffffffffffffff80821115611bae57600080fd5b611bba89838a01611a79565b94506060880135915080821115611bd057600080fd5b611bdc89838a01611a79565b93506080880135915080821115611bf257600080fd5b50611bff88828901611aea565b9150509295509295909350565b60008060408385031215611c1f57600080fd5b823567ffffffffffffffff80821115611c3757600080fd5b818501915085601f830112611c4b57600080fd5b81356020611c5882611a55565b604051611c658282611a28565b83815260059390931b8501820192828101915089841115611c8557600080fd5b948201945b83861015611cac578535611c9d816118d0565b82529482019490820190611c8a565b96505086013592505080821115611cc257600080fd5b50611ccf85828601611a79565b9150509250929050565b600081518084526020808501945080840160005b83811015611d0957815187529582019590820190600101611ced565b509495945050505050565b6020815260006107a16020830184611cd9565b80358015158114611d3757600080fd5b919050565b600080600060608486031215611d5157600080fd5b8335925060208401359150611d6860408501611d27565b90509250925092565b60008060408385031215611d8457600080fd5b8235611d8f816118d0565b9150611d9d60208401611d27565b90509250929050565b60008060408385031215611db957600080fd5b82359150611d9d60208401611d27565b600080600080600060a08688031215611de157600080fd5b8535611dec816118d0565b94506020860135611dfc816118d0565b935060408601359250606086013567ffffffffffffffff80821115611e2057600080fd5b611bdc89838a01611aea565b60008060408385031215611e3f57600080fd5b8235611e4a816118d0565b91506020830135611e5a816118d0565b809150509250929050565b600080600080600060a08688031215611e7d57600080fd5b8535611e88816118d0565b94506020860135611e98816118d0565b93506040860135925060608601359150608086013567ffffffffffffffff811115611ec257600080fd5b611bff88828901611aea565b600181811c90821680611ee257607f821691505b602082108103611f0257634e487b7160e01b600052602260045260246000fd5b50919050565b6000808454611f1681611ece565b60018281168015611f2e5760018114611f4357611f72565b60ff1984168752821515830287019450611f72565b8860005260208060002060005b85811015611f695781548a820152908401908201611f50565b50505082870194505b50506241c55b60e71b835250508351611f92816004840160208801611961565b01600401949350505050565b6020808252602e908201527f455243313135353a2063616c6c6572206973206e6f7420746f6b656e206f776e60408201526d195c881bdc88185c1c1c9bdd995960921b606082015260800190565b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052601160045260246000fd5b60006001820161202a5761202a612002565b5060010190565b601f82111561207757600081815260208120601f850160051c810160208610156120585750805b601f850160051c820191505b81811015610a0857828155600101612064565b505050565b815167ffffffffffffffff81111561209657612096611a12565b6120aa816120a48454611ece565b84612031565b602080601f8311600181146120df57600084156120c75750858301515b600019600386901b1c1916600185901b178555610a08565b600085815260208120601f198616915b8281101561210e578886015182559484019460019091019084016120ef565b508582101561212c5787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b808201808211156103cc576103cc612002565b60208082526025908201527f455243313135353a207472616e7366657220746f20746865207a65726f206164604082015264647265737360d81b606082015260800190565b6020808252602a908201527f455243313135353a20696e73756666696369656e742062616c616e636520666f60408201526939103a3930b739b332b960b11b606082015260800190565b6040815260006121f16040830185611cd9565b82810360208401526122038185611cd9565b95945050505050565b60006020828403121561221e57600080fd5b81516107a1816118d0565b6020808252602b908201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960408201526a6e697469616c697a696e6760a81b606082015260800190565b6001600160a01b03868116825285166020820152604081018490526060810183905260a0608082018190526000906122ae90830184611985565b979650505050505050565b6000602082840312156122cb57600080fd5b81516107a181611911565b600060033d11156122ef5760046000803e5060005160e01c5b90565b600060443d10156123005790565b6040516003193d81016004833e81513d67ffffffffffffffff816024840111818411171561233057505050505090565b82850191508151818111156123485750505050505090565b843d87010160208285010111156123625750505050505090565b61237160208286010187611a28565b509095945050505050565b60208082526028908201527f455243313135353a204552433131353552656365697665722072656a656374656040820152676420746f6b656e7360c01b606082015260800190565b6001600160a01b0386811682528516602082015260a0604082018190526000906123f090830186611cd9565b82810360608401526124028186611cd9565b905082810360808401526124168185611985565b9897505050505050505056fea2646970667358221220ee7f810feef1b382c8ef11eb3d6f0b845bda726deaea1e489e353f59025211be64736f6c63430008140033a2646970667358221220ea3ce65f4b921acac47f314a689a5ec16ba6d76cce7b6d58b3b98a450302fd6b64736f6c63430008140033", + "balance": "0x0" + }, + "0x1000777700000000000000000000000000000009": { + "contractName": "ERC1155VaultProxy", + "storage": { + "0x0000000000000000000000000000000000000000000000000000000000000000": "0x0000000000000000000000000000000000000000000000000000000000000001", + "0x0000000000000000000000000000000000000000000000000000000000000001": "0x0000000000000000000000000000000000000000000000000000000000000001", + "0x0000000000000000000000000000000000000000000000000000000000000065": "0x00000000000000000000000019b4f9c381c7927fe33d853e48b560141a380c44", + "0x0000000000000000000000000000000000000000000000000000000000000097": "0x0000000000000000000000001000777700000000000000000000000000000006", + "0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103": "0x113cE23c9e0cc50F4D41d7cE6DA02dCAFf8BFF85", + "0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc": "0x0000777700000000000000000000000000000009" + }, + "code": "0x60806040526004361061004e5760003560e01c80633659cfe6146100655780634f1ef286146100855780635c60da1b146100985780638f283970146100c9578063f851a440146100e95761005d565b3661005d5761005b6100fe565b005b61005b6100fe565b34801561007157600080fd5b5061005b6100803660046106b3565b610118565b61005b6100933660046106ce565b610155565b3480156100a457600080fd5b506100ad6101bc565b6040516001600160a01b03909116815260200160405180910390f35b3480156100d557600080fd5b5061005b6100e43660046106b3565b6101ed565b3480156100f557600080fd5b506100ad61020d565b61010661022e565b6101166101116102c3565b6102cd565b565b6101206102f1565b6001600160a01b0316330361014d5761014a81604051806020016040528060008152506000610324565b50565b61014a6100fe565b61015d6102f1565b6001600160a01b031633036101b4576101af8383838080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525060019250610324915050565b505050565b6101af6100fe565b60006101c66102f1565b6001600160a01b031633036101e2576101dd6102c3565b905090565b6101ea6100fe565b90565b6101f56102f1565b6001600160a01b0316330361014d5761014a8161034f565b60006102176102f1565b6001600160a01b031633036101e2576101dd6102f1565b6102366102f1565b6001600160a01b031633036101165760405162461bcd60e51b815260206004820152604260248201527f5472616e73706172656e745570677261646561626c6550726f78793a2061646d60448201527f696e2063616e6e6f742066616c6c6261636b20746f2070726f78792074617267606482015261195d60f21b608482015260a4015b60405180910390fd5b60006101dd6103a3565b3660008037600080366000845af43d6000803e8080156102ec573d6000f35b3d6000fd5b60007fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035b546001600160a01b0316919050565b61032d836103cb565b60008251118061033a5750805b156101af57610349838361040b565b50505050565b7f7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f6103786102f1565b604080516001600160a01b03928316815291841660208301520160405180910390a161014a81610437565b60007f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc610315565b6103d4816104e0565b6040516001600160a01b038216907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b90600090a250565b606061043083836040518060600160405280602781526020016107c560279139610574565b9392505050565b6001600160a01b03811661049c5760405162461bcd60e51b815260206004820152602660248201527f455243313936373a206e65772061646d696e20697320746865207a65726f206160448201526564647265737360d01b60648201526084016102ba565b807fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035b80546001600160a01b0319166001600160a01b039290921691909117905550565b6001600160a01b0381163b61054d5760405162461bcd60e51b815260206004820152602d60248201527f455243313936373a206e657720696d706c656d656e746174696f6e206973206e60448201526c1bdd08184818dbdb9d1c9858dd609a1b60648201526084016102ba565b807f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc6104bf565b6060600080856001600160a01b0316856040516105919190610775565b600060405180830381855af49150503d80600081146105cc576040519150601f19603f3d011682016040523d82523d6000602084013e6105d1565b606091505b50915091506105e2868383876105ec565b9695505050505050565b6060831561065b578251600003610654576001600160a01b0385163b6106545760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e747261637400000060448201526064016102ba565b5081610665565b610665838361066d565b949350505050565b81511561067d5781518083602001fd5b8060405162461bcd60e51b81526004016102ba9190610791565b80356001600160a01b03811681146106ae57600080fd5b919050565b6000602082840312156106c557600080fd5b61043082610697565b6000806000604084860312156106e357600080fd5b6106ec84610697565b9250602084013567ffffffffffffffff8082111561070957600080fd5b818601915086601f83011261071d57600080fd5b81358181111561072c57600080fd5b87602082850101111561073e57600080fd5b6020830194508093505050509250925092565b60005b8381101561076c578181015183820152602001610754565b50506000910152565b60008251610787818460208701610751565b9190910192915050565b60208152600082518060208401526107b0816040850160208701610751565b601f01601f1916919091016040019291505056fe416464726573733a206c6f772d6c6576656c2064656c65676174652063616c6c206661696c6564a264697066735822122013e4be7fbb9448379ca283101ef1037ca99a17f6ad00269fe32f79bcefab6e1864736f6c63430008140033", + "balance": "0x0" + }, + "0x0000777700000000000000000000000000000003": { + "contractName": "ProxiedEtherVault", + "storage": {}, + "code": "0x6080604052600436106100ab5760003560e01c80638da5cb5b116100645780638da5cb5b146101c0578063a86f9d9e146101de578063ba0bbd95146101fe578063d73bb3d01461021e578063f2fde38b1461023e578063fe9fbb801461025e57600080fd5b80630652b57a146100f457806319ab453c146101145780632d1fb389146101345780633ab76e9f146101545780636c6563f61461018b578063715018a6146101ab57600080fd5b366100ef5747158015906100cf575033600090815260c9602052604090205460ff16155b156100ed57604051634fa3f24560e01b815260040160405180910390fd5b005b600080fd5b34801561010057600080fd5b506100ed61010f366004610a8d565b6102a7565b34801561012057600080fd5b506100ed61012f366004610a8d565b610320565b34801561014057600080fd5b506100ed61014f366004610abf565b610438565b34801561016057600080fd5b506097546001600160a01b03165b6040516001600160a01b0390911681526020015b60405180910390f35b34801561019757600080fd5b5061016e6101a6366004610af4565b6104f1565b3480156101b757600080fd5b506100ed610508565b3480156101cc57600080fd5b506065546001600160a01b031661016e565b3480156101ea57600080fd5b5061016e6101f9366004610b29565b61051c565b34801561020a57600080fd5b506100ed610219366004610b4c565b610529565b34801561022a57600080fd5b506100ed610239366004610b78565b6105ee565b34801561024a57600080fd5b506100ed610259366004610a8d565b610671565b34801561026a57600080fd5b50610297610279366004610a8d565b6001600160a01b0316600090815260c9602052604090205460ff1690565b6040519015158152602001610182565b6102af6106e7565b6001600160a01b0381166102d657604051634d084d8560e11b815260040160405180910390fd5b609780546001600160a01b0319166001600160a01b0383169081179091556040517f399ded90cb5ed8d89ef7e76ff4af65c373f06d3bf5d7eef55f4228e7b702a18b90600090a250565b600054610100900460ff16158080156103405750600054600160ff909116105b8061035a5750303b15801561035a575060005460ff166001145b6103c25760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b60648201526084015b60405180910390fd5b6000805460ff1916600117905580156103e5576000805461ff0019166101001790555b6103ee82610741565b8015610434576000805461ff0019169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b5050565b6104406106e7565b6001600160a01b038216158061047457506001600160a01b038216600090815260c9602052604090205460ff161515811515145b1561049257604051631bebdfa760e21b815260040160405180910390fd5b6001600160a01b038216600081815260c96020908152604091829020805460ff191685151590811790915591519182527f4c0079b9bcd37cd5d29a13938effd97c881798cbc6bd52a3026a29d94b27d1bf910160405180910390a25050565b60006104fe84848461075a565b90505b9392505050565b6105106106e7565b61051a600061080e565b565b600061050146848461075a565b33600090815260c9602052604090205460ff1661055957604051634fa3f24560e01b815260040160405180910390fd5b610561610860565b80156105e5576001600160a01b03821661058e5760405163687563df60e01b815260040160405180910390fd5b6105a16001600160a01b038316826108b9565b816001600160a01b03167f7b9f77d35803cd201eac9c4ed739bc1fcd3f1be6ab8877d925d1e55517b6fd6e826040516105dc91815260200190565b60405180910390a25b61043460018055565b33600090815260c9602052604090205460ff1661061e57604051634fa3f24560e01b815260040160405180910390fd5b610626610860565b61063033826108b9565b60405181815233907f7b9f77d35803cd201eac9c4ed739bc1fcd3f1be6ab8877d925d1e55517b6fd6e9060200160405180910390a261066e60018055565b50565b6106796106e7565b6001600160a01b0381166106de5760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b60648201526084016103b9565b61066e8161080e565b6065546001600160a01b0316331461051a5760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657260448201526064016103b9565b61074961097a565b6107516109a9565b61066e816109d8565b60975460405163195ac1a960e21b815260048101859052602481018490526000916001600160a01b03169063656b06a490604401602060405180830381865afa1580156107ab573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906107cf9190610b91565b9050811580156107e657506001600160a01b038116155b1561050157604051631467050360e21b815260048101859052602481018490526044016103b9565b606580546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b6002600154036108b25760405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c0060448201526064016103b9565b6002600155565b8015806108cd57506001600160a01b038216155b156108d6575050565b6000826001600160a01b03168260405160006040518083038185875af1925050503d8060008114610923576040519150601f19603f3d011682016040523d82523d6000602084013e610928565b606091505b505090508061096f5760405162461bcd60e51b8152602060048201526013602482015272115512081d1c985b9cd9995c8819985a5b1959606a1b60448201526064016103b9565b505050565b60018055565b600054610100900460ff166109a15760405162461bcd60e51b81526004016103b990610bae565b61051a610a21565b600054610100900460ff166109d05760405162461bcd60e51b81526004016103b990610bae565b61051a610a48565b6001600160a01b0381166109ff57604051634d084d8560e11b815260040160405180910390fd5b609780546001600160a01b0319166001600160a01b0392909216919091179055565b600054610100900460ff166109745760405162461bcd60e51b81526004016103b990610bae565b600054610100900460ff16610a6f5760405162461bcd60e51b81526004016103b990610bae565b61051a3361080e565b6001600160a01b038116811461066e57600080fd5b600060208284031215610a9f57600080fd5b813561050181610a78565b80358015158114610aba57600080fd5b919050565b60008060408385031215610ad257600080fd5b8235610add81610a78565b9150610aeb60208401610aaa565b90509250929050565b600080600060608486031215610b0957600080fd5b8335925060208401359150610b2060408501610aaa565b90509250925092565b60008060408385031215610b3c57600080fd5b82359150610aeb60208401610aaa565b60008060408385031215610b5f57600080fd5b8235610b6a81610a78565b946020939093013593505050565b600060208284031215610b8a57600080fd5b5035919050565b600060208284031215610ba357600080fd5b815161050181610a78565b6020808252602b908201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960408201526a6e697469616c697a696e6760a81b60608201526080019056fea26469706673582212204c31d592cfc1ec7ee55355c17834d2e62089d97edf1b79bd01f89108c83709d164736f6c63430008140033", + "balance": "0x0" + }, + "0x1000777700000000000000000000000000000003": { + "contractName": "EtherVaultProxy", + "storage": { + "0x0000000000000000000000000000000000000000000000000000000000000000": "0x0000000000000000000000000000000000000000000000000000000000000001", + "0x0000000000000000000000000000000000000000000000000000000000000001": "0x0000000000000000000000000000000000000000000000000000000000000001", + "0x0000000000000000000000000000000000000000000000000000000000000065": "0x00000000000000000000000019b4f9c381c7927fe33d853e48b560141a380c44", + "0x0000000000000000000000000000000000000000000000000000000000000097": "0x0000000000000000000000001000777700000000000000000000000000000006", + "0xa738d3397c1eb96f671d7e4bd29cabbfa1a9c9ebc0db4142aee17809c43ab720": "0x0000000000000000000000000000000000000000000000000000000000000001", + "0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103": "0x113cE23c9e0cc50F4D41d7cE6DA02dCAFf8BFF85", + "0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc": "0x0000777700000000000000000000000000000003" + }, + "code": "0x60806040526004361061004e5760003560e01c80633659cfe6146100655780634f1ef286146100855780635c60da1b146100985780638f283970146100c9578063f851a440146100e95761005d565b3661005d5761005b6100fe565b005b61005b6100fe565b34801561007157600080fd5b5061005b6100803660046106b3565b610118565b61005b6100933660046106ce565b610155565b3480156100a457600080fd5b506100ad6101bc565b6040516001600160a01b03909116815260200160405180910390f35b3480156100d557600080fd5b5061005b6100e43660046106b3565b6101ed565b3480156100f557600080fd5b506100ad61020d565b61010661022e565b6101166101116102c3565b6102cd565b565b6101206102f1565b6001600160a01b0316330361014d5761014a81604051806020016040528060008152506000610324565b50565b61014a6100fe565b61015d6102f1565b6001600160a01b031633036101b4576101af8383838080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525060019250610324915050565b505050565b6101af6100fe565b60006101c66102f1565b6001600160a01b031633036101e2576101dd6102c3565b905090565b6101ea6100fe565b90565b6101f56102f1565b6001600160a01b0316330361014d5761014a8161034f565b60006102176102f1565b6001600160a01b031633036101e2576101dd6102f1565b6102366102f1565b6001600160a01b031633036101165760405162461bcd60e51b815260206004820152604260248201527f5472616e73706172656e745570677261646561626c6550726f78793a2061646d60448201527f696e2063616e6e6f742066616c6c6261636b20746f2070726f78792074617267606482015261195d60f21b608482015260a4015b60405180910390fd5b60006101dd6103a3565b3660008037600080366000845af43d6000803e8080156102ec573d6000f35b3d6000fd5b60007fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035b546001600160a01b0316919050565b61032d836103cb565b60008251118061033a5750805b156101af57610349838361040b565b50505050565b7f7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f6103786102f1565b604080516001600160a01b03928316815291841660208301520160405180910390a161014a81610437565b60007f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc610315565b6103d4816104e0565b6040516001600160a01b038216907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b90600090a250565b606061043083836040518060600160405280602781526020016107c560279139610574565b9392505050565b6001600160a01b03811661049c5760405162461bcd60e51b815260206004820152602660248201527f455243313936373a206e65772061646d696e20697320746865207a65726f206160448201526564647265737360d01b60648201526084016102ba565b807fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035b80546001600160a01b0319166001600160a01b039290921691909117905550565b6001600160a01b0381163b61054d5760405162461bcd60e51b815260206004820152602d60248201527f455243313936373a206e657720696d706c656d656e746174696f6e206973206e60448201526c1bdd08184818dbdb9d1c9858dd609a1b60648201526084016102ba565b807f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc6104bf565b6060600080856001600160a01b0316856040516105919190610775565b600060405180830381855af49150503d80600081146105cc576040519150601f19603f3d011682016040523d82523d6000602084013e6105d1565b606091505b50915091506105e2868383876105ec565b9695505050505050565b6060831561065b578251600003610654576001600160a01b0385163b6106545760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e747261637400000060448201526064016102ba565b5081610665565b610665838361066d565b949350505050565b81511561067d5781518083602001fd5b8060405162461bcd60e51b81526004016102ba9190610791565b80356001600160a01b03811681146106ae57600080fd5b919050565b6000602082840312156106c557600080fd5b61043082610697565b6000806000604084860312156106e357600080fd5b6106ec84610697565b9250602084013567ffffffffffffffff8082111561070957600080fd5b818601915086601f83011261071d57600080fd5b81358181111561072c57600080fd5b87602082850101111561073e57600080fd5b6020830194508093505050509250925092565b60005b8381101561076c578181015183820152602001610754565b50506000910152565b60008251610787818460208701610751565b9190910192915050565b60208152600082518060208401526107b0816040850160208701610751565b601f01601f1916919091016040019291505056fe416464726573733a206c6f772d6c6576656c2064656c65676174652063616c6c206661696c6564a264697066735822122013e4be7fbb9448379ca283101ef1037ca99a17f6ad00269fe32f79bcefab6e1864736f6c63430008140033", + "balance": "0xffffffffffffff21f494c589bfffffff" + }, + "0x0000777700000000000000000000000000000007": { + "contractName": "ProxiedSignalService", + "storage": {}, + "code": "0x608060405234801561001057600080fd5b50600436106100b45760003560e01c80636c6563f6116100715780636c6563f614610162578063715018a6146101755780638da5cb5b1461017d578063a86f9d9e1461018e578063f2fde38b146101a1578063f8f3f844146101b457600080fd5b80630652b57a146100b957806319ab453c146100ce57806332676bc6146100e15780633ab76e9f146101095780635221f6131461012e57806366ca2bc014610141575b600080fd5b6100cc6100c7366004611a23565b6101e0565b005b6100cc6100dc366004611a23565b610259565b6100f46100ef366004611a40565b610371565b60405190151581526020015b60405180910390f35b6097546001600160a01b03165b6040516001600160a01b039091168152602001610100565b6100f461013c366004611a6c565b6103e3565b61015461014f366004611b02565b61055d565b604051908152602001610100565b610116610170366004611b30565b6105a4565b6100cc6105bb565b6065546001600160a01b0316610116565b61011661019c366004611b65565b6105cf565b6100cc6101af366004611a23565b6105e5565b6101546101c2366004611a40565b6040805192835260208301919091526034600c830120918101905290565b6101e861065e565b6001600160a01b03811661020f57604051634d084d8560e11b815260040160405180910390fd5b609780546001600160a01b0319166001600160a01b0383169081179091556040517f399ded90cb5ed8d89ef7e76ff4af65c373f06d3bf5d7eef55f4228e7b702a18b90600090a250565b600054610100900460ff16158080156102795750600054600160ff909116105b806102935750303b158015610293575060005460ff166001145b6102fb5760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b60648201526084015b60405180910390fd5b6000805460ff19166001179055801561031e576000805461ff0019166101001790555b610327826106b8565b801561036d576000805461ff0019169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b5050565b6000826001600160a01b03811661039b576040516354cdfc8d60e11b815260040160405180910390fd5b8260008190036103be5760405163014f1da760e21b815260040160405180910390fd5b5050604080519384526020840192909252506034600c83012091810190525460011490565b6000854681036104065760405163e822b48d60e01b815260040160405180910390fd5b856001600160a01b03811661042e576040516354cdfc8d60e11b815260040160405180910390fd5b8560008190036104515760405163014f1da760e21b815260040160405180910390fd5b600061045f86880188611c01565b90506000610476647461696b6f60d81b60006105cf565b825160405163016674a560e21b815267ffffffffffffffff90911660048201526001600160a01b039190911690630599d29490602401602060405180830381865afa1580156104c9573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906104ed9190611cd6565b604080518c8152602081018c90526034600c820120818301909252606081019190915290915061054e90608001604051602081830303815290604052604051806040016040528060018152602001600160f81b8152508460200151846106d1565b9b9a5050505050505050505050565b6000818082036105805760405163014f1da760e21b815260040160405180910390fd5b50506040805133815260208101929092526034600c83012091810190526001815590565b60006105b18484846106f5565b90505b9392505050565b6105c361065e565b6105cd60006107a9565b565b60006105dc4684846106f5565b90505b92915050565b6105ed61065e565b6001600160a01b0381166106525760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b60648201526084016102f2565b61065b816107a9565b50565b6065546001600160a01b031633146105cd5760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657260448201526064016102f2565b6106c06107fb565b6106c861082a565b61065b81610859565b6000806106dd866108a2565b90506106eb818686866108d4565b9695505050505050565b60975460405163195ac1a960e21b815260048101859052602481018490526000916001600160a01b03169063656b06a490604401602060405180830381865afa158015610746573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061076a9190611cef565b90508115801561078157506001600160a01b038116155b156105b457604051631467050360e21b815260048101859052602481018490526044016102f2565b606580546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b600054610100900460ff166108225760405162461bcd60e51b81526004016102f290611d0c565b6105cd610911565b600054610100900460ff166108515760405162461bcd60e51b81526004016102f290611d0c565b6105cd61093e565b6001600160a01b03811661088057604051634d084d8560e11b815260040160405180910390fd5b609780546001600160a01b0319166001600160a01b0392909216919091179055565b606081805190602001206040516020016108be91815260200190565b6040516020818303038152906040529050919050565b60008060006108e487868661096e565b9150915081801561090657508051602080830191909120875191880191909120145b979650505050505050565b600054610100900460ff166109385760405162461bcd60e51b81526004016102f290611d0c565b60018055565b600054610100900460ff166109655760405162461bcd60e51b81526004016102f290611d0c565b6105cd336107a9565b60006060600061097d85610a49565b9050600080600061098f848a89610b42565b815192955090935091501580806109a35750815b6109ef5760405162461bcd60e51b815260206004820152601a60248201527f50726f76696465642070726f6f6620697320696e76616c69642e00000000000060448201526064016102f2565b600081610a0b5760405180602001604052806000815250610a37565b610a3786610a1a600188611d6d565b81518110610a2a57610a2a611d80565b6020026020010151610f62565b919b919a509098505050505050505050565b60606000610a5683610f89565b90506000815167ffffffffffffffff811115610a7457610a74611b91565b604051908082528060200260200182016040528015610ab957816020015b6040805180820190915260608082526020820152815260200190600190039081610a925790505b50905060005b8251811015610b3a576000610aec848381518110610adf57610adf611d80565b6020026020010151610fbc565b90506040518060400160405280610b0283610f89565b815260200182815250838381518110610b1d57610b1d611d80565b60200260200101819052505080610b3390611d96565b9050610abf565b509392505050565b600060606000806000610b548761104c565b90506000869050600080610b7b604051806040016040528060608152602001606081525090565b60005b8c51811015610f3a578c8181518110610b9957610b99611d80565b602002602001015191508284610baf9190611daf565b9350610bbc600188611daf565b965083600003610c19578482602001518051906020012014610c145760405162461bcd60e51b8152602060048201526011602482015270092dcecc2d8d2c840e4dedee840d0c2e6d607b1b60448201526064016102f2565b610cdb565b602082602001515110610c80578482602001518051906020012014610c145760405162461bcd60e51b815260206004820152601b60248201527f496e76616c6964206c6172676520696e7465726e616c2068617368000000000060448201526064016102f2565b84610c8e8360200151611185565b14610cdb5760405162461bcd60e51b815260206004820152601a60248201527f496e76616c696420696e7465726e616c206e6f6465206861736800000000000060448201526064016102f2565b610ce760106001611dc2565b60ff1682600001515103610d555785518414610f3a576000868581518110610d1157610d11611d80565b01602001518351805160f89290921c925060009183908110610d3557610d35611d80565b60200260200101519050610d48816111ad565b9650600194505050610f2a565b81515160011901610ee2576000610d6b836111e3565b9050600081600081518110610d8257610d82611d80565b016020015160f81c90506000610d99600283611ddb565b610da4906002611e0b565b90506000610db5848360ff16611207565b90506000610dc38b8a611207565b90506000610dd1838361123d565b905060ff851660021480610de8575060ff85166003145b15610e2257808351148015610dfd5750808251145b15610e0f57610e0c818b611daf565b99505b50600160ff1b9950610f3a945050505050565b60ff85161580610e35575060ff85166001145b15610e8b5782518114610e555750600160ff1b9950610f3a945050505050565b610e7c8860000151600181518110610e6f57610e6f611d80565b60200260200101516111ad565b9a509750610f2a945050505050565b60405162461bcd60e51b815260206004820152602660248201527f52656365697665642061206e6f6465207769746820616e20756e6b6e6f776e206044820152650e0e4caccd2f60d31b60648201526084016102f2565b60405162461bcd60e51b815260206004820152601d60248201527f526563656976656420616e20756e706172736561626c65206e6f64652e00000060448201526064016102f2565b610f3381611d96565b9050610b7e565b50600160ff1b841486610f4d8786611207565b909e909d50909b509950505050505050505050565b805180516060916105df91610f7990600190611d6d565b81518110610adf57610adf611d80565b6040805180820182526000808252602091820152815180830190925282518252808301908201526060906105df906112b7565b60606000806000610fcc856114a3565b919450925090506000816001811115610fe757610fe7611e24565b146110345760405162461bcd60e51b815260206004820152601860248201527f496e76616c696420524c502062797465732076616c75652e000000000000000060448201526064016102f2565b611043856020015184846117ed565b95945050505050565b606060008251600261105e9190611e3a565b67ffffffffffffffff81111561107657611076611b91565b6040519080825280601f01601f1916602001820160405280156110a0576020820181803683370190505b50905060005b835181101561117e5760048482815181106110c3576110c3611d80565b01602001516001600160f81b031916901c826110e0836002611e3a565b815181106110f0576110f0611d80565b60200101906001600160f81b031916908160001a905350601084828151811061111b5761111b611d80565b016020015161112d919060f81c611ddb565b60f81b8261113c836002611e3a565b611147906001611daf565b8151811061115757611157611d80565b60200101906001600160f81b031916908160001a90535061117781611d96565b90506110a6565b5092915050565b600060208251101561119957506020015190565b818060200190518101906105df9190611cd6565b600060606020836000015110156111ce576111c783611896565b90506111da565b6111d783610fbc565b90505b6105b481611185565b60606105df6112028360000151600081518110610adf57610adf611d80565b61104c565b60608251821061122657506040805160208101909152600081526105df565b6105dc83838486516112389190611d6d565b6118a1565b6000805b8084511180156112515750808351115b80156112a2575082818151811061126a5761126a611d80565b602001015160f81c60f81b6001600160f81b03191684828151811061129157611291611d80565b01602001516001600160f81b031916145b156105dc576112b081611d96565b9050611241565b60606000806112c5846114a3565b919350909150600190508160018111156112e1576112e1611e24565b1461132e5760405162461bcd60e51b815260206004820152601760248201527f496e76616c696420524c50206c6973742076616c75652e00000000000000000060448201526064016102f2565b6040805160208082526104208201909252600091816020015b60408051808201909152600080825260208201528152602001906001900390816113475790505090506000835b865181101561149857602082106113e05760405162461bcd60e51b815260206004820152602a60248201527f50726f766964656420524c50206c6973742065786365656473206d6178206c6960448201526939ba103632b733ba341760b11b60648201526084016102f2565b60008061141d6040518060400160405280858c600001516114019190611d6d565b8152602001858c602001516114169190611daf565b90526114a3565b5091509150604051806040016040528083836114399190611daf565b8152602001848b6020015161144e9190611daf565b81525085858151811061146357611463611d80565b6020908102919091010152611479600185611daf565b93506114858183611daf565b61148f9084611daf565b92505050611374565b508152949350505050565b6000806000808460000151116114fb5760405162461bcd60e51b815260206004820152601860248201527f524c50206974656d2063616e6e6f74206265206e756c6c2e000000000000000060448201526064016102f2565b6020840151805160001a607f81116115205760006001600094509450945050506117e6565b60b7811161159c576000611535608083611d6d565b90508087600001511161158a5760405162461bcd60e51b815260206004820152601960248201527f496e76616c696420524c502073686f727420737472696e672e0000000000000060448201526064016102f2565b600195509350600092506117e6915050565b60bf811161168b5760006115b160b783611d6d565b9050808760000151116116065760405162461bcd60e51b815260206004820152601f60248201527f496e76616c696420524c50206c6f6e6720737472696e67206c656e6774682e0060448201526064016102f2565b600183015160208290036101000a90046116208183611daf565b88511161166f5760405162461bcd60e51b815260206004820152601860248201527f496e76616c696420524c50206c6f6e6720737472696e672e000000000000000060448201526064016102f2565b61167a826001611daf565b96509450600093506117e692505050565b60f781116117065760006116a060c083611d6d565b9050808760000151116116f55760405162461bcd60e51b815260206004820152601760248201527f496e76616c696420524c502073686f7274206c6973742e00000000000000000060448201526064016102f2565b6001955093508492506117e6915050565b600061171360f783611d6d565b9050808760000151116117685760405162461bcd60e51b815260206004820152601d60248201527f496e76616c696420524c50206c6f6e67206c697374206c656e6774682e00000060448201526064016102f2565b600183015160208290036101000a90046117828183611daf565b8851116117ca5760405162461bcd60e51b815260206004820152601660248201527524b73b30b634b210292628103637b733903634b9ba1760511b60448201526064016102f2565b6117d5826001611daf565b96509450600193506117e692505050565b9193909250565b606060008267ffffffffffffffff81111561180a5761180a611b91565b6040519080825280601f01601f191660200182016040528015611834576020820181803683370190505b50905080516000036118475790506105b4565b8484016020820160005b85811015611869578281015182820152602001611851565b5060006001602087066020036101000a039050808251168119845116178252839450505050509392505050565b60606105df826119f8565b6060816118af81601f611daf565b10156118ee5760405162461bcd60e51b815260206004820152600e60248201526d736c6963655f6f766572666c6f7760901b60448201526064016102f2565b826118f98382611daf565b10156119385760405162461bcd60e51b815260206004820152600e60248201526d736c6963655f6f766572666c6f7760901b60448201526064016102f2565b6119428284611daf565b845110156119865760405162461bcd60e51b8152602060048201526011602482015270736c6963655f6f75744f66426f756e647360781b60448201526064016102f2565b6060821580156119a557604051915060008252602082016040526119ef565b6040519150601f8416801560200281840101858101878315602002848b0101015b818310156119de5780518352602092830192016119c6565b5050858452601f01601f1916604052505b50949350505050565b60606105df8260200151600084600001516117ed565b6001600160a01b038116811461065b57600080fd5b600060208284031215611a3557600080fd5b81356105dc81611a0e565b60008060408385031215611a5357600080fd5b8235611a5e81611a0e565b946020939093013593505050565b600080600080600060808688031215611a8457600080fd5b853594506020860135611a9681611a0e565b935060408601359250606086013567ffffffffffffffff80821115611aba57600080fd5b818801915088601f830112611ace57600080fd5b813581811115611add57600080fd5b896020828501011115611aef57600080fd5b9699959850939650602001949392505050565b600060208284031215611b1457600080fd5b5035919050565b80358015158114611b2b57600080fd5b919050565b600080600060608486031215611b4557600080fd5b8335925060208401359150611b5c60408501611b1b565b90509250925092565b60008060408385031215611b7857600080fd5b82359150611b8860208401611b1b565b90509250929050565b634e487b7160e01b600052604160045260246000fd5b6040805190810167ffffffffffffffff81118282101715611bca57611bca611b91565b60405290565b604051601f8201601f1916810167ffffffffffffffff81118282101715611bf957611bf9611b91565b604052919050565b60006020808385031215611c1457600080fd5b823567ffffffffffffffff80821115611c2c57600080fd5b9084019060408287031215611c4057600080fd5b611c48611ba7565b82358281168114611c5857600080fd5b81528284013582811115611c6b57600080fd5b80840193505086601f840112611c8057600080fd5b823582811115611c9257611c92611b91565b611ca4601f8201601f19168601611bd0565b92508083528785828601011115611cba57600080fd5b8085850186850137600090830185015292830152509392505050565b600060208284031215611ce857600080fd5b5051919050565b600060208284031215611d0157600080fd5b81516105dc81611a0e565b6020808252602b908201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960408201526a6e697469616c697a696e6760a81b606082015260800190565b634e487b7160e01b600052601160045260246000fd5b818103818111156105df576105df611d57565b634e487b7160e01b600052603260045260246000fd5b600060018201611da857611da8611d57565b5060010190565b808201808211156105df576105df611d57565b60ff81811683821601908111156105df576105df611d57565b600060ff831680611dfc57634e487b7160e01b600052601260045260246000fd5b8060ff84160691505092915050565b60ff82811682821603908111156105df576105df611d57565b634e487b7160e01b600052602160045260246000fd5b80820281158282048414176105df576105df611d5756fea2646970667358221220c8e5d2f03cdfd05271211f91051ea017cc78712d374c157f61c7f6293b421c5864736f6c63430008140033", + "balance": "0x0" + }, + "0x1000777700000000000000000000000000000007": { + "contractName": "SignalServiceProxy", + "storage": { + "0x0000000000000000000000000000000000000000000000000000000000000000": "0x0000000000000000000000000000000000000000000000000000000000000001", + "0x0000000000000000000000000000000000000000000000000000000000000001": "0x0000000000000000000000000000000000000000000000000000000000000001", + "0x0000000000000000000000000000000000000000000000000000000000000065": "0x00000000000000000000000019b4f9c381c7927fe33d853e48b560141a380c44", + "0x0000000000000000000000000000000000000000000000000000000000000097": "0x0000000000000000000000001000777700000000000000000000000000000006", + "0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103": "0x113cE23c9e0cc50F4D41d7cE6DA02dCAFf8BFF85", + "0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc": "0x0000777700000000000000000000000000000007" + }, + "code": "0x60806040526004361061004e5760003560e01c80633659cfe6146100655780634f1ef286146100855780635c60da1b146100985780638f283970146100c9578063f851a440146100e95761005d565b3661005d5761005b6100fe565b005b61005b6100fe565b34801561007157600080fd5b5061005b6100803660046106b3565b610118565b61005b6100933660046106ce565b610155565b3480156100a457600080fd5b506100ad6101bc565b6040516001600160a01b03909116815260200160405180910390f35b3480156100d557600080fd5b5061005b6100e43660046106b3565b6101ed565b3480156100f557600080fd5b506100ad61020d565b61010661022e565b6101166101116102c3565b6102cd565b565b6101206102f1565b6001600160a01b0316330361014d5761014a81604051806020016040528060008152506000610324565b50565b61014a6100fe565b61015d6102f1565b6001600160a01b031633036101b4576101af8383838080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525060019250610324915050565b505050565b6101af6100fe565b60006101c66102f1565b6001600160a01b031633036101e2576101dd6102c3565b905090565b6101ea6100fe565b90565b6101f56102f1565b6001600160a01b0316330361014d5761014a8161034f565b60006102176102f1565b6001600160a01b031633036101e2576101dd6102f1565b6102366102f1565b6001600160a01b031633036101165760405162461bcd60e51b815260206004820152604260248201527f5472616e73706172656e745570677261646561626c6550726f78793a2061646d60448201527f696e2063616e6e6f742066616c6c6261636b20746f2070726f78792074617267606482015261195d60f21b608482015260a4015b60405180910390fd5b60006101dd6103a3565b3660008037600080366000845af43d6000803e8080156102ec573d6000f35b3d6000fd5b60007fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035b546001600160a01b0316919050565b61032d836103cb565b60008251118061033a5750805b156101af57610349838361040b565b50505050565b7f7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f6103786102f1565b604080516001600160a01b03928316815291841660208301520160405180910390a161014a81610437565b60007f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc610315565b6103d4816104e0565b6040516001600160a01b038216907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b90600090a250565b606061043083836040518060600160405280602781526020016107c560279139610574565b9392505050565b6001600160a01b03811661049c5760405162461bcd60e51b815260206004820152602660248201527f455243313936373a206e65772061646d696e20697320746865207a65726f206160448201526564647265737360d01b60648201526084016102ba565b807fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035b80546001600160a01b0319166001600160a01b039290921691909117905550565b6001600160a01b0381163b61054d5760405162461bcd60e51b815260206004820152602d60248201527f455243313936373a206e657720696d706c656d656e746174696f6e206973206e60448201526c1bdd08184818dbdb9d1c9858dd609a1b60648201526084016102ba565b807f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc6104bf565b6060600080856001600160a01b0316856040516105919190610775565b600060405180830381855af49150503d80600081146105cc576040519150601f19603f3d011682016040523d82523d6000602084013e6105d1565b606091505b50915091506105e2868383876105ec565b9695505050505050565b6060831561065b578251600003610654576001600160a01b0385163b6106545760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e747261637400000060448201526064016102ba565b5081610665565b610665838361066d565b949350505050565b81511561067d5781518083602001fd5b8060405162461bcd60e51b81526004016102ba9190610791565b80356001600160a01b03811681146106ae57600080fd5b919050565b6000602082840312156106c557600080fd5b61043082610697565b6000806000604084860312156106e357600080fd5b6106ec84610697565b9250602084013567ffffffffffffffff8082111561070957600080fd5b818601915086601f83011261071d57600080fd5b81358181111561072c57600080fd5b87602082850101111561073e57600080fd5b6020830194508093505050509250925092565b60005b8381101561076c578181015183820152602001610754565b50506000910152565b60008251610787818460208701610751565b9190910192915050565b60208152600082518060208401526107b0816040850160208701610751565b601f01601f1916919091016040019291505056fe416464726573733a206c6f772d6c6576656c2064656c65676174652063616c6c206661696c6564a264697066735822122013e4be7fbb9448379ca283101ef1037ca99a17f6ad00269fe32f79bcefab6e1864736f6c63430008140033", + "balance": "0x0" + }, + "0x0000777700000000000000000000000000000005": { + "contractName": "RegularERC20", + "storage": { + "0x0000000000000000000000000000000000000000000000000000000000000003": "0x526567756c617245524332300000000000000000000000000000000000000018", + "0x0000000000000000000000000000000000000000000000000000000000000004": "0x52474c0000000000000000000000000000000000000000000000000000000006", + "0x0000000000000000000000000000000000000000000000000000000000000002": "0x00000000000000000000000000000000000000000000000000000000003e8000", + "0xc4fd933fc30203af5f8bd19ad30e064c96642a369b9fc4288ea95569541f4034": "0x00000000000000000000000000000000000000000000000000000000000fa000", + "0x967c153683def525608ec6efe0cac3319a9c97a6d4164fb43765c79311abffdc": "0x00000000000000000000000000000000000000000000000000000000000fa000", + "0x4b9b777e5e3847acfd8740f275a6896b3f3a10ae36191d153fdb5ef40d61b6c1": "0x00000000000000000000000000000000000000000000000000000000000fa000", + "0x9e7a5276a30d934c5fffd9ef18e4dcae10597352188cecf658522b6bf4d924d3": "0x00000000000000000000000000000000000000000000000000000000000fa000" + }, + "code": "0x608060405234801561001057600080fd5b50600436106100a95760003560e01c80633950935111610071578063395093511461012357806370a082311461013657806395d89b411461015f578063a457c2d714610167578063a9059cbb1461017a578063dd62ed3e1461018d57600080fd5b806306fdde03146100ae578063095ea7b3146100cc57806318160ddd146100ef57806323b872dd14610101578063313ce56714610114575b600080fd5b6100b66101a0565b6040516100c3919061069c565b60405180910390f35b6100df6100da366004610706565b610232565b60405190151581526020016100c3565b6002545b6040519081526020016100c3565b6100df61010f366004610730565b61024c565b604051601281526020016100c3565b6100df610131366004610706565b610270565b6100f361014436600461076c565b6001600160a01b031660009081526020819052604090205490565b6100b6610292565b6100df610175366004610706565b6102a1565b6100df610188366004610706565b610321565b6100f361019b36600461078e565b61032f565b6060600380546101af906107c1565b80601f01602080910402602001604051908101604052809291908181526020018280546101db906107c1565b80156102285780601f106101fd57610100808354040283529160200191610228565b820191906000526020600020905b81548152906001019060200180831161020b57829003601f168201915b5050505050905090565b60003361024081858561035a565b60019150505b92915050565b60003361025a85828561047e565b6102658585856104f8565b506001949350505050565b600033610240818585610283838361032f565b61028d91906107fb565b61035a565b6060600480546101af906107c1565b600033816102af828661032f565b9050838110156103145760405162461bcd60e51b815260206004820152602560248201527f45524332303a2064656372656173656420616c6c6f77616e63652062656c6f77604482015264207a65726f60d81b60648201526084015b60405180910390fd5b610265828686840361035a565b6000336102408185856104f8565b6001600160a01b03918216600090815260016020908152604080832093909416825291909152205490565b6001600160a01b0383166103bc5760405162461bcd60e51b8152602060048201526024808201527f45524332303a20617070726f76652066726f6d20746865207a65726f206164646044820152637265737360e01b606482015260840161030b565b6001600160a01b03821661041d5760405162461bcd60e51b815260206004820152602260248201527f45524332303a20617070726f766520746f20746865207a65726f206164647265604482015261737360f01b606482015260840161030b565b6001600160a01b0383811660008181526001602090815260408083209487168084529482529182902085905590518481527f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925910160405180910390a3505050565b600061048a848461032f565b905060001981146104f257818110156104e55760405162461bcd60e51b815260206004820152601d60248201527f45524332303a20696e73756666696369656e7420616c6c6f77616e6365000000604482015260640161030b565b6104f2848484840361035a565b50505050565b6001600160a01b03831661055c5760405162461bcd60e51b815260206004820152602560248201527f45524332303a207472616e736665722066726f6d20746865207a65726f206164604482015264647265737360d81b606482015260840161030b565b6001600160a01b0382166105be5760405162461bcd60e51b815260206004820152602360248201527f45524332303a207472616e7366657220746f20746865207a65726f206164647260448201526265737360e81b606482015260840161030b565b6001600160a01b038316600090815260208190526040902054818110156106365760405162461bcd60e51b815260206004820152602660248201527f45524332303a207472616e7366657220616d6f756e7420657863656564732062604482015265616c616e636560d01b606482015260840161030b565b6001600160a01b03848116600081815260208181526040808320878703905593871680835291849020805487019055925185815290927fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef910160405180910390a36104f2565b600060208083528351808285015260005b818110156106c9578581018301518582016040015282016106ad565b506000604082860101526040601f19601f8301168501019250505092915050565b80356001600160a01b038116811461070157600080fd5b919050565b6000806040838503121561071957600080fd5b610722836106ea565b946020939093013593505050565b60008060006060848603121561074557600080fd5b61074e846106ea565b925061075c602085016106ea565b9150604084013590509250925092565b60006020828403121561077e57600080fd5b610787826106ea565b9392505050565b600080604083850312156107a157600080fd5b6107aa836106ea565b91506107b8602084016106ea565b90509250929050565b600181811c908216806107d557607f821691505b6020821081036107f557634e487b7160e01b600052602260045260246000fd5b50919050565b8082018082111561024657634e487b7160e01b600052601160045260246000fdfea26469706673582212200c6a590d0220261e9ad2a153910ca40f21f69a425e5af92fee3a769ffc07753764736f6c63430008140033", + "balance": "0x0" + } +}
diff --git ethereum/go-ethereum/core/taiko_genesis/snaefellsjokull.json taikoxyz/taiko-geth/core/taiko_genesis/snaefellsjokull.json new file mode 100644 index 0000000000000000000000000000000000000000..01ce4e45c7d785d860e9e73a0645ac95da4d1729 --- /dev/null +++ taikoxyz/taiko-geth/core/taiko_genesis/snaefellsjokull.json @@ -0,0 +1,98 @@ +{ + "0x26250179C8e8E12104e556C4Cd03bCF4dabd51b9": { + "balance": "0xfffffffffffffacbbb7ca13a7fffffff" + }, + "0x9D716db5fF59f8dd903D44a56C41BcbE99bA666c": { + "balance": "0xfffffffffffffacbbb7ca13a7fffffff" + }, + "0x11f080128e565c07caD6fF7ADbb50Be1f62B84DB": { + "balance": "0xfffffffffffffacbbb7ca13a7fffffff" + }, + "0x617138FAdFEeE2E57f87cCba7dd6D6902aB0427d": { + "balance": "0xfffffffffffffacbbb7ca13a7fffffff" + }, + "0x5fa99CB8C2201B2a8CFfe2edfbF11ed6B78cb069": { + "balance": "0x8ac7230489e80000" + }, + "0xC5d653E17c24928B788a17838F11d2AcF0c922A3": { + "contractName": "LibTrieProof", + "storage": {}, + "code": "0x73000000000000000000000000000000000000000030146080604052600436106100355760003560e01c8063960304391461003a575b600080fd5b61004d6100483660046119a5565b61004f565b005b60008061005e83850185611b39565b6040517fffffffffffffffffffffffffffffffffffffffff00000000000000000000000060608b901b166020820152919350915060009081906100b490603401604051602081830303815290604052858c6101d3565b915091508161010a5760405162461bcd60e51b815260206004820152601960248201527f4c54503a696e76616c6964206163636f756e742070726f6f660000000000000060448201526064015b60405180910390fd5b6000610115826101fc565b9050600061013c8260028151811061012f5761012f611b9d565b6020026020010151610235565b905060006101758b60405160200161015691815260200190565b60405160208183030381529060405261016e8c610338565b888561034b565b9050806101c45760405162461bcd60e51b815260206004820152601960248201527f4c54503a696e76616c69642073746f726167652070726f6f66000000000000006044820152606401610101565b50505050505050505050505050565b6000606060006101e286610365565b90506101ef818686610397565b9250925050935093915050565b60408051808201825260008082526020918201528151808301909252825182528083019082015260609061022f90610472565b92915050565b600060218260000151111561028c5760405162461bcd60e51b815260206004820152601a60248201527f496e76616c696420524c5020627974657333322076616c75652e0000000000006044820152606401610101565b600080600061029a85610671565b9194509250905060008160018111156102b5576102b5611bcc565b146103025760405162461bcd60e51b815260206004820152601a60248201527f496e76616c696420524c5020627974657333322076616c75652e0000000000006044820152606401610101565b60008386602001516103149190611c2a565b8051909150602084101561032e5760208490036101000a90045b9695505050505050565b606061022f610346836109c2565b610b2d565b60008061035786610365565b905061032e81868686610b9c565b6060818051906020012060405160200161038191815260200190565b6040516020818303038152906040529050919050565b6000606060006103a685610bd9565b905060008060006103b8848a89610cd4565b815192955090935091501580806103cc5750815b6104185760405162461bcd60e51b815260206004820152601a60248201527f50726f76696465642070726f6f6620697320696e76616c69642e0000000000006044820152606401610101565b6000816104345760405180602001604052806000815250610460565b61046086610443600188611c42565b8151811061045357610453611b9d565b602002602001015161116f565b919b919a509098505050505050505050565b606060008061048084610671565b9193509091506001905081600181111561049c5761049c611bcc565b146104e95760405162461bcd60e51b815260206004820152601760248201527f496e76616c696420524c50206c6973742076616c75652e0000000000000000006044820152606401610101565b6040805160208082526104208201909252600091816020015b60408051808201909152600080825260208201528152602001906001900390816105025790505090506000835b865181101561066657602082106105ae5760405162461bcd60e51b815260206004820152602a60248201527f50726f766964656420524c50206c6973742065786365656473206d6178206c6960448201527f7374206c656e6774682e000000000000000000000000000000000000000000006064820152608401610101565b6000806105eb6040518060400160405280858c600001516105cf9190611c42565b8152602001858c602001516105e49190611c2a565b9052610671565b5091509150604051806040016040528083836106079190611c2a565b8152602001848b6020015161061c9190611c2a565b81525085858151811061063157610631611b9d565b6020908102919091010152610647600185611c2a565b93506106538183611c2a565b61065d9084611c2a565b9250505061052f565b508152949350505050565b6000806000808460000151116106c95760405162461bcd60e51b815260206004820152601860248201527f524c50206974656d2063616e6e6f74206265206e756c6c2e00000000000000006044820152606401610101565b6020840151805160001a607f81116106ee5760006001600094509450945050506109bb565b60b7811161076a576000610703608083611c42565b9050808760000151116107585760405162461bcd60e51b815260206004820152601960248201527f496e76616c696420524c502073686f727420737472696e672e000000000000006044820152606401610101565b600195509350600092506109bb915050565b60bf811161085957600061077f60b783611c42565b9050808760000151116107d45760405162461bcd60e51b815260206004820152601f60248201527f496e76616c696420524c50206c6f6e6720737472696e67206c656e6774682e006044820152606401610101565b600183015160208290036101000a90046107ee8183611c2a565b88511161083d5760405162461bcd60e51b815260206004820152601860248201527f496e76616c696420524c50206c6f6e6720737472696e672e00000000000000006044820152606401610101565b610848826001611c2a565b96509450600093506109bb92505050565b60f781116108d457600061086e60c083611c42565b9050808760000151116108c35760405162461bcd60e51b815260206004820152601760248201527f496e76616c696420524c502073686f7274206c6973742e0000000000000000006044820152606401610101565b6001955093508492506109bb915050565b60006108e160f783611c42565b9050808760000151116109365760405162461bcd60e51b815260206004820152601d60248201527f496e76616c696420524c50206c6f6e67206c697374206c656e6774682e0000006044820152606401610101565b600183015160208290036101000a90046109508183611c2a565b88511161099f5760405162461bcd60e51b815260206004820152601660248201527f496e76616c696420524c50206c6f6e67206c6973742e000000000000000000006044820152606401610101565b6109aa826001611c2a565b96509450600193506109bb92505050565b9193909250565b60606000826040516020016109d991815260200190565b604051602081830303815290604052905060005b6020811015610a4b57818181518110610a0857610a08611b9d565b01602001517fff000000000000000000000000000000000000000000000000000000000000001615610a3957610a4b565b80610a4381611c59565b9150506109ed565b6000610a58826020611c42565b67ffffffffffffffff811115610a7057610a70611a5f565b6040519080825280601f01601f191660200182016040528015610a9a576020820181803683370190505b50905060005b8151811015610b24578383610ab481611c59565b945081518110610ac657610ac6611b9d565b602001015160f81c60f81b828281518110610ae357610ae3611b9d565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a90535080610b1c81611c59565b915050610aa0565b50949350505050565b60608082516001148015610b5b5750608083600081518110610b5157610b51611b9d565b016020015160f81c105b15610b6757508161022f565b610b7383516080611199565b83604051602001610b85929190611ccd565b604051602081830303815290604052905092915050565b6000806000610bac878686610397565b91509150818015610bce57508051602080830191909120875191880191909120145b979650505050505050565b60606000610be6836101fc565b90506000815167ffffffffffffffff811115610c0457610c04611a5f565b604051908082528060200260200182016040528015610c4957816020015b6040805180820190915260608082526020820152815260200190600190039081610c225790505b50905060005b8251811015610ccc576000610c7c848381518110610c6f57610c6f611b9d565b6020026020010151611390565b90506040518060400160405280828152602001610c98836101fc565b815250838381518110610cad57610cad611b9d565b6020026020010181905250508080610cc490611c59565b915050610c4f565b509392505050565b60006060818080610ce487611420565b90506000869050600080610d0b604051806040016040528060608152602001606081525090565b60005b8c5181101561112b578c8181518110610d2957610d29611b9d565b602002602001015191508284610d3f9190611c2a565b9350610d4c600188611c2a565b965083610db057815180516020909101208514610dab5760405162461bcd60e51b815260206004820152601160248201527f496e76616c696420726f6f7420686173680000000000000000000000000000006044820152606401610101565b610e6d565b815151602011610e1257815180516020909101208514610dab5760405162461bcd60e51b815260206004820152601b60248201527f496e76616c6964206c6172676520696e7465726e616c206861736800000000006044820152606401610101565b84610e2083600001516115a3565b14610e6d5760405162461bcd60e51b815260206004820152601a60248201527f496e76616c696420696e7465726e616c206e6f646520686173680000000000006044820152606401610101565b610e7960106001611c2a565b8260200151511415610ef2578551841415610e935761112b565b6000868581518110610ea757610ea7611b9d565b602001015160f81c60f81b60f81c9050600083602001518260ff1681518110610ed257610ed2611b9d565b60200260200101519050610ee5816115cb565b9650600194505050611119565b600282602001515114156110d1576000610f0b83611601565b9050600081600081518110610f2257610f22611b9d565b016020015160f81c90506000610f39600283611d19565b610f44906002611d3b565b90506000610f55848360ff16611625565b90506000610f638b8a611625565b90506000610f71838361165b565b905060ff851660021480610f88575060ff85166003145b15610fde57808351148015610f9d5750808251145b15610faf57610fac818b611c2a565b99505b507f8000000000000000000000000000000000000000000000000000000000000000995061112b945050505050565b60ff85161580610ff1575060ff85166001145b15611063578251811461102d57507f8000000000000000000000000000000000000000000000000000000000000000995061112b945050505050565b611054886020015160018151811061104757611047611b9d565b60200260200101516115cb565b9a509750611119945050505050565b60405162461bcd60e51b815260206004820152602660248201527f52656365697665642061206e6f6465207769746820616e20756e6b6e6f776e2060448201527f70726566697800000000000000000000000000000000000000000000000000006064820152608401610101565b60405162461bcd60e51b815260206004820152601d60248201527f526563656976656420616e20756e706172736561626c65206e6f64652e0000006044820152606401610101565b8061112381611c59565b915050610d0e565b507f800000000000000000000000000000000000000000000000000000000000000084148661115a8786611625565b909e909d50909b509950505050505050505050565b6020810151805160609161022f9161118990600190611c42565b81518110610c6f57610c6f611b9d565b606080603884101561121857604080516001808252818301909252906020820181803683370190505090506111ce8385611d5e565b60f81b816000815181106111e4576111e4611b9d565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a905350611389565b600060015b6112278187611d83565b1561124d578161123681611c59565b9250611246905061010082611d97565b905061121d565b611258826001611c2a565b67ffffffffffffffff81111561127057611270611a5f565b6040519080825280601f01601f19166020018201604052801561129a576020820181803683370190505b5092506112a78583611d5e565b6112b2906037611d5e565b60f81b836000815181106112c8576112c8611b9d565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a905350600190505b818111611386576101006113108284611c42565b61131c90610100611ef4565b6113269088611d83565b6113309190611f00565b60f81b83828151811061134557611345611b9d565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a9053508061137e81611c59565b9150506112fc565b50505b9392505050565b606060008060006113a085610671565b9194509250905060008160018111156113bb576113bb611bcc565b146114085760405162461bcd60e51b815260206004820152601860248201527f496e76616c696420524c502062797465732076616c75652e00000000000000006044820152606401610101565b61141785602001518484611707565b95945050505050565b60606000825160026114329190611d97565b67ffffffffffffffff81111561144a5761144a611a5f565b6040519080825280601f01601f191660200182016040528015611474576020820181803683370190505b50905060005b835181101561159c57600484828151811061149757611497611b9d565b01602001517fff0000000000000000000000000000000000000000000000000000000000000016901c826114cc836002611d97565b815181106114dc576114dc611b9d565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a905350601084828151811061151f5761151f611b9d565b0160200151611531919060f81c611d19565b60f81b82611540836002611d97565b61154b906001611c2a565b8151811061155b5761155b611b9d565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a9053508061159481611c59565b91505061147a565b5092915050565b60006020825110156115b757506020015190565b8180602001905181019061022f9190611f14565b600060606020836000015110156115ec576115e5836117e6565b90506115f8565b6115f583611390565b90505b611389816115a3565b606061022f6116208360200151600081518110610c6f57610c6f611b9d565b611420565b606082518210611644575060408051602081019091526000815261022f565b61138983838486516116569190611c42565b6117f1565b6000805b80845111801561166f5750808351115b80156116f0575082818151811061168857611688611b9d565b602001015160f81c60f81b7effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff19168482815181106116c7576116c7611b9d565b01602001517fff0000000000000000000000000000000000000000000000000000000000000016145b1561138957806116ff81611c59565b91505061165f565b606060008267ffffffffffffffff81111561172457611724611a5f565b6040519080825280601f01601f19166020018201604052801561174e576020820181803683370190505b509050805160001415611762579050611389565b600061176e8587611c2a565b90506020820160005b611782602087611d83565b8110156117b95782518252611798602084611c2a565b92506117a5602083611c2a565b9150806117b181611c59565b915050611777565b5060006001602087066020036101000a039050808251168119845116178252839450505050509392505050565b606061022f8261198f565b6060816117ff81601f611c2a565b101561184d5760405162461bcd60e51b815260206004820152600e60248201527f736c6963655f6f766572666c6f770000000000000000000000000000000000006044820152606401610101565b826118588382611c2a565b10156118a65760405162461bcd60e51b815260206004820152600e60248201527f736c6963655f6f766572666c6f770000000000000000000000000000000000006044820152606401610101565b6118b08284611c2a565b845110156119005760405162461bcd60e51b815260206004820152601160248201527f736c6963655f6f75744f66426f756e64730000000000000000000000000000006044820152606401610101565b60608215801561191f5760405191506000825260208201604052610b24565b6040519150601f8416801560200281840101858101878315602002848b0101015b81831015611958578051835260209283019201611940565b5050858452601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0166040525050949350505050565b606061022f826020015160008460000151611707565b60008060008060008060a087890312156119be57600080fd5b86359550602087013573ffffffffffffffffffffffffffffffffffffffff811681146119e957600080fd5b94506040870135935060608701359250608087013567ffffffffffffffff80821115611a1457600080fd5b818901915089601f830112611a2857600080fd5b813581811115611a3757600080fd5b8a6020828501011115611a4957600080fd5b6020830194508093505050509295509295509295565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b600082601f830112611a9f57600080fd5b813567ffffffffffffffff80821115611aba57611aba611a5f565b604051601f83017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f01168101908282118183101715611b0057611b00611a5f565b81604052838152866020858801011115611b1957600080fd5b836020870160208301376000602085830101528094505050505092915050565b60008060408385031215611b4c57600080fd5b823567ffffffffffffffff80821115611b6457600080fd5b611b7086838701611a8e565b93506020850135915080821115611b8657600080fd5b50611b9385828601611a8e565b9150509250929050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60008219821115611c3d57611c3d611bfb565b500190565b600082821015611c5457611c54611bfb565b500390565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff821415611c8b57611c8b611bfb565b5060010190565b6000815160005b81811015611cb35760208185018101518683015201611c99565b81811115611cc2576000828601525b509290920192915050565b6000611ce2611cdc8386611c92565b84611c92565b949350505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b600060ff831680611d2c57611d2c611cea565b8060ff84160691505092915050565b600060ff821660ff841680821015611d5557611d55611bfb565b90039392505050565b600060ff821660ff84168060ff03821115611d7b57611d7b611bfb565b019392505050565b600082611d9257611d92611cea565b500490565b6000817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0483118215151615611dcf57611dcf611bfb565b500290565b600181815b80851115611e2d57817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff04821115611e1357611e13611bfb565b80851615611e2057918102915b93841c9390800290611dd9565b509250929050565b600082611e445750600161022f565b81611e515750600061022f565b8160018114611e675760028114611e7157611e8d565b600191505061022f565b60ff841115611e8257611e82611bfb565b50506001821b61022f565b5060208310610133831016604e8410600b8410161715611eb0575081810a61022f565b611eba8383611dd4565b807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff04821115611eec57611eec611bfb565b029392505050565b60006113898383611e35565b600082611f0f57611f0f611cea565b500690565b600060208284031215611f2657600080fd5b505191905056fea2646970667358221220f7f04c88df651530a5c547edaa8d0ac57b5adf851950adbf06f8245338f8d71564736f6c63430008090033", + "balance": "0x0" + }, + "0x8A9E82Ebf0E219BBdB4fBBd50FEd45d098a8Ba1e": { + "contractName": "LibBridgeRetry", + "storage": {}, + "code": "0x73000000000000000000000000000000000000000030146080604052600436106100355760003560e01c806346eb9db51461003a575b600080fd5b81801561004657600080fd5b5061005a6100553660046107f9565b61005c565b005b610140820135158061006b5750805b156101195761008060a0830160808401610880565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614610119576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600860248201527f423a64656e69656400000000000000000000000000000000000000000000000060448201526064015b60405180910390fd5b600061012c610127846109a8565b610432565b90506001600082815260018701602052604090205460ff16600381111561015557610155610aaa565b146101bc576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600a60248201527f423a6e6f74466f756e64000000000000000000000000000000000000000000006044820152606401610110565b6040517f461a447800000000000000000000000000000000000000000000000000000000815260206004820152600b60248201527f65746865725f7661756c74000000000000000000000000000000000000000000604482015260009073ffffffffffffffffffffffffffffffffffffffff86169063461a44789060640160206040518083038186803b15801561025257600080fd5b505afa158015610266573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061028a9190610ad9565b905073ffffffffffffffffffffffffffffffffffffffff81161561032d576040517f1efa4ec0000000000000000000000000000000000000000000000000000000008152610100850135600482015273ffffffffffffffffffffffffffffffffffffffff821690631efa4ec090602401600060405180830381600087803b15801561031457600080fd5b505af1158015610328573d6000803e3d6000fd5b505050505b6103418661033a866109a8565b845a610462565b156103575761035286836002610634565b61042a565b82156103e95761036986836003610634565b60008061037c60e0870160c08801610880565b73ffffffffffffffffffffffffffffffffffffffff16146103ac576103a760e0860160c08701610880565b6103bc565b6103bc60a0860160808701610880565b90506103e373ffffffffffffffffffffffffffffffffffffffff8216610100870135610700565b5061042a565b73ffffffffffffffffffffffffffffffffffffffff81161561042a5761042a73ffffffffffffffffffffffffffffffffffffffff8216610100860135610700565b505050505050565b6000816040516020016104459190610b70565b604051602081830303815290604052805190602001209050919050565b60008082116104cd576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600a60248201527f423a6761734c696d6974000000000000000000000000000000000000000000006044820152606401610110565b6040805160608101825284815260208681015173ffffffffffffffffffffffffffffffffffffffff90811691830182905287840151928401839052600389018790556004890180547fffffffffffffffffffffffff000000000000000000000000000000000000000016909217909155600588019190915560a08601516101008701516101608801519351919092169285929161056a9190610d04565b600060405180830381858888f193505050503d80600081146105a8576040519150601f19603f3d011682016040523d82523d6000602084013e6105ad565b606091505b5050604080516060810182526001808252602082018190527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff91909201819052600388018290556004880180547fffffffffffffffffffffffff00000000000000000000000000000000000000001690921790915560059096019590955550929392505050565b80600381111561064657610646610aaa565b600083815260018501602052604090205460ff16600381111561066b5761066b610aaa565b146106fb57600082815260018085016020526040909120805483927fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00909116908360038111156106bd576106bd610aaa565b0217905550817f6c51882bc2ed67617f77a1e9b9a25d2caad8448647ecb093b357a603b2575634826040516106f29190610d20565b60405180910390a25b505050565b80156107d05760008273ffffffffffffffffffffffffffffffffffffffff168260405160006040518083038185875af1925050503d8060008114610760576040519150601f19603f3d011682016040523d82523d6000602084013e610765565b606091505b50509050806106fb576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601360248201527f455448207472616e73666572206661696c6564000000000000000000000000006044820152606401610110565b5050565b73ffffffffffffffffffffffffffffffffffffffff811681146107f657600080fd5b50565b6000806000806080858703121561080f57600080fd5b843593506020850135610821816107d4565b9250604085013567ffffffffffffffff81111561083d57600080fd5b85016101a0818803121561085057600080fd5b91506060850135801515811461086557600080fd5b939692955090935050565b803561087b816107d4565b919050565b60006020828403121561089257600080fd5b813561089d816107d4565b9392505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6040516101a0810167ffffffffffffffff811182821017156108f7576108f76108a4565b60405290565b600082601f83011261090e57600080fd5b813567ffffffffffffffff80821115610929576109296108a4565b604051601f83017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f0116810190828211818310171561096f5761096f6108a4565b8160405283815286602085880101111561098857600080fd5b836020870160208301376000602085830101528094505050505092915050565b60006101a082360312156109bb57600080fd5b6109c36108d3565b823581526109d360208401610870565b602082015260408301356040820152606083013560608201526109f860808401610870565b6080820152610a0960a08401610870565b60a0820152610a1a60c08401610870565b60c082015260e083810135908201526101008084013590820152610120808401359082015261014080840135908201526101608084013567ffffffffffffffff80821115610a6757600080fd5b610a73368388016108fd565b83850152610180925082860135915080821115610a8f57600080fd5b50610a9c368287016108fd565b918301919091525092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b600060208284031215610aeb57600080fd5b815161089d816107d4565b60005b83811015610b11578181015183820152602001610af9565b83811115610b20576000848401525b50505050565b60008151808452610b3e816020860160208601610af6565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b60408152601460408201527f5441494b4f5f4252494447455f4d4553534147450000000000000000000000006060820152608060208201528151608082015260006020830151610bd860a084018273ffffffffffffffffffffffffffffffffffffffff169052565b50604083015160c0830152606083015160e08301526080830151610100610c168185018373ffffffffffffffffffffffffffffffffffffffff169052565b60a08501519150610120610c418186018473ffffffffffffffffffffffffffffffffffffffff169052565b60c08601519250610140610c6c8187018573ffffffffffffffffffffffffffffffffffffffff169052565b60e0870151610160878101919091529287015161018080880191909152918701516101a080880191909152908701516101c0870152918601516101e0860192909252909150610cbf610220850183610b26565b908501518482037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8001610200860152909150610cfb8282610b26565b95945050505050565b60008251610d16818460208701610af6565b9190910192915050565b6020810160048310610d5b577f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b9190529056fea2646970667358221220ef77fa8abe15893a91d42d96908d637a4ee0724e51d926aff79565effe20a22c64736f6c63430008090033", + "balance": "0x0" + }, + "0xf7c52068c40213E7C49313B0d6FCc11Cb2C45dbF": { + "contractName": "LibBridgeProcess", + "storage": {}, + "code": "0x73000000000000000000000000000000000000000030146080604052600436106100355760003560e01c8063c0249e2d1461003a575b600080fd5b81801561004657600080fd5b5061005a6100553660046119c3565b61005c565b005b61014083013561010f5761007660a0840160808501611a8d565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161461010f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600b60248201527f423a666f7262696464656e00000000000000000000000000000000000000000060448201526064015b60405180910390fd5b4683606001351461017c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600d60248201527f423a64657374436861696e4964000000000000000000000000000000000000006044820152606401610106565b600061018f61018a85611bf5565b61073d565b905060008082815260018801602052604090205460ff1660038111156101b7576101b7611cf7565b1461021e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600860248201527f423a7374617475730000000000000000000000000000000000000000000000006044820152606401610106565b604080517ff16c79340000000000000000000000000000000000000000000000000000000081528186013560048201526024810191909152600660448201527f6272696467650000000000000000000000000000000000000000000000000000606482015260009073ffffffffffffffffffffffffffffffffffffffff87169063f16c79349060840160206040518083038186803b1580156102bf57600080fd5b505afa1580156102d3573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906102f79190611d26565b905061030786828385888861076d565b61036d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600d60248201527f423a6e6f745265636569766564000000000000000000000000000000000000006044820152606401610106565b6040517f461a447800000000000000000000000000000000000000000000000000000000815260206004820152600b60248201527f65746865725f7661756c74000000000000000000000000000000000000000000604482015260009073ffffffffffffffffffffffffffffffffffffffff88169063461a44789060640160206040518083038186803b15801561040357600080fd5b505afa158015610417573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061043b9190611d26565b905073ffffffffffffffffffffffffffffffffffffffff8116156104e95773ffffffffffffffffffffffffffffffffffffffff8116631efa4ec061012088013561048e6101008a013560e08b0135611d72565b6104989190611d72565b6040518263ffffffff1660e01b81526004016104b691815260200190565b600060405180830381600087803b1580156104d057600080fd5b505af11580156104e4573d6000803e3d6000fd5b505050505b61051d60e087013561050160a0890160808a01611a8d565b73ffffffffffffffffffffffffffffffffffffffff1690610b33565b6000803061053160c08a0160a08b01611a8d565b73ffffffffffffffffffffffffffffffffffffffff1614806105785750600061056060c08a0160a08b01611a8d565b73ffffffffffffffffffffffffffffffffffffffff16145b1561058d57506002905061010087013561064f565b600061059f60a08a0160808b01611a8d565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16146105dc578861014001356105de565b5a5b905060006105f68c6105ef8c611bf5565b8985610c09565b90508015610607576002935061064c565b6001935073ffffffffffffffffffffffffffffffffffffffff85161561064c5761064c73ffffffffffffffffffffffffffffffffffffffff86166101008c0135610b33565b50505b61065a8a8684610dbd565b60008061066d60e08b0160c08c01611a8d565b73ffffffffffffffffffffffffffffffffffffffff161461069d5761069860e08a0160c08b01611a8d565b6106ad565b6106ad60a08a0160808b01611a8d565b90503373ffffffffffffffffffffffffffffffffffffffff82161415610701576106fc6106df6101208b013584611d72565b73ffffffffffffffffffffffffffffffffffffffff831690610b33565b610730565b610710336101208b0135610b33565b61073073ffffffffffffffffffffffffffffffffffffffff821683610b33565b5050505050505050505050565b6000816040516020016107509190611e04565b604051602081830303815290604052805190602001209050919050565b6000848473ffffffffffffffffffffffffffffffffffffffff82166107ee576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600860248201527f423a73656e6465720000000000000000000000000000000000000000000000006044820152606401610106565b80610855576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600860248201527f423a7369676e616c0000000000000000000000000000000000000000000000006044820152606401610106565b73ffffffffffffffffffffffffffffffffffffffff88166108d2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600b60248201527f423a7372634272696467650000000000000000000000000000000000000000006044820152606401610106565b60006108e08587018761203e565b905073C5d653E17c24928B788a17838F11d2AcF0c922A363960304398260000151606001518b6109108c8c610e88565b60208601516040517fffffffff0000000000000000000000000000000000000000000000000000000060e087901b168152610953949392916001916004016121d7565b60006040518083038186803b15801561096b57600080fd5b505af415801561097f573d6000803e3d6000fd5b50506040517f461a447800000000000000000000000000000000000000000000000000000000815260206004820152600560248201527f7461696b6f00000000000000000000000000000000000000000000000000000060448201526000925073ffffffffffffffffffffffffffffffffffffffff8d16915063461a44789060640160206040518083038186803b158015610a1957600080fd5b505afa158015610a2d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a519190611d26565b825161010001516040517f25bf86f20000000000000000000000000000000000000000000000000000000081526fffffffffffffffffffffffffffffffff909116600482015273ffffffffffffffffffffffffffffffffffffffff91909116906325bf86f29060240160206040518083038186803b158015610ad257600080fd5b505afa158015610ae6573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b0a9190612223565b90508015801590610b2457508151610b2190610ee3565b81145b9b9a5050505050505050505050565b8015610c055760008273ffffffffffffffffffffffffffffffffffffffff168260405160006040518083038185875af1925050503d8060008114610b93576040519150601f19603f3d011682016040523d82523d6000602084013e610b98565b606091505b5050905080610c03576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601360248201527f455448207472616e73666572206661696c6564000000000000000000000000006044820152606401610106565b505b5050565b6000808211610c74576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600a60248201527f423a6761734c696d6974000000000000000000000000000000000000000000006044820152606401610106565b6040805160608101825284815260208681015173ffffffffffffffffffffffffffffffffffffffff90811691830182905287840151928401839052600389018790556004890180547fffffffffffffffffffffffff000000000000000000000000000000000000000016909217909155600588019190915560a086015161010087015161016088015193519190921692859291610d11919061223c565b600060405180830381858888f193505050503d8060008114610d4f576040519150601f19603f3d011682016040523d82523d6000602084013e610d54565b606091505b50506040805160608101825260018082526020820181905260001991909201819052600388018290556004880180547fffffffffffffffffffffffff00000000000000000000000000000000000000001690921790915560059096019590955550929392505050565b806003811115610dcf57610dcf611cf7565b600083815260018501602052604090205460ff166003811115610df457610df4611cf7565b14610c0357600082815260018085016020526040909120805483927fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0090911690836003811115610e4657610e46611cf7565b0217905550817f6c51882bc2ed67617f77a1e9b9a25d2caad8448647ecb093b357a603b257563482604051610e7b9190612258565b60405180910390a2505050565b6040517fffffffffffffffffffffffffffffffffffffffff000000000000000000000000606084901b166020820152603481018290526000906054016040516020818303038152906040528051906020012090505b92915050565b60006060826101e0015160001415610f285760408051600f808252610200820190925290816020015b6060815260200190600190039081610f0c579050509050610f57565b604080516010808252610220820190925290816020015b6060815260200190600190039081610f3f5790505090505b8251610f629061129d565b81600081518110610f7557610f75612299565b6020026020010181905250610f8d836020015161129d565b81600181518110610fa057610fa0612299565b6020026020010181905250610fb883604001516112b0565b81600281518110610fcb57610fcb612299565b6020026020010181905250610fe3836060015161129d565b81600381518110610ff657610ff6612299565b602002602001018190525061100e836080015161129d565b8160048151811061102157611021612299565b60200260200101819052506110398360a0015161129d565b8160058151811061104c5761104c612299565b60200260200101819052506110838360c0015160405160200161106f91906122c8565b6040516020818303038152906040526112ec565b8160068151811061109657611096612299565b60200260200101819052506110ae8360e0015161135b565b816007815181106110c1576110c1612299565b60200260200101819052506110ec8361010001516fffffffffffffffffffffffffffffffff1661135b565b816008815181106110ff576110ff612299565b6020026020010181905250611118836101200151611369565b8160098151811061112b5761112b612299565b6020026020010181905250611144836101400151611369565b81600a8151811061115757611157612299565b6020026020010181905250611170836101600151611369565b81600b8151811061118357611183612299565b602002602001018190525061119c8361018001516112ec565b81600c815181106111af576111af612299565b60200260200101819052506111c8836101a0015161129d565b81600d815181106111db576111db612299565b602002602001018190525061122a836101c0015160405160200161106f919060c09190911b7fffffffffffffffff00000000000000000000000000000000000000000000000016815260080190565b81600e8151811061123d5761123d612299565b6020026020010181905250826101e0015160001461128257611263836101e0015161135b565b81600f8151811061127657611276612299565b60200260200101819052505b600061128d82611381565b8051602090910120949350505050565b6060610edd6112ab836113c5565b6112ec565b604051606082811b7fffffffffffffffffffffffffffffffffffffffff00000000000000000000000016602083015290610edd9060340161106f565b6060808251600114801561131a575060808360008151811061131057611310612299565b016020015160f81c105b15611326575081610edd565b611332835160806114b8565b836040516020016113449291906122fd565b604051602081830303815290604052905092915050565b6060610edd6112ab836116af565b6060610edd6112ab8367ffffffffffffffff166116af565b6060600061138e83611811565b905061139c815160c06114b8565b816040516020016113ae9291906122fd565b604051602081830303815290604052915050919050565b60606000826040516020016113dc91815260200190565b604080518083037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe001815260208084528383019092529250600091829160208201818036833701905050905060005b81518110156114af57838361143f8161232c565b94508151811061145157611451612299565b602001015160f81c60f81b82828151811061146e5761146e612299565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a905350806114a78161232c565b91505061142b565b50949350505050565b606080603884101561153757604080516001808252818301909252906020820181803683370190505090506114ed8385612347565b60f81b8160008151811061150357611503612299565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a9053506116a8565b600060015b611546818761239b565b1561156c57816115558161232c565b92506115659050610100826123af565b905061153c565b611577826001611d72565b67ffffffffffffffff81111561158f5761158f611aaa565b6040519080825280601f01601f1916602001820160405280156115b9576020820181803683370190505b5092506115c68583612347565b6115d1906037612347565b60f81b836000815181106115e7576115e7612299565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a905350600190505b8181116116a55761010061162f82846123ce565b61163b906101006124c9565b611645908861239b565b61164f91906124d5565b60f81b83828151811061166457611664612299565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a9053508061169d8161232c565b91505061161b565b50505b9392505050565b60606000826040516020016116c691815260200190565b604051602081830303815290604052905060005b6020811015611738578181815181106116f5576116f5612299565b01602001517fff00000000000000000000000000000000000000000000000000000000000000161561172657611738565b806117308161232c565b9150506116da565b60006117458260206123ce565b67ffffffffffffffff81111561175d5761175d611aaa565b6040519080825280601f01601f191660200182016040528015611787576020820181803683370190505b50905060005b81518110156114af5783836117a18161232c565b9450815181106117b3576117b3612299565b602001015160f81c60f81b8282815181106117d0576117d0612299565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a905350806118098161232c565b91505061178d565b606081516000141561183157505060408051600081526020810190915290565b6000805b83518110156118785783818151811061185057611850612299565b602002602001015151826118649190611d72565b9150806118708161232c565b915050611835565b60008267ffffffffffffffff81111561189357611893611aaa565b6040519080825280601f01601f1916602001820160405280156118bd576020820181803683370190505b50600092509050602081015b85518310156114af5760008684815181106118e6576118e6612299565b60200260200101519050600060208201905061190483828451611941565b87858151811061191657611916612299565b6020026020010151518361192a9190611d72565b9250505082806119399061232c565b9350506118c9565b8282825b6020811061197d578151835261195c602084611d72565b9250611969602083611d72565b91506119766020826123ce565b9050611945565b905182516020929092036101000a6000190180199091169116179052505050565b73ffffffffffffffffffffffffffffffffffffffff811681146119c057600080fd5b50565b6000806000806000608086880312156119db57600080fd5b8535945060208601356119ed8161199e565b9350604086013567ffffffffffffffff80821115611a0a57600080fd5b908701906101a0828a031215611a1f57600080fd5b90935060608701359080821115611a3557600080fd5b818801915088601f830112611a4957600080fd5b813581811115611a5857600080fd5b896020828501011115611a6a57600080fd5b9699959850939650602001949392505050565b8035611a888161199e565b919050565b600060208284031215611a9f57600080fd5b81356116a88161199e565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6040516101a0810167ffffffffffffffff81118282101715611afd57611afd611aaa565b60405290565b6040805190810167ffffffffffffffff81118282101715611afd57611afd611aaa565b604051610200810167ffffffffffffffff81118282101715611afd57611afd611aaa565b600082601f830112611b5b57600080fd5b813567ffffffffffffffff80821115611b7657611b76611aaa565b604051601f83017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f01168101908282118183101715611bbc57611bbc611aaa565b81604052838152866020858801011115611bd557600080fd5b836020870160208301376000602085830101528094505050505092915050565b60006101a08236031215611c0857600080fd5b611c10611ad9565b82358152611c2060208401611a7d565b60208201526040830135604082015260608301356060820152611c4560808401611a7d565b6080820152611c5660a08401611a7d565b60a0820152611c6760c08401611a7d565b60c082015260e083810135908201526101008084013590820152610120808401359082015261014080840135908201526101608084013567ffffffffffffffff80821115611cb457600080fd5b611cc036838801611b4a565b83850152610180925082860135915080821115611cdc57600080fd5b50611ce936828701611b4a565b918301919091525092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b600060208284031215611d3857600080fd5b81516116a88161199e565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60008219821115611d8557611d85611d43565b500190565b60005b83811015611da5578181015183820152602001611d8d565b83811115611db4576000848401525b50505050565b60008151808452611dd2816020860160208601611d8a565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b60408152601460408201527f5441494b4f5f4252494447455f4d4553534147450000000000000000000000006060820152608060208201528151608082015260006020830151611e6c60a084018273ffffffffffffffffffffffffffffffffffffffff169052565b50604083015160c0830152606083015160e08301526080830151610100611eaa8185018373ffffffffffffffffffffffffffffffffffffffff169052565b60a08501519150610120611ed58186018473ffffffffffffffffffffffffffffffffffffffff169052565b60c08601519250610140611f008187018573ffffffffffffffffffffffffffffffffffffffff169052565b60e0870151610160878101919091529287015161018080880191909152918701516101a080880191909152908701516101c0870152918601516101e0860192909252909150611f53610220850183611dba565b908501518482037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8001610200860152909150611f8f8282611dba565b95945050505050565b600082601f830112611fa957600080fd5b60405161010080820182811067ffffffffffffffff82111715611fce57611fce611aaa565b60405283018185821115611fe157600080fd5b845b82811015611ffb578035825260209182019101611fe3565b509195945050505050565b80356fffffffffffffffffffffffffffffffff81168114611a8857600080fd5b803567ffffffffffffffff81168114611a8857600080fd5b60006020828403121561205057600080fd5b813567ffffffffffffffff8082111561206857600080fd5b908301906040828603121561207c57600080fd5b612084611b03565b82358281111561209357600080fd5b83016102e081880312156120a657600080fd5b6120ae611b26565b81358152602082013560208201526120c860408301611a7d565b6040820152606082013560608201526080820135608082015260a082013560a08201526120f88860c08401611f98565b60c08201526101c08083013560e08301526101e0612117818501612006565b61010084015261212a6102008501612026565b61012084015261213d6102208501612026565b6101408401526121506102408501612026565b6101608401526102608401358681111561216957600080fd5b6121758b828701611b4a565b610180850152506102808401356101a08401526121956102a08501612026565b828401526102c084013581840152505080835250506020830135828111156121bc57600080fd5b6121c887828601611b4a565b60208301525095945050505050565b85815273ffffffffffffffffffffffffffffffffffffffff8516602082015283604082015282606082015260a06080820152600061221860a0830184611dba565b979650505050505050565b60006020828403121561223557600080fd5b5051919050565b6000825161224e818460208701611d8a565b9190910192915050565b6020810160048310612293577f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b91905290565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b60008183825b60088110156122ed5781518352602092830192909101906001016122ce565b5050506101008201905092915050565b6000835161230f818460208801611d8a565b835190830190612323818360208801611d8a565b01949350505050565b600060001982141561234057612340611d43565b5060010190565b600060ff821660ff84168060ff0382111561236457612364611d43565b019392505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b6000826123aa576123aa61236c565b500490565b60008160001904831182151516156123c9576123c9611d43565b500290565b6000828210156123e0576123e0611d43565b500390565b600181815b8085111561242057816000190482111561240657612406611d43565b8085161561241357918102915b93841c93908002906123ea565b509250929050565b60008261243757506001610edd565b8161244457506000610edd565b816001811461245a576002811461246457612480565b6001915050610edd565b60ff84111561247557612475611d43565b50506001821b610edd565b5060208310610133831016604e8410600b84101617156124a3575081810a610edd565b6124ad83836123e5565b80600019048211156124c1576124c1611d43565b029392505050565b60006116a88383612428565b6000826124e4576124e461236c565b50069056fea264697066735822122014b842a0757d4ec0c7768c8c29fec84d20bd7c03ad1a5e3376215194d1c9806464736f6c63430008090033", + "balance": "0x0" + }, + "0x1FEEE7d2A4da93fE4899fFf3ff844A224b1A143d": { + "contractName": "LibTxDecoder", + "storage": {}, + "code": "0x73000000000000000000000000000000000000000030146080604052600436106100405760003560e01c80632cb6101a14610045578063dae029d31461006e575b600080fd5b6100586100533660046117b8565b61008e565b6040516100659190611925565b60405180910390f35b61008161007c3660046119de565b610218565b6040516100659190611aad565b604080516020810190915260608152816100a757610212565b60006100e884848080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152506104e092505050565b90506000815167ffffffffffffffff811115610106576101066119af565b60405190808252806020026020018201604052801561019b57816020015b610188604051806101000160405280600060ff168152602001600073ffffffffffffffffffffffffffffffffffffffff1681526020016060815260200160008152602001600060ff1681526020016000815260200160008152602001606081525090565b8152602001906001900390816101245790505b50905060005b82518110156101ff576101cf61007c8483815181106101c2576101c2611ac0565b6020026020010151610513565b8282815181106101e1576101e1611ac0565b602002602001018190525080806101f790611b1e565b9150506101a1565b5060408051602081019091529081529150505b92915050565b61027c604051806101000160405280600060ff168152602001600073ffffffffffffffffffffffffffffffffffffffff1681526020016060815260200160008152602001600060ff1681526020016000815260200160008152602001606081525090565b602082015160e0820183905260001a60c081108015906102a0575060fe8160ff1611155b156103265760008083526102b3846104e0565b905060006102c0826105a3565b60408082015160608088019190915282015173ffffffffffffffffffffffffffffffffffffffff16602087015260c08083015160ff16608088015260e083015160a080890191909152610100840151918801919091529091015190850152506104da9050565b607f8160ff16116104925760ff81168252600061034c6103478560016107bd565b6104e0565b90508160ff16600114156103c4576000610365826107fa565b6060808201519086015260808082015173ffffffffffffffffffffffffffffffffffffffff16602087015261010082015160ff169086015261012081015160a086015261014081015160c080870191909152015160408501525061048c565b826000015160ff166002141561043f5760006103df82610a3b565b608080820151606087015260a08083015173ffffffffffffffffffffffffffffffffffffffff16602088015261012083015160ff16918701919091526101408201519086015261016081015160c086015260e0015160408501525061048c565b60405162461bcd60e51b815260206004820152600e60248201527f696e76616c69642074785479706500000000000000000000000000000000000060448201526064015b60405180910390fd5b506104da565b60405162461bcd60e51b815260206004820152600e60248201527f696e76616c6964207072656669780000000000000000000000000000000000006044820152606401610483565b50919050565b60408051808201825260008082526020918201528151808301909252825182528083019082015260609061021290610c90565b6060600080600061052385610e8f565b91945092509050600081600181111561053e5761053e611b57565b1461058b5760405162461bcd60e51b815260206004820152601860248201527f496e76616c696420524c502062797465732076616c75652e00000000000000006044820152606401610483565b61059a856020015184846111e0565b95945050505050565b61060b604051806101200160405280600081526020016000815260200160008152602001600073ffffffffffffffffffffffffffffffffffffffff1681526020016000815260200160608152602001600060ff16815260200160008152602001600081525090565b815160091461065c5760405162461bcd60e51b815260206004820152601460248201527f696e76616c6964206974656d73206c656e6774680000000000000000000000006044820152606401610483565b61067f8260008151811061067257610672611ac0565b60200260200101516112d9565b8152815161069a908390600190811061067257610672611ac0565b602082015281516106b8908390600290811061067257610672611ac0565b604082015281516106e390839060039081106106d6576106d6611ac0565b60200260200101516112e4565b73ffffffffffffffffffffffffffffffffffffffff1660608201528151610717908390600490811061067257610672611ac0565b6080820152815161073590839060059081106101c2576101c2611ac0565b60a082015261074862028c5b6002611b86565b61075e8360068151811061067257610672611ac0565b6107689190611bc3565b610773906023611bda565b60ff1660c08201528151610794908390600790811061067257610672611ac0565b60e082015281516107b2908390600890811061067257610672611ac0565b610100820152919050565b6060825182106107dc5750604080516020810190915260008152610212565b6107f383838486516107ee9190611bc3565b611353565b9392505050565b61087060405180610160016040528060008152602001600081526020016000815260200160008152602001600073ffffffffffffffffffffffffffffffffffffffff168152602001600081526020016060815260200160608152602001600060ff16815260200160008152602001600081525090565b8151600b146108c15760405162461bcd60e51b815260206004820152601460248201527f696e76616c6964206974656d73206c656e6774680000000000000000000000006044820152606401610483565b6108d78260008151811061067257610672611ac0565b815281516108f2908390600190811061067257610672611ac0565b60208201528151610910908390600290811061067257610672611ac0565b6040820152815161092e908390600390811061067257610672611ac0565b6060820152815161094c90839060049081106106d6576106d6611ac0565b73ffffffffffffffffffffffffffffffffffffffff1660808201528151610980908390600590811061067257610672611ac0565b60a0820152815161099e90839060069081106101c2576101c2611ac0565b8160c001819052506109d16109cc836007815181106109bf576109bf611ac0565b6020026020010151610c90565b6114f2565b8160e001819052506109ef8260088151811061067257610672611ac0565b60ff166101008201528151610a11908390600990811061067257610672611ac0565b6101208201528151610a30908390600a90811061067257610672611ac0565b610140820152919050565b610ab86040518061018001604052806000815260200160008152602001600081526020016000815260200160008152602001600073ffffffffffffffffffffffffffffffffffffffff168152602001600081526020016060815260200160608152602001600060ff16815260200160008152602001600081525090565b8151600c14610b095760405162461bcd60e51b815260206004820152601460248201527f696e76616c6964206974656d73206c656e6774680000000000000000000000006044820152606401610483565b610b1f8260008151811061067257610672611ac0565b81528151610b3a908390600190811061067257610672611ac0565b60208201528151610b58908390600290811061067257610672611ac0565b60408201528151610b76908390600390811061067257610672611ac0565b60608201528151610b94908390600490811061067257610672611ac0565b60808201528151610bb290839060059081106106d6576106d6611ac0565b73ffffffffffffffffffffffffffffffffffffffff1660a08201528151610be6908390600690811061067257610672611ac0565b60c08201528151610c0490839060079081106101c2576101c2611ac0565b8160e00181905250610c256109cc836008815181106109bf576109bf611ac0565b816101000181905250610c448260098151811061067257610672611ac0565b60ff166101208201528151610c66908390600a90811061067257610672611ac0565b6101408201528151610c85908390600b90811061067257610672611ac0565b610160820152919050565b6060600080610c9e84610e8f565b91935090915060019050816001811115610cba57610cba611b57565b14610d075760405162461bcd60e51b815260206004820152601760248201527f496e76616c696420524c50206c6973742076616c75652e0000000000000000006044820152606401610483565b6040805160208082526104208201909252600091816020015b6040805180820190915260008082526020820152815260200190600190039081610d205790505090506000835b8651811015610e845760208210610dcc5760405162461bcd60e51b815260206004820152602a60248201527f50726f766964656420524c50206c6973742065786365656473206d6178206c6960448201527f7374206c656e6774682e000000000000000000000000000000000000000000006064820152608401610483565b600080610e096040518060400160405280858c60000151610ded9190611bc3565b8152602001858c60200151610e029190611bda565b9052610e8f565b509150915060405180604001604052808383610e259190611bda565b8152602001848b60200151610e3a9190611bda565b815250858581518110610e4f57610e4f611ac0565b6020908102919091010152610e65600185611bda565b9350610e718183611bda565b610e7b9084611bda565b92505050610d4d565b508152949350505050565b600080600080846000015111610ee75760405162461bcd60e51b815260206004820152601860248201527f524c50206974656d2063616e6e6f74206265206e756c6c2e00000000000000006044820152606401610483565b6020840151805160001a607f8111610f0c5760006001600094509450945050506111d9565b60b78111610f88576000610f21608083611bc3565b905080876000015111610f765760405162461bcd60e51b815260206004820152601960248201527f496e76616c696420524c502073686f727420737472696e672e000000000000006044820152606401610483565b600195509350600092506111d9915050565b60bf8111611077576000610f9d60b783611bc3565b905080876000015111610ff25760405162461bcd60e51b815260206004820152601f60248201527f496e76616c696420524c50206c6f6e6720737472696e67206c656e6774682e006044820152606401610483565b600183015160208290036101000a900461100c8183611bda565b88511161105b5760405162461bcd60e51b815260206004820152601860248201527f496e76616c696420524c50206c6f6e6720737472696e672e00000000000000006044820152606401610483565b611066826001611bda565b96509450600093506111d992505050565b60f781116110f257600061108c60c083611bc3565b9050808760000151116110e15760405162461bcd60e51b815260206004820152601760248201527f496e76616c696420524c502073686f7274206c6973742e0000000000000000006044820152606401610483565b6001955093508492506111d9915050565b60006110ff60f783611bc3565b9050808760000151116111545760405162461bcd60e51b815260206004820152601d60248201527f496e76616c696420524c50206c6f6e67206c697374206c656e6774682e0000006044820152606401610483565b600183015160208290036101000a900461116e8183611bda565b8851116111bd5760405162461bcd60e51b815260206004820152601660248201527f496e76616c696420524c50206c6f6e67206c6973742e000000000000000000006044820152606401610483565b6111c8826001611bda565b96509450600193506111d992505050565b9193909250565b606060008267ffffffffffffffff8111156111fd576111fd6119af565b6040519080825280601f01601f191660200182016040528015611227576020820181803683370190505b50905080516000141561123b5790506107f3565b60006112478587611bda565b90506020820160005b61125b602087611bf2565b8110156112925782518252611271602084611bda565b925061127e602083611bda565b91508061128a81611b1e565b915050611250565b5080519151601f959095166020036101000a7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff019182169119909416179092525092915050565b6000610212826116b5565b8051600090600114156112f957506000919050565b815160151461134a5760405162461bcd60e51b815260206004820152601a60248201527f496e76616c696420524c5020616464726573732076616c75652e0000000000006044820152606401610483565b610212826112d9565b60608161136181601f611bda565b10156113af5760405162461bcd60e51b815260206004820152600e60248201527f736c6963655f6f766572666c6f770000000000000000000000000000000000006044820152606401610483565b826113ba8382611bda565b10156114085760405162461bcd60e51b815260206004820152600e60248201527f736c6963655f6f766572666c6f770000000000000000000000000000000000006044820152606401610483565b6114128284611bda565b845110156114625760405162461bcd60e51b815260206004820152601160248201527f736c6963655f6f75744f66426f756e64730000000000000000000000000000006044820152606401610483565b60608215801561148157604051915060008252602082016040526114e9565b6040519150601f8416801560200281840101858101878315602002848b0101015b818310156114ba5780518352602092830192016114a2565b5050858452601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016604052505b50949350505050565b6060815167ffffffffffffffff81111561150e5761150e6119af565b60405190808252806020026020018201604052801561155457816020015b60408051808201909152600081526060602082015281526020019060019003908161152c5790505b50905060005b82518110156104da57600061157a8483815181106109bf576109bf611ac0565b90506000611594826000815181106106d6576106d6611ac0565b905060006115ae836001815181106109bf576109bf611ac0565b90506000815167ffffffffffffffff8111156115cc576115cc6119af565b6040519080825280602002602001820160405280156115f5578160200160208202803683370190505b50905060005b82518110156116555761162683828151811061161957611619611ac0565b60200260200101516116b5565b82828151811061163857611638611ac0565b60209081029190910101528061164d81611b1e565b9150506115fb565b5060405180604001604052808473ffffffffffffffffffffffffffffffffffffffff1681526020018281525086868151811061169357611693611ac0565b60200260200101819052505050505080806116ad90611b1e565b91505061155a565b600060218260000151111561170c5760405162461bcd60e51b815260206004820152601a60248201527f496e76616c696420524c5020627974657333322076616c75652e0000000000006044820152606401610483565b600080600061171a85610e8f565b91945092509050600081600181111561173557611735611b57565b146117825760405162461bcd60e51b815260206004820152601a60248201527f496e76616c696420524c5020627974657333322076616c75652e0000000000006044820152606401610483565b60008386602001516117949190611bda565b805190915060208410156117ae5760208490036101000a90045b9695505050505050565b600080602083850312156117cb57600080fd5b823567ffffffffffffffff808211156117e357600080fd5b818501915085601f8301126117f757600080fd5b81358181111561180657600080fd5b86602082850101111561181857600080fd5b60209290920196919550909350505050565b6000815180845260005b8181101561185057602081850181015186830182015201611834565b81811115611862576000602083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b600061010060ff835116845273ffffffffffffffffffffffffffffffffffffffff602084015116602085015260408301518160408601526118d88286018261182a565b9150506060830151606085015260808301516118f9608086018260ff169052565b5060a083015160a085015260c083015160c085015260e083015184820360e086015261059a828261182a565b60006020808352604083018451828386015281815180845260608701915060608160051b8801019350848301925060005b818110156119a2577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa0888603018352611990858551611895565b94509285019291850191600101611956565b5092979650505050505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6000602082840312156119f057600080fd5b813567ffffffffffffffff80821115611a0857600080fd5b818401915084601f830112611a1c57600080fd5b813581811115611a2e57611a2e6119af565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f01168101908382118183101715611a7457611a746119af565b81604052828152876020848701011115611a8d57600080fd5b826020860160208301376000928101602001929092525095945050505050565b6020815260006107f36020830184611895565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff821415611b5057611b50611aef565b5060010190565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b6000817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0483118215151615611bbe57611bbe611aef565b500290565b600082821015611bd557611bd5611aef565b500390565b60008219821115611bed57611bed611aef565b500190565b600082611c28577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b50049056fea2646970667358221220ce05fa3cbf6e91edf039ea061baf84063d7d321bf9eb0101e512c682c93dd08f64736f6c63430008090033", + "balance": "0x0" + }, + "0x0000777700000000000000000000000000000006": { + "contractName": "AddressManager", + "storage": { + "0x0000000000000000000000000000000000000000000000000000000000000000": "0x0000000000000000000000000000000000000000000000000000000000000001", + "0x0000000000000000000000000000000000000000000000000000000000000033": "0x00000000000000000000000026250179c8e8e12104e556c4cd03bcf4dabd51b9", + "0x9e150550d912c06ad86bcac5075c8239136cbee2772f59805934f638390787fd": "0x0000000000000000000000000000777700000000000000000000000000000001", + "0xdf0a4e0e7239b530f3a9e9f04f6a2a1d6919446d7589e04de0d7da7f18f5d05a": "0x0000000000000000000000000000777700000000000000000000000000000004", + "0x20beed59eb6fea4f4c6192069320a80e7e285095b80b0603151a98cc480424ce": "0x0000000000000000000000000000777700000000000000000000000000000002", + "0x3d81277ccd96113ddd1d87267c98b973367fd126e1b94b601a82a8474494f54f": "0x0000000000000000000000000000777700000000000000000000000000000003" + }, + "code": "0x608060405234801561001057600080fd5b50600436106100725760003560e01c8063bf40fac111610050578063bf40fac1146100d7578063e1c7392a146100ea578063f2fde38b146100f257600080fd5b8063715018a6146100775780638da5cb5b146100815780639b2ea4bd146100c4575b600080fd5b61007f610105565b005b60335473ffffffffffffffffffffffffffffffffffffffff165b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200160405180910390f35b61007f6100d23660046107d8565b610119565b61009b6100e5366004610826565b6101ec565b61007f610228565b61007f610100366004610863565b6103bf565b61010d610473565b61011760006104f4565b565b610121610473565b600061012c8361056b565b60008181526065602052604090819020805473ffffffffffffffffffffffffffffffffffffffff8681167fffffffffffffffffffffffff00000000000000000000000000000000000000008316179092559151929350169061018f908590610885565b6040805191829003822073ffffffffffffffffffffffffffffffffffffffff808716845284166020840152917f9416a153a346f93d95f94b064ae3f148b6460473c6e82b3f9fc2521b873fcd6c910160405180910390a250505050565b6000606560006101fb8461056b565b815260208101919091526040016000205473ffffffffffffffffffffffffffffffffffffffff1692915050565b600054610100900460ff16158080156102485750600054600160ff909116105b806102625750303b158015610262575060005460ff166001145b6102f3576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a656400000000000000000000000000000000000060648201526084015b60405180910390fd5b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001179055801561035157600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff166101001790555b61035961059b565b80156103bc57600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b50565b6103c7610473565b73ffffffffffffffffffffffffffffffffffffffff811661046a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201527f646472657373000000000000000000000000000000000000000000000000000060648201526084016102ea565b6103bc816104f4565b60335473ffffffffffffffffffffffffffffffffffffffff163314610117576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657260448201526064016102ea565b6033805473ffffffffffffffffffffffffffffffffffffffff8381167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b60008160405160200161057e9190610885565b604051602081830303815290604052805190602001209050919050565b600054610100900460ff16610632576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e6700000000000000000000000000000000000000000060648201526084016102ea565b610117600054610100900460ff166106cc576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e6700000000000000000000000000000000000000000060648201526084016102ea565b610117336104f4565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b600082601f83011261071557600080fd5b813567ffffffffffffffff80821115610730576107306106d5565b604051601f83017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f01168101908282118183101715610776576107766106d5565b8160405283815286602085880101111561078f57600080fd5b836020870160208301376000602085830101528094505050505092915050565b803573ffffffffffffffffffffffffffffffffffffffff811681146107d357600080fd5b919050565b600080604083850312156107eb57600080fd5b823567ffffffffffffffff81111561080257600080fd5b61080e85828601610704565b92505061081d602084016107af565b90509250929050565b60006020828403121561083857600080fd5b813567ffffffffffffffff81111561084f57600080fd5b61085b84828501610704565b949350505050565b60006020828403121561087557600080fd5b61087e826107af565b9392505050565b6000825160005b818110156108a6576020818601810151858301520161088c565b818111156108b5576000828501525b50919091019291505056fea264697066735822122073e1836383d35ef46f9abd6688521406480eb2e7754e7387e4dd208fb4d7c6e464736f6c63430008090033", + "balance": "0x0" + }, + "0x0000777700000000000000000000000000000001": { + "contractName": "TaikoL2", + "storage": { + "0x0000000000000000000000000000000000000000000000000000000000000032": "0x0000000000000000000000000000000000000000000000000000000000000001", + "0x0000000000000000000000000000000000000000000000000000000000000000": "0x0000000000000000000000000000777700000000000000000000000000000006", + "0x0000000000000000000000000000000000000000000000000000000000000035": "0x7eb68e48c9bb3d707a9aba14662dab6ddd0a07c15abb07e83f02d11a86c15560" + }, + "code": "0x608060405234801561001057600080fd5b50600436106100c95760003560e01c80639a295e7311610081578063dac5df781161005b578063dac5df78146101f2578063ee82ac5e146101fb578063f16c79341461020e57600080fd5b80639a295e7314610170578063a0ca2d08146101d6578063c8d772ab146101e957600080fd5b8063461a4478116100b2578063461a4478146101405780635155ce9f14610153578063975e09a01461015b57600080fd5b806325bf86f2146100ce5780633ab76e9f14610101575b600080fd5b6100ee6100dc366004611e7a565b60009081526034602052604090205490565b6040519081526020015b60405180910390f35b60005473ffffffffffffffffffffffffffffffffffffffff165b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016100f8565b61011b61014e366004611fbe565b610221565b6036546100ee565b61016e610169366004611ff3565b610233565b005b604080516001815262028c5b6020820152610801918101919091526014606082015260006080820152600560a0820152624c4b4060c0820152606460e0820152620927c06101008201526152086101208201526203d090610140820152610160016100f8565b61016e6101e4366004612080565b6102ec565b6100ee60365481565b6100ee60355481565b6100ee610209366004611e7a565b61034c565b61011b61021c3660046120a2565b610399565b600061022d4683610456565b92915050565b600061024185858585610531565b90506000816006811115610257576102576120e9565b14156102aa5760405162461bcd60e51b815260206004820152600960248201527f4c323a726561736f6e000000000000000000000000000000000000000000000060448201526064015b60405180910390fd5b6102b261082f565b6102bc8585610952565b6040517f64b299ff9f8ba674288abb53380419048a4271dda03b837ecba6b40e6ddea4a290600090a25050505050565b6102f461082f565b60008281526034602052604090819020829055603682905551829043907f930c750845026c7bb04c0e3d9111d512b4c86981713c4944a35a10a4a7a854f3906103409085815260200190565b60405180910390a35050565b600043821061035d57506000919050565b4382108015610377575061037361010043612147565b8210155b1561038157504090565b5060009081526033602052604090205490565b919050565b60006103a58383610456565b9392505050565b73ffffffffffffffffffffffffffffffffffffffff811661040f5760405162461bcd60e51b815260206004820152600e60248201527f41523a7a65726f4164647265737300000000000000000000000000000000000060448201526064016102a1565b600080547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff92909216919091179055565b60008061046284610974565b8360405160200161047492919061218e565b60408051601f19818403018152908290526000547fbf40fac100000000000000000000000000000000000000000000000000000000835290925073ffffffffffffffffffffffffffffffffffffffff169063bf40fac1906104d99084906004016121e6565b60206040518083038186803b1580156104f157600080fd5b505afa158015610505573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610529919061223d565b949350505050565b6000620927c084111561054657506001610529565b6040517f2cb6101a000000000000000000000000000000000000000000000000000000008152731FEEE7d2A4da93fE4899fFf3ff844A224b1A143d90632cb6101a906105989088908890600401612258565b60006040518083038186803b1580156105b057600080fd5b505af49250505080156105e557506040513d6000823e601f3d908101601f191682016040526105e291908101906122dd565b60015b610623573d808015610613576040519150601f19603f3d011682016040523d82523d6000602084013e610618565b606091505b506002915050610529565b80515160641015610638576003915050610529565b624c4b4061064582610aa6565b1115610655576004915050610529565b80515183106106a65760405162461bcd60e51b815260206004820152600d60248201527f696e76616c69642074784964780000000000000000000000000000000000000060448201526064016102a1565b6000816000015184815181106106be576106be61247d565b60200260200101519050600560068111156106db576106db6120e9565b8560068111156106ed576106ed6120e9565b141561076c5760006106fe82610afa565b73ffffffffffffffffffffffffffffffffffffffff16146107615760405162461bcd60e51b815260206004820152601760248201527f6261642068696e742054585f494e56414c49445f53494700000000000000000060448201526064016102a1565b600592505050610529565b6006856006811115610780576107806120e9565b14156107e757615208816060015110156107dc5760405162461bcd60e51b815260206004820152600860248201527f6261642068696e7400000000000000000000000000000000000000000000000060448201526064016102a1565b600692505050610529565b60405162461bcd60e51b815260206004820152601e60248201527f6661696c656420746f2070726f76652074786c69737420696e76616c6964000060448201526064016102a1565b610837611e5b565b434660025b610100811115801561084e5750808310155b1561089c5761085d8184612147565b408460ff61086b8487612147565b61087591906124db565b60ff81106108855761088561247d565b602002015280610894816124ef565b91505061083c565b5060006108aa600184612147565b905080406108bb8383600088610b89565b6035541461090b5760405162461bcd60e51b815260206004820152601260248201527f4c323a7075626c6963496e70757448617368000000000000000000000000000060448201526064016102a1565b808561091860ff856124db565b60ff81106109285761092861247d565b602002015261093a8385600088610b89565b60355560009182526033602052604090912055505050565b60008282604051610964929190612528565b6040518091039020905092915050565b6060816109b457505060408051808201909152600181527f3000000000000000000000000000000000000000000000000000000000000000602082015290565b8160005b81156109de57806109c8816124ef565b91506109d79050600a83612538565b91506109b8565b60008167ffffffffffffffff8111156109f9576109f9611e93565b6040519080825280601f01601f191660200182016040528015610a23576020820181803683370190505b5090505b841561052957610a38600183612147565b9150610a45600a866124db565b610a5090603061254c565b60f81b818381518110610a6557610a6561247d565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a905350610a9f600a86612538565b9450610a27565b8051600090815b8151811015610af357818181518110610ac857610ac861247d565b60200260200101516060015183610adf919061254c565b925080610aeb816124ef565b915050610aad565b5050919050565b60006001610b0783610bc2565b6080840151610b1790601b612564565b60a085015160c0860151604080516000815260200190819052610b56949392919093845260ff9290921660208401526040830152606082015260800190565b6020604051602081039080840390855afa158015610b78573d6000803e3d6000fd5b5050604051601f1901519392505050565b600084848484604051602001610ba29493929190612589565b604051602081830303815290604052805190602001209050949350505050565b805160009060609060ff16610be557610bde8360e00151610fb5565b9050610bff565b610bfc610bf78460e001516001610fe8565b610fb5565b90505b825160ff16610c5e578051600914610c595760405162461bcd60e51b815260206004820152601160248201527f696e76616c696420726c70206974656d7300000000000000000000000000000060448201526064016102a1565b610d68565b826000015160ff1660011415610cbf578051600b14610c595760405162461bcd60e51b815260206004820152601160248201527f696e76616c696420726c70206974656d7300000000000000000000000000000060448201526064016102a1565b826000015160ff1660021415610d20578051600c14610c595760405162461bcd60e51b815260206004820152601160248201527f696e76616c696420726c70206974656d7300000000000000000000000000000060448201526064016102a1565b60405162461bcd60e51b815260206004820152600e60248201527f696e76616c69642074785479706500000000000000000000000000000000000060448201526064016102a1565b825160009060ff1615610d885760038251610d839190612147565b610d8b565b81515b67ffffffffffffffff811115610da357610da3611e93565b604051908082528060200260200182016040528015610dd657816020015b6060815260200190600190039081610dc15790505b50905060005b8151811015610f6357845160ff1615801590610e04575060018251610e019190612147565b81145b15610e4d57610e2b838281518110610e1e57610e1e61247d565b602002602001015161101e565b828281518110610e3d57610e3d61247d565b6020026020010181905250610f51565b610e77610e72848381518110610e6557610e6561247d565b6020026020010151611029565b6110b9565b828281518110610e8957610e8961247d565b6020908102919091010152845160ff16158015610eb2575060048251610eaf9190612147565b81145b15610f5157610ec362028c5b611128565b82610ecf83600161254c565b81518110610edf57610edf61247d565b6020026020010181905250610ef46000611136565b82610f0083600261254c565b81518110610f1057610f1061247d565b6020026020010181905250610f256000611136565b82610f3183600361254c565b81518110610f4157610f4161247d565b6020026020010181905250610f63565b80610f5b816124ef565b915050610ddc565b506000610f6f8261114e565b855190915060ff1615610fa5578451604051610f939160f81b9083906020016125d4565b60405160208183030381529060405290505b8051602090910120949350505050565b60408051808201825260008082526020918201528151808301909252825182528083019082015260609061022d90611192565b606082518210611007575060408051602081019091526000815261022d565b6103a583838486516110199190612147565b611391565b606061022d82611512565b6060600080600061103985611528565b919450925090506000816001811115611054576110546120e9565b146110a15760405162461bcd60e51b815260206004820152601860248201527f496e76616c696420524c502062797465732076616c75652e000000000000000060448201526064016102a1565b6110b085602001518484611879565b95945050505050565b606080825160011480156110e757506080836000815181106110dd576110dd61247d565b016020015160f81c105b156110f357508161022d565b6110ff83516080611958565b8360405160200161111192919061261c565b604051602081830303815290604052905092915050565b606061022d610e7283611b4e565b606061022d610e728367ffffffffffffffff16611b4e565b6060600061115b83611cb0565b9050611169815160c0611958565b8160405160200161117b92919061261c565b604051602081830303815290604052915050919050565b60606000806111a084611528565b919350909150600190508160018111156111bc576111bc6120e9565b146112095760405162461bcd60e51b815260206004820152601760248201527f496e76616c696420524c50206c6973742076616c75652e00000000000000000060448201526064016102a1565b6040805160208082526104208201909252600091816020015b60408051808201909152600080825260208201528152602001906001900390816112225790505090506000835b865181101561138657602082106112ce5760405162461bcd60e51b815260206004820152602a60248201527f50726f766964656420524c50206c6973742065786365656473206d6178206c6960448201527f7374206c656e6774682e0000000000000000000000000000000000000000000060648201526084016102a1565b60008061130b6040518060400160405280858c600001516112ef9190612147565b8152602001858c60200151611304919061254c565b9052611528565b509150915060405180604001604052808383611327919061254c565b8152602001848b6020015161133c919061254c565b8152508585815181106113515761135161247d565b602090810291909101015261136760018561254c565b9350611373818361254c565b61137d908461254c565b9250505061124f565b508152949350505050565b60608161139f81601f61254c565b10156113ed5760405162461bcd60e51b815260206004820152600e60248201527f736c6963655f6f766572666c6f7700000000000000000000000000000000000060448201526064016102a1565b826113f8838261254c565b10156114465760405162461bcd60e51b815260206004820152600e60248201527f736c6963655f6f766572666c6f7700000000000000000000000000000000000060448201526064016102a1565b611450828461254c565b845110156114a05760405162461bcd60e51b815260206004820152601160248201527f736c6963655f6f75744f66426f756e647300000000000000000000000000000060448201526064016102a1565b6060821580156114bf5760405191506000825260208201604052611509565b6040519150601f8416801560200281840101858101878315602002848b0101015b818310156114f85780518352602092830192016114e0565b5050858452601f01601f1916604052505b50949350505050565b606061022d826020015160008460000151611879565b6000806000808460000151116115805760405162461bcd60e51b815260206004820152601860248201527f524c50206974656d2063616e6e6f74206265206e756c6c2e000000000000000060448201526064016102a1565b6020840151805160001a607f81116115a5576000600160009450945094505050611872565b60b781116116215760006115ba608083612147565b90508087600001511161160f5760405162461bcd60e51b815260206004820152601960248201527f496e76616c696420524c502073686f727420737472696e672e0000000000000060448201526064016102a1565b60019550935060009250611872915050565b60bf811161171057600061163660b783612147565b90508087600001511161168b5760405162461bcd60e51b815260206004820152601f60248201527f496e76616c696420524c50206c6f6e6720737472696e67206c656e6774682e0060448201526064016102a1565b600183015160208290036101000a90046116a5818361254c565b8851116116f45760405162461bcd60e51b815260206004820152601860248201527f496e76616c696420524c50206c6f6e6720737472696e672e000000000000000060448201526064016102a1565b6116ff82600161254c565b965094506000935061187292505050565b60f7811161178b57600061172560c083612147565b90508087600001511161177a5760405162461bcd60e51b815260206004820152601760248201527f496e76616c696420524c502073686f7274206c6973742e00000000000000000060448201526064016102a1565b600195509350849250611872915050565b600061179860f783612147565b9050808760000151116117ed5760405162461bcd60e51b815260206004820152601d60248201527f496e76616c696420524c50206c6f6e67206c697374206c656e6774682e00000060448201526064016102a1565b600183015160208290036101000a9004611807818361254c565b8851116118565760405162461bcd60e51b815260206004820152601660248201527f496e76616c696420524c50206c6f6e67206c6973742e0000000000000000000060448201526064016102a1565b61186182600161254c565b965094506001935061187292505050565b9193909250565b606060008267ffffffffffffffff81111561189657611896611e93565b6040519080825280601f01601f1916602001820160405280156118c0576020820181803683370190505b5090508051600014156118d45790506103a5565b60006118e0858761254c565b90506020820160005b6118f4602087612538565b81101561192b578251825261190a60208461254c565b925061191760208361254c565b915080611923816124ef565b9150506118e9565b5060006001602087066020036101000a039050808251168119845116178252839450505050509392505050565b60608060388410156119d7576040805160018082528183019092529060208201818036833701905050905061198d8385612564565b60f81b816000815181106119a3576119a361247d565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a9053506103a5565b600060015b6119e68187612538565b15611a0c57816119f5816124ef565b9250611a0590506101008261264b565b90506119dc565b611a1782600161254c565b67ffffffffffffffff811115611a2f57611a2f611e93565b6040519080825280601f01601f191660200182016040528015611a59576020820181803683370190505b509250611a668583612564565b611a71906037612564565b60f81b83600081518110611a8757611a8761247d565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a905350600190505b818111611b4557610100611acf8284612147565b611adb906101006127a8565b611ae59088612538565b611aef91906124db565b60f81b838281518110611b0457611b0461247d565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a90535080611b3d816124ef565b915050611abb565b50509392505050565b6060600082604051602001611b6591815260200190565b604051602081830303815290604052905060005b6020811015611bd757818181518110611b9457611b9461247d565b01602001517fff000000000000000000000000000000000000000000000000000000000000001615611bc557611bd7565b80611bcf816124ef565b915050611b79565b6000611be4826020612147565b67ffffffffffffffff811115611bfc57611bfc611e93565b6040519080825280601f01601f191660200182016040528015611c26576020820181803683370190505b50905060005b8151811015611509578383611c40816124ef565b945081518110611c5257611c5261247d565b602001015160f81c60f81b828281518110611c6f57611c6f61247d565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a90535080611ca8816124ef565b915050611c2c565b6060815160001415611cd057505060408051600081526020810190915290565b6000805b8351811015611d1757838181518110611cef57611cef61247d565b60200260200101515182611d03919061254c565b915080611d0f816124ef565b915050611cd4565b60008267ffffffffffffffff811115611d3257611d32611e93565b6040519080825280601f01601f191660200182016040528015611d5c576020820181803683370190505b50600092509050602081015b8551831015611509576000868481518110611d8557611d8561247d565b602002602001015190506000602082019050611da383828451611de0565b878581518110611db557611db561247d565b60200260200101515183611dc9919061254c565b925050508280611dd8906124ef565b935050611d68565b8282825b60208110611e1c5781518352611dfb60208461254c565b9250611e0860208361254c565b9150611e15602082612147565b9050611de4565b905182516020929092036101000a7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0180199091169116179052505050565b60405180611fe0016040528060ff906020820280368337509192915050565b600060208284031215611e8c57600080fd5b5035919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6040516020810167ffffffffffffffff81118282101715611ee557611ee5611e93565b60405290565b604051610100810167ffffffffffffffff81118282101715611ee557611ee5611e93565b604051601f8201601f1916810167ffffffffffffffff81118282101715611f3857611f38611e93565b604052919050565b600067ffffffffffffffff821115611f5a57611f5a611e93565b50601f01601f191660200190565b600082601f830112611f7957600080fd5b8135611f8c611f8782611f40565b611f0f565b818152846020838601011115611fa157600080fd5b816020850160208301376000918101602001919091529392505050565b600060208284031215611fd057600080fd5b813567ffffffffffffffff811115611fe757600080fd5b61052984828501611f68565b6000806000806060858703121561200957600080fd5b843567ffffffffffffffff8082111561202157600080fd5b818701915087601f83011261203557600080fd5b81358181111561204457600080fd5b88602082850101111561205657600080fd5b602092830196509450508501356007811061207057600080fd5b9396929550929360400135925050565b6000806040838503121561209357600080fd5b50508035926020909101359150565b600080604083850312156120b557600080fd5b82359150602083013567ffffffffffffffff8111156120d357600080fd5b6120df85828601611f68565b9150509250929050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60008282101561215957612159612118565b500390565b60005b83811015612179578181015183820152602001612161565b83811115612188576000848401525b50505050565b600083516121a081846020880161215e565b7f2e0000000000000000000000000000000000000000000000000000000000000090830190815283516121da81600184016020880161215e565b01600101949350505050565b602081526000825180602084015261220581604085016020870161215e565b601f01601f19169190910160400192915050565b805173ffffffffffffffffffffffffffffffffffffffff8116811461039457600080fd5b60006020828403121561224f57600080fd5b6103a582612219565b60208152816020820152818360408301376000818301604090810191909152601f909201601f19160101919050565b805160ff8116811461039457600080fd5b600082601f8301126122a957600080fd5b81516122b7611f8782611f40565b8181528460208386010111156122cc57600080fd5b61052982602083016020870161215e565b600060208083850312156122f057600080fd5b825167ffffffffffffffff8082111561230857600080fd5b818501915082828703121561231c57600080fd5b612324611ec2565b82518281111561233357600080fd5b80840193505086601f84011261234857600080fd5b82518281111561235a5761235a611e93565b8060051b612369868201611f0f565b918252848101860191868101908a84111561238357600080fd5b87870192505b8383101561246d578251868111156123a057600080fd5b8701610100818d03601f19018113156123b857600080fd5b6123c0611eeb565b6123cb8b8401612287565b81526123d960408401612219565b8b8201526060830151898111156123ef57600080fd5b6123fd8f8d83870101612298565b6040830152506080830151606082015260a061241a818501612287565b608083015260c0808501518284015260e091508185015181840152508284015192508983111561244a5760008081fd5b6124588f8d85870101612298565b90820152845250509187019190870190612389565b8452509198975050505050505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b6000826124ea576124ea6124ac565b500690565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82141561252157612521612118565b5060010190565b8183823760009101908152919050565b600082612547576125476124ac565b500490565b6000821982111561255f5761255f612118565b500190565b600060ff821660ff84168060ff0382111561258157612581612118565b019392505050565b848152600060208581840152846040840152606083018460005b60ff8110156125c0578151835291830191908301906001016125a3565b505050506120408201905095945050505050565b7fff00000000000000000000000000000000000000000000000000000000000000831681526000825161260e81600185016020870161215e565b919091016001019392505050565b6000835161262e81846020880161215e565b83519083019061264281836020880161215e565b01949350505050565b6000817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff048311821515161561268357612683612118565b500290565b600181815b808511156126e157817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff048211156126c7576126c7612118565b808516156126d457918102915b93841c939080029061268d565b509250929050565b6000826126f85750600161022d565b816127055750600061022d565b816001811461271b576002811461272557612741565b600191505061022d565b60ff84111561273657612736612118565b50506001821b61022d565b5060208310610133831016604e8410600b8410161715612764575081810a61022d565b61276e8383612688565b807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff048211156127a0576127a0612118565b029392505050565b60006103a583836126e956fea264697066735822122033da65b31403f3528dc6eca551c4217b5ea7512d6e8827e9af8f7449068335bf64736f6c63430008090033", + "balance": "0x0" + }, + "0x0000777700000000000000000000000000000004": { + "contractName": "Bridge", + "storage": { + "0x0000000000000000000000000000000000000000000000000000000000000000": "0x0000000000000000000000000000000000000000000000000000000000000001", + "0x0000000000000000000000000000000000000000000000000000000000000001": "0x0000000000000000000000000000000000000000000000000000000000000001", + "0x0000000000000000000000000000000000000000000000000000000000000065": "0x00000000000000000000000026250179c8e8e12104e556c4cd03bcf4dabd51b9", + "0x0000000000000000000000000000000000000000000000000000000000000097": "0x0000000000000000000000000000777700000000000000000000000000000006" + }, + "code": "0x6080604052600436106101485760003560e01c80636950f0de116100c0578063d0496d6a11610074578063f2fde38b11610059578063f2fde38b14610421578063f980391914610441578063fee99b221461046157600080fd5b8063d0496d6a14610385578063f16c79341461040157600080fd5b80638da5cb5b116100a55780638da5cb5b1461031957806396e1785214610344578063a4444efd1461036557600080fd5b80636950f0de146102e4578063715018a61461030457600080fd5b8063461a447811610117578063540be6a3116100fc578063540be6a3146102745780635d0bd9861461029457806366ca2bc0146102c457600080fd5b8063461a4478146102175780635075a9d41461023757600080fd5b806319ab453c1461015457806332676bc6146101765780633ab76e9f146101ab5780633aec8585146101f757600080fd5b3661014f57005b600080fd5b34801561016057600080fd5b5061017461016f36600461260a565b610481565b005b34801561018257600080fd5b50610196610191366004612627565b610600565b60405190151581526020015b60405180910390f35b3480156101b757600080fd5b5060975473ffffffffffffffffffffffffffffffffffffffff165b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016101a2565b34801561020357600080fd5b5061019661021236600461269c565b610615565b34801561022357600080fd5b506101d2610232366004612851565b610672565b34801561024357600080fd5b50610267610252366004612886565b600090815260ca602052604090205460ff1690565b6040516101a2919061289f565b34801561028057600080fd5b5061019661028f366004612886565b61067e565b3480156102a057600080fd5b506101966102af366004612886565b600090815260c9602052604090205460ff1690565b3480156102d057600080fd5b506101746102df366004612886565b61068a565b3480156102f057600080fd5b506101746102ff3660046128f0565b6106d0565b34801561031057600080fd5b5061017461073c565b34801561032557600080fd5b5060655473ffffffffffffffffffffffffffffffffffffffff166101d2565b610357610352366004612935565b610750565b6040519081526020016101a2565b34801561037157600080fd5b5061019661038036600461296a565b6107c8565b34801561039157600080fd5b50604080516060808201835260008083526020808401829052928401528251808201845260cc5480825260cd5473ffffffffffffffffffffffffffffffffffffffff90811683860190815260ce5493870193845286519283525116938101939093525192820192909252016101a2565b34801561040d57600080fd5b506101d261041c3660046129bd565b610824565b34801561042d57600080fd5b5061017461043c36600461260a565b610830565b34801561044d57600080fd5b5061017461045c366004612a04565b6108cd565b34801561046d57600080fd5b5061017461047c366004612a49565b6109b4565b600054610100900460ff16158080156104a15750600054600160ff909116105b806104bb5750303b1580156104bb575060005460ff166001145b6105325760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a656400000000000000000000000000000000000060648201526084015b60405180910390fd5b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001179055801561059057600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff166101001790555b61059982610a9e565b80156105fc57600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b5050565b600061060c8383610ab7565b90505b92915050565b600080610657866040518060400160405280600681526020017f6272696467650000000000000000000000000000000000000000000000000000815250610824565b90506106673082878a8888610bc9565b979650505050505050565b600061060f4683610f96565b600061060f3083610ab7565b610694338261108f565b60408051338152602081018390527ff0958489d2a32db2b0faf27a72a31fdf28f2636ca5532f1b077ddc2f51b20d1d910160405180910390a150565b600260015414156107235760405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c006044820152606401610529565b600260015561073460c9838361119d565b505060018055565b61074461126d565b61074e60006112d4565b565b6000600260015414156107a55760405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c006044820152606401610529565b60026001556107be60c9306107b985612ab2565b61134b565b6001805592915050565b60008061080a856040518060400160405280600681526020017f6272696467650000000000000000000000000000000000000000000000000000815250610824565b905061081a308283898888610bc9565b9695505050505050565b600061060c8383610f96565b61083861126d565b73ffffffffffffffffffffffffffffffffffffffff81166108c15760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201527f64647265737300000000000000000000000000000000000000000000000000006064820152608401610529565b6108ca816112d4565b50565b600260015414156109205760405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c006044820152606401610529565b60026001556040517f46eb9db5000000000000000000000000000000000000000000000000000000008152738A9E82Ebf0E219BBdB4fBBd50FEd45d098a8Ba1e906346eb9db59061097c9060c990309087908790600401612d8e565b60006040518083038186803b15801561099457600080fd5b505af41580156109a8573d6000803e3d6000fd5b50505050505060018055565b60026001541415610a075760405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c006044820152606401610529565b60026001556040517fc0249e2d00000000000000000000000000000000000000000000000000000000815273f7c52068c40213E7C49313B0d6FCc11Cb2C45dbF9063c0249e2d90610a659060c9903090889088908890600401612dd6565b60006040518083038186803b158015610a7d57600080fd5b505af4158015610a91573d6000803e3d6000fd5b5050505050506001805550565b610aa6611626565b610aae6116ab565b6108ca81611730565b6000828273ffffffffffffffffffffffffffffffffffffffff8216610b1e5760405162461bcd60e51b815260206004820152600860248201527f423a73656e6465720000000000000000000000000000000000000000000000006044820152606401610529565b80610b6b5760405162461bcd60e51b815260206004820152600860248201527f423a7369676e616c0000000000000000000000000000000000000000000000006044820152606401610529565b50506040805160609490941b7fffffffffffffffffffffffffffffffffffffffff0000000000000000000000001660208086019190915260348086019490945281518086039094018452605490940190525080519101205460011490565b6000848473ffffffffffffffffffffffffffffffffffffffff8216610c305760405162461bcd60e51b815260206004820152600860248201527f423a73656e6465720000000000000000000000000000000000000000000000006044820152606401610529565b80610c7d5760405162461bcd60e51b815260206004820152600860248201527f423a7369676e616c0000000000000000000000000000000000000000000000006044820152606401610529565b73ffffffffffffffffffffffffffffffffffffffff8816610ce05760405162461bcd60e51b815260206004820152600b60248201527f423a7372634272696467650000000000000000000000000000000000000000006044820152606401610529565b6000610cee85870187612ed0565b905073C5d653E17c24928B788a17838F11d2AcF0c922A363960304398260000151606001518b610d738c8c6040517fffffffffffffffffffffffffffffffffffffffff000000000000000000000000606084901b1660208201526034810182905260009060540160405160208183030381529060405280519060200120905092915050565b60208601516040517fffffffff0000000000000000000000000000000000000000000000000000000060e087901b168152610db6949392916001916004016130e3565b60006040518083038186803b158015610dce57600080fd5b505af4158015610de2573d6000803e3d6000fd5b50506040517f461a447800000000000000000000000000000000000000000000000000000000815260206004820152600560248201527f7461696b6f00000000000000000000000000000000000000000000000000000060448201526000925073ffffffffffffffffffffffffffffffffffffffff8d16915063461a44789060640160206040518083038186803b158015610e7c57600080fd5b505afa158015610e90573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610eb49190613124565b825161010001516040517f25bf86f20000000000000000000000000000000000000000000000000000000081526fffffffffffffffffffffffffffffffff909116600482015273ffffffffffffffffffffffffffffffffffffffff91909116906325bf86f29060240160206040518083038186803b158015610f3557600080fd5b505afa158015610f49573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f6d9190613141565b90508015801590610f8757508151610f84906117da565b81145b9b9a5050505050505050505050565b600080610fa284611b94565b83604051602001610fb492919061315a565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152908290526097547fbf40fac100000000000000000000000000000000000000000000000000000000835290925073ffffffffffffffffffffffffffffffffffffffff169063bf40fac1906110379084906004016131b2565b60206040518083038186803b15801561104f57600080fd5b505afa158015611063573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110879190613124565b949350505050565b818173ffffffffffffffffffffffffffffffffffffffff82166110f45760405162461bcd60e51b815260206004820152600860248201527f423a73656e6465720000000000000000000000000000000000000000000000006044820152606401610529565b806111415760405162461bcd60e51b815260206004820152600860248201527f423a7369676e616c0000000000000000000000000000000000000000000000006044820152606401610529565b50506040805160609390931b7fffffffffffffffffffffffffffffffffffffffff000000000000000000000000166020808501919091526034808501939093528151808503909301835260549093019052805191012060019055565b6000821180156111ad5750468214155b6111f95760405162461bcd60e51b815260206004820152600960248201527f423a636861696e496400000000000000000000000000000000000000000000006044820152606401610529565b6000828152602084815260409182902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016841515908117909155915191825283917f9f391218c06d4fc365ceb15f340bb3d77306b28ac0b8d4e519aec2654794536d910160405180910390a2505050565b60655473ffffffffffffffffffffffffffffffffffffffff16331461074e5760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610529565b6065805473ffffffffffffffffffffffffffffffffffffffff8381167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b608081015160009073ffffffffffffffffffffffffffffffffffffffff166113b55760405162461bcd60e51b815260206004820152600760248201527f423a6f776e6572000000000000000000000000000000000000000000000000006044820152606401610529565b468260600151141580156113dc5750606082015160009081526020859052604090205460ff165b6114285760405162461bcd60e51b815260206004820152600d60248201527f423a64657374436861696e4964000000000000000000000000000000000000006044820152606401610529565b60008261012001518361010001518460e0015161144591906131f4565b61144f91906131f4565b90503481146114a05760405162461bcd60e51b815260206004820152600760248201527f423a76616c7565000000000000000000000000000000000000000000000000006044820152606401610529565b6040517f461a447800000000000000000000000000000000000000000000000000000000815260206004820152600b60248201527f65746865725f7661756c74000000000000000000000000000000000000000000604482015260009073ffffffffffffffffffffffffffffffffffffffff86169063461a44789060640160206040518083038186803b15801561153657600080fd5b505afa15801561154a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061156e9190613124565b905073ffffffffffffffffffffffffffffffffffffffff8116156115ac576115ac73ffffffffffffffffffffffffffffffffffffffff821683611cc6565b6002860180549060006115be8361320c565b9091555084523360208501524660408501526115d984611d81565b92506115e5308461108f565b827f47866f7dacd4a276245be6ed543cae03c9c17eb17e6980cee28e3dd168b7f9f3856040516116159190613362565b60405180910390a250509392505050565b600054610100900460ff166116a35760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401610529565b61074e611db1565b600054610100900460ff166117285760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401610529565b61074e611e34565b73ffffffffffffffffffffffffffffffffffffffff81166117935760405162461bcd60e51b815260206004820152600e60248201527f41523a7a65726f416464726573730000000000000000000000000000000000006044820152606401610529565b609780547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff92909216919091179055565b60006060826101e001516000141561181f5760408051600f808252610200820190925290816020015b606081526020019060019003908161180357905050905061184e565b604080516010808252610220820190925290816020015b60608152602001906001900390816118365790505090505b825161185990611eba565b8160008151811061186c5761186c613375565b60200260200101819052506118848360200151611eba565b8160018151811061189757611897613375565b60200260200101819052506118af8360400151611ecd565b816002815181106118c2576118c2613375565b60200260200101819052506118da8360600151611eba565b816003815181106118ed576118ed613375565b60200260200101819052506119058360800151611eba565b8160048151811061191857611918613375565b60200260200101819052506119308360a00151611eba565b8160058151811061194357611943613375565b602002602001018190525061197a8360c0015160405160200161196691906133a4565b604051602081830303815290604052611f09565b8160068151811061198d5761198d613375565b60200260200101819052506119a58360e00151611f78565b816007815181106119b8576119b8613375565b60200260200101819052506119e38361010001516fffffffffffffffffffffffffffffffff16611f78565b816008815181106119f6576119f6613375565b6020026020010181905250611a0f836101200151611f86565b81600981518110611a2257611a22613375565b6020026020010181905250611a3b836101400151611f86565b81600a81518110611a4e57611a4e613375565b6020026020010181905250611a67836101600151611f86565b81600b81518110611a7a57611a7a613375565b6020026020010181905250611a93836101800151611f09565b81600c81518110611aa657611aa6613375565b6020026020010181905250611abf836101a00151611eba565b81600d81518110611ad257611ad2613375565b6020026020010181905250611b21836101c00151604051602001611966919060c09190911b7fffffffffffffffff00000000000000000000000000000000000000000000000016815260080190565b81600e81518110611b3457611b34613375565b6020026020010181905250826101e00151600014611b7957611b5a836101e00151611f78565b81600f81518110611b6d57611b6d613375565b60200260200101819052505b6000611b8482611f9e565b8051602090910120949350505050565b606081611bd457505060408051808201909152600181527f3000000000000000000000000000000000000000000000000000000000000000602082015290565b8160005b8115611bfe5780611be88161320c565b9150611bf79050600a83613408565b9150611bd8565b60008167ffffffffffffffff811115611c1957611c19612706565b6040519080825280601f01601f191660200182016040528015611c43576020820181803683370190505b5090505b841561108757611c5860018361341c565b9150611c65600a86613433565b611c709060306131f4565b60f81b818381518110611c8557611c85613375565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a905350611cbf600a86613408565b9450611c47565b80156105fc5760008273ffffffffffffffffffffffffffffffffffffffff168260405160006040518083038185875af1925050503d8060008114611d26576040519150601f19603f3d011682016040523d82523d6000602084013e611d2b565b606091505b5050905080611d7c5760405162461bcd60e51b815260206004820152601360248201527f455448207472616e73666572206661696c6564000000000000000000000000006044820152606401610529565b505050565b600081604051602001611d949190613447565b604051602081830303815290604052805190602001209050919050565b600054610100900460ff16611e2e5760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401610529565b60018055565b600054610100900460ff16611eb15760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401610529565b61074e336112d4565b606061060f611ec883611fe2565b611f09565b604051606082811b7fffffffffffffffffffffffffffffffffffffffff0000000000000000000000001660208301529061060f90603401611966565b60608082516001148015611f375750608083600081518110611f2d57611f2d613375565b016020015160f81c105b15611f4357508161060f565b611f4f835160806120d5565b83604051602001611f6192919061348e565b604051602081830303815290604052905092915050565b606061060f611ec8836122cb565b606061060f611ec88367ffffffffffffffff166122cb565b60606000611fab8361242d565b9050611fb9815160c06120d5565b81604051602001611fcb92919061348e565b604051602081830303815290604052915050919050565b6060600082604051602001611ff991815260200190565b604080518083037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe001815260208084528383019092529250600091829160208201818036833701905050905060005b81518110156120cc57838361205c8161320c565b94508151811061206e5761206e613375565b602001015160f81c60f81b82828151811061208b5761208b613375565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a905350806120c48161320c565b915050612048565b50949350505050565b6060806038841015612154576040805160018082528183019092529060208201818036833701905050905061210a83856134bd565b60f81b8160008151811061212057612120613375565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a90535061060c565b600060015b6121638187613408565b1561218957816121728161320c565b92506121829050610100826134e2565b9050612159565b6121948260016131f4565b67ffffffffffffffff8111156121ac576121ac612706565b6040519080825280601f01601f1916602001820160405280156121d6576020820181803683370190505b5092506121e385836134bd565b6121ee9060376134bd565b60f81b8360008151811061220457612204613375565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a905350600190505b8181116122c25761010061224c828461341c565b6122589061010061363f565b6122629088613408565b61226c9190613433565b60f81b83828151811061228157612281613375565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a905350806122ba8161320c565b915050612238565b50509392505050565b60606000826040516020016122e291815260200190565b604051602081830303815290604052905060005b60208110156123545781818151811061231157612311613375565b01602001517fff00000000000000000000000000000000000000000000000000000000000000161561234257612354565b8061234c8161320c565b9150506122f6565b600061236182602061341c565b67ffffffffffffffff81111561237957612379612706565b6040519080825280601f01601f1916602001820160405280156123a3576020820181803683370190505b50905060005b81518110156120cc5783836123bd8161320c565b9450815181106123cf576123cf613375565b602001015160f81c60f81b8282815181106123ec576123ec613375565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a905350806124258161320c565b9150506123a9565b606081516000141561244d57505060408051600081526020810190915290565b6000805b83518110156124945783818151811061246c5761246c613375565b6020026020010151518261248091906131f4565b91508061248c8161320c565b915050612451565b60008267ffffffffffffffff8111156124af576124af612706565b6040519080825280601f01601f1916602001820160405280156124d9576020820181803683370190505b50600092509050602081015b85518310156120cc57600086848151811061250257612502613375565b6020026020010151905060006020820190506125208382845161255d565b87858151811061253257612532613375565b6020026020010151518361254691906131f4565b9250505082806125559061320c565b9350506124e5565b8282825b6020811061259957815183526125786020846131f4565b92506125856020836131f4565b915061259260208261341c565b9050612561565b905182516020929092036101000a7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0180199091169116179052505050565b73ffffffffffffffffffffffffffffffffffffffff811681146108ca57600080fd5b8035612605816125d8565b919050565b60006020828403121561261c57600080fd5b813561060c816125d8565b6000806040838503121561263a57600080fd5b8235612645816125d8565b946020939093013593505050565b60008083601f84011261266557600080fd5b50813567ffffffffffffffff81111561267d57600080fd5b60208301915083602082850101111561269557600080fd5b9250929050565b6000806000806000608086880312156126b457600080fd5b853594506020860135935060408601356126cd816125d8565b9250606086013567ffffffffffffffff8111156126e957600080fd5b6126f588828901612653565b969995985093965092949392505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6040516101a0810167ffffffffffffffff8111828210171561275957612759612706565b60405290565b6040805190810167ffffffffffffffff8111828210171561275957612759612706565b604051610200810167ffffffffffffffff8111828210171561275957612759612706565b600082601f8301126127b757600080fd5b813567ffffffffffffffff808211156127d2576127d2612706565b604051601f83017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f0116810190828211818310171561281857612818612706565b8160405283815286602085880101111561283157600080fd5b836020870160208301376000602085830101528094505050505092915050565b60006020828403121561286357600080fd5b813567ffffffffffffffff81111561287a57600080fd5b611087848285016127a6565b60006020828403121561289857600080fd5b5035919050565b60208101600483106128da577f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b91905290565b8035801515811461260557600080fd5b6000806040838503121561290357600080fd5b82359150612913602084016128e0565b90509250929050565b60006101a0828403121561292f57600080fd5b50919050565b60006020828403121561294757600080fd5b813567ffffffffffffffff81111561295e57600080fd5b6110878482850161291c565b6000806000806060858703121561298057600080fd5b8435935060208501359250604085013567ffffffffffffffff8111156129a557600080fd5b6129b187828801612653565b95989497509550505050565b600080604083850312156129d057600080fd5b82359150602083013567ffffffffffffffff8111156129ee57600080fd5b6129fa858286016127a6565b9150509250929050565b60008060408385031215612a1757600080fd5b823567ffffffffffffffff811115612a2e57600080fd5b612a3a8582860161291c565b925050612913602084016128e0565b600080600060408486031215612a5e57600080fd5b833567ffffffffffffffff80821115612a7657600080fd5b612a828783880161291c565b94506020860135915080821115612a9857600080fd5b50612aa586828701612653565b9497909650939450505050565b60006101a08236031215612ac557600080fd5b612acd612735565b82358152612add602084016125fa565b60208201526040830135604082015260608301356060820152612b02608084016125fa565b6080820152612b1360a084016125fa565b60a0820152612b2460c084016125fa565b60c082015260e083810135908201526101008084013590820152610120808401359082015261014080840135908201526101608084013567ffffffffffffffff80821115612b7157600080fd5b612b7d368388016127a6565b83850152610180925082860135915080821115612b9957600080fd5b50612ba6368287016127a6565b918301919091525092915050565b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe1843603018112612be957600080fd5b830160208101925035905067ffffffffffffffff811115612c0957600080fd5b80360383131561269557600080fd5b8183528181602085013750600060208284010152600060207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f840116840101905092915050565b60006101a082358452612c76602084016125fa565b73ffffffffffffffffffffffffffffffffffffffff81166020860152506040830135604085015260608301356060850152612cb3608084016125fa565b73ffffffffffffffffffffffffffffffffffffffff166080850152612cda60a084016125fa565b73ffffffffffffffffffffffffffffffffffffffff1660a0850152612d0160c084016125fa565b73ffffffffffffffffffffffffffffffffffffffff1660c085015260e08381013590850152610100808401359085015261012080840135908501526101408084013590850152610160612d5681850185612bb4565b8383880152612d688488018284612c18565b9350505050610180612d7c81850185612bb4565b86840383880152610667848284612c18565b84815273ffffffffffffffffffffffffffffffffffffffff84166020820152608060408201526000612dc36080830185612c61565b9050821515606083015295945050505050565b85815273ffffffffffffffffffffffffffffffffffffffff85166020820152608060408201526000612e0b6080830186612c61565b8281036060840152612e1e818587612c18565b98975050505050505050565b600082601f830112612e3b57600080fd5b60405161010080820182811067ffffffffffffffff82111715612e6057612e60612706565b60405283018185821115612e7357600080fd5b845b82811015612e8d578035825260209182019101612e75565b509195945050505050565b80356fffffffffffffffffffffffffffffffff8116811461260557600080fd5b803567ffffffffffffffff8116811461260557600080fd5b600060208284031215612ee257600080fd5b813567ffffffffffffffff80821115612efa57600080fd5b9083019060408286031215612f0e57600080fd5b612f1661275f565b823582811115612f2557600080fd5b83016102e08188031215612f3857600080fd5b612f40612782565b8135815260208201356020820152612f5a604083016125fa565b6040820152606082013560608201526080820135608082015260a082013560a0820152612f8a8860c08401612e2a565b60c08201526101c08083013560e08301526101e0612fa9818501612e98565b610100840152612fbc6102008501612eb8565b610120840152612fcf6102208501612eb8565b610140840152612fe26102408501612eb8565b61016084015261026084013586811115612ffb57600080fd5b6130078b8287016127a6565b610180850152506102808401356101a08401526130276102a08501612eb8565b828401526102c0840135818401525050808352505060208301358281111561304e57600080fd5b61305a878286016127a6565b60208301525095945050505050565b60005b8381101561308457818101518382015260200161306c565b83811115613093576000848401525b50505050565b600081518084526130b1816020860160208601613069565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b85815273ffffffffffffffffffffffffffffffffffffffff8516602082015283604082015282606082015260a06080820152600061066760a0830184613099565b60006020828403121561313657600080fd5b815161060c816125d8565b60006020828403121561315357600080fd5b5051919050565b6000835161316c818460208801613069565b7f2e0000000000000000000000000000000000000000000000000000000000000090830190815283516131a6816001840160208801613069565b01600101949350505050565b60208152600061060c6020830184613099565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60008219821115613207576132076131c5565b500190565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82141561323e5761323e6131c5565b5060010190565b60006101a0825184526020830151613275602086018273ffffffffffffffffffffffffffffffffffffffff169052565b50604083015160408501526060830151606085015260808301516132b1608086018273ffffffffffffffffffffffffffffffffffffffff169052565b5060a08301516132d960a086018273ffffffffffffffffffffffffffffffffffffffff169052565b5060c083015161330160c086018273ffffffffffffffffffffffffffffffffffffffff169052565b5060e083810151908501526101008084015190850152610120808401519085015261014080840151908501526101608084015181860183905261334683870182613099565b92505050610180808401518583038287015261081a8382613099565b60208152600061060c6020830184613245565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b60008183825b60088110156133c95781518352602092830192909101906001016133aa565b5050506101008201905092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b600082613417576134176133d9565b500490565b60008282101561342e5761342e6131c5565b500390565b600082613442576134426133d9565b500690565b60408152601460408201527f5441494b4f5f4252494447455f4d455353414745000000000000000000000000606082015260806020820152600061060c6080830184613245565b600083516134a0818460208801613069565b8351908301906134b4818360208801613069565b01949350505050565b600060ff821660ff84168060ff038211156134da576134da6131c5565b019392505050565b6000817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff048311821515161561351a5761351a6131c5565b500290565b600181815b8085111561357857817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0482111561355e5761355e6131c5565b8085161561356b57918102915b93841c9390800290613524565b509250929050565b60008261358f5750600161060f565b8161359c5750600061060f565b81600181146135b257600281146135bc576135d8565b600191505061060f565b60ff8411156135cd576135cd6131c5565b50506001821b61060f565b5060208310610133831016604e8410600b84101617156135fb575081810a61060f565b613605838361351f565b807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff04821115613637576136376131c5565b029392505050565b600061060c838361358056fea2646970667358221220d5e1fe055176dc14480cf9170f5a503d79f8793c534119929c5bbb34db12f54764736f6c63430008090033", + "balance": "0x0" + }, + "0x0000777700000000000000000000000000000002": { + "contractName": "TokenVault", + "storage": { + "0x0000000000000000000000000000000000000000000000000000000000000000": "0x0000000000000000000000000000000000000000000000000000000000000001", + "0x0000000000000000000000000000000000000000000000000000000000000001": "0x0000000000000000000000000000000000000000000000000000000000000001", + "0x0000000000000000000000000000000000000000000000000000000000000065": "0x00000000000000000000000026250179c8e8e12104e556c4cd03bcf4dabd51b9", + "0x0000000000000000000000000000000000000000000000000000000000000097": "0x0000000000000000000000000000777700000000000000000000000000000006" + }, + "code": "0x6080604052600436106100d25760003560e01c8063715018a61161007f578063c287e57811610059578063c287e57814610228578063ee1490b214610268578063f16c79341461027b578063f2fde38b1461029b57600080fd5b8063715018a6146101c45780638da5cb5b146101d95780639aa8605c146101f757600080fd5b80633ab76e9f116100b05780633ab76e9f1461012c578063461a44781461016357806367090ccf1461018357600080fd5b80630c6fab82146100d757806319ab453c146100f957806339da33ba14610119575b600080fd5b3480156100e357600080fd5b506100f76100f2366004612459565b6102bb565b005b34801561010557600080fd5b506100f76101143660046124c8565b6105f9565b6100f76101273660046125c3565b610773565b34801561013857600080fd5b506097546001600160a01b03165b6040516001600160a01b0390911681526020015b60405180910390f35b34801561016f57600080fd5b5061014661017e366004612641565b610ad1565b34801561018f57600080fd5b5061014661019e366004612676565b60cb6020908152600092835260408084209091529082529020546001600160a01b031681565b3480156101d057600080fd5b506100f7610ae3565b3480156101e557600080fd5b506065546001600160a01b0316610146565b34801561020357600080fd5b506102176102123660046124c8565b610af7565b60405161015a9594939291906126fe565b34801561023457600080fd5b506102586102433660046124c8565b60c96020526000908152604090205460ff1681565b604051901515815260200161015a565b6100f761027636600461274d565b610c59565b34801561028757600080fd5b506101466102963660046127e9565b611682565b3480156102a757600080fd5b506100f76102b63660046124c8565b611695565b600260015414156103135760405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c0060448201526064015b60405180910390fd5b600260015560408051808201909152600681527f6272696467650000000000000000000000000000000000000000000000000000602082015261035581610ad1565b6001600160a01b0316336001600160a01b0316146103b55760405162461bcd60e51b815260206004820152600960248201527f41523a64656e6965640000000000000000000000000000000000000000000000604482015260640161030a565b6000336001600160a01b031663d0496d6a6040518163ffffffff1660e01b815260040160606040518083038186803b1580156103f057600080fd5b505afa158015610404573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906104289190612830565b905061046d81604001516040518060400160405280600b81526020017f746f6b656e5f7661756c74000000000000000000000000000000000000000000815250611682565b6001600160a01b031681602001516001600160a01b0316146104d15760405162461bcd60e51b815260206004820152600860248201527f563a73656e646572000000000000000000000000000000000000000000000000604482015260640161030a565b60008635461415610507576104ec60408801602089016124c8565b90506105026001600160a01b0382168686611725565b610590565b610510876117d3565b6040517f42e91bb30000000000000000000000000000000000000000000000000000000081526001600160a01b03878116600483015260248201879052919250908216906342e91bb390604401600060405180830381600087803b15801561057757600080fd5b505af115801561058b573d6000803e3d6000fd5b505050505b60408281015181516001600160a01b038981168252602082019290925283821681840152606081018790529151908716917f485a7041eaecffd5ef478f291c05a2a47a1e6af7e7780e46578f18bf03e1bf3f919081900360800190a25050600180555050505050565b600054610100900460ff16158080156106195750600054600160ff909116105b806106335750303b158015610633575060005460ff166001145b6106a55760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a6564000000000000000000000000000000000000606482015260840161030a565b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001179055801561070357600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff166101001790555b61070c8261182c565b801561076f57600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b5050565b600260015414156107c65760405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c00604482015260640161030a565b60026001556001600160a01b03851615801590610833575061081d866040518060400160405280600b81526020017f746f6b656e5f7661756c74000000000000000000000000000000000000000000815250611682565b6001600160a01b0316856001600160a01b031614155b6108815760405162461bcd60e51b815260040161030a9060208082526004908201527f563a746f00000000000000000000000000000000000000000000000000000000604082015260600190565b8234116108d05760405162461bcd60e51b815260206004820152600a60248201527f563a6d736756616c756500000000000000000000000000000000000000000000604482015260640161030a565b61095f604051806101a001604052806000815260200160006001600160a01b03168152602001600081526020016000815260200160006001600160a01b0316815260200160006001600160a01b0316815260200160006001600160a01b031681526020016000815260200160008152602001600081526020016000815260200160608152602001606081525090565b606081018790523360808201526001600160a01b03861660a08201526101408101859052610120810184905261099584346128c1565b60e08201526001600160a01b03831660c0820152610180810182905260408051808201909152600681527f627269646765000000000000000000000000000000000000000000000000000060208201526000906109f190610ad1565b6001600160a01b03166396e1785234846040518363ffffffff1660e01b8152600401610a1d91906128d8565b6020604051808303818588803b158015610a3657600080fd5b505af1158015610a4a573d6000803e3d6000fd5b50505050506040513d601f19601f82011682018060405250810190610a6f91906129d2565b60e0830151604080518b8152602081019290925281018290529091506001600160a01b038816907fc4f150c33b1c9146a833662318b1e72e3d07a471886bb6f3a547a8e0bc3a7cfa9060600160405180910390a2505060018055505050505050565b6000610add4683611845565b92915050565b610aeb611913565b610af5600061196d565b565b60ca6020526000908152604090208054600182015460028301805492936001600160a01b038316937401000000000000000000000000000000000000000090930460ff1692909190610b48906129eb565b80601f0160208091040260200160405190810160405280929190818152602001828054610b74906129eb565b8015610bc15780601f10610b9657610100808354040283529160200191610bc1565b820191906000526020600020905b815481529060010190602001808311610ba457829003601f168201915b505050505090806003018054610bd6906129eb565b80601f0160208091040260200160405190810160405280929190818152602001828054610c02906129eb565b8015610c4f5780601f10610c2457610100808354040283529160200191610c4f565b820191906000526020600020905b815481529060010190602001808311610c3257829003601f168201915b5050505050905085565b60026001541415610cac5760405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c00604482015260640161030a565b60026001556001600160a01b03871615801590610d195750610d03886040518060400160405280600b81526020017f746f6b656e5f7661756c74000000000000000000000000000000000000000000815250611682565b6001600160a01b0316876001600160a01b031614155b610d675760405162461bcd60e51b815260040161030a9060208082526004908201527f563a746f00000000000000000000000000000000000000000000000000000000604082015260600190565b6001600160a01b038616610dbd5760405162461bcd60e51b815260206004820152600760248201527f563a746f6b656e00000000000000000000000000000000000000000000000000604482015260640161030a565b60008511610e0d5760405162461bcd60e51b815260206004820152600860248201527f563a616d6f756e74000000000000000000000000000000000000000000000000604482015260640161030a565b6040805160a08101825260008082526020820181905291810191909152606080820181905260808201526001600160a01b038716600090815260c9602052604081205460ff16156110bd576040517f77be18a8000000000000000000000000000000000000000000000000000000008152336004820152602481018890526001600160a01b038916906377be18a890604401600060405180830381600087803b158015610eb957600080fd5b505af1158015610ecd573d6000803e3d6000fd5b505050506001600160a01b03888116600090815260ca6020908152604091829020825160a081018452815481526001820154948516928101929092527401000000000000000000000000000000000000000090930460ff1691810191909152600282018054919291606084019190610f44906129eb565b80601f0160208091040260200160405190810160405280929190818152602001828054610f70906129eb565b8015610fbd5780601f10610f9257610100808354040283529160200191610fbd565b820191906000526020600020905b815481529060010190602001808311610fa057829003601f168201915b50505050508152602001600382018054610fd6906129eb565b80601f0160208091040260200160405190810160405280929190818152602001828054611002906129eb565b801561104f5780601f106110245761010080835404028352916020019161104f565b820191906000526020600020905b81548152906001019060200180831161103257829003601f168201915b5050509190925250505060208101519092506001600160a01b03166110b65760405162461bcd60e51b815260206004820152601060248201527f563a63616e6f6e6963616c546f6b656e00000000000000000000000000000000604482015260640161030a565b508561139a565b60008890506040518060a001604052804681526020018a6001600160a01b03168152602001826001600160a01b031663313ce5676040518163ffffffff1660e01b815260040160206040518083038186803b15801561111b57600080fd5b505afa15801561112f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111539190612a4e565b60ff168152602001826001600160a01b03166395d89b416040518163ffffffff1660e01b815260040160006040518083038186803b15801561119457600080fd5b505afa1580156111a8573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526111d09190810190612a6b565b8152602001826001600160a01b03166306fdde036040518163ffffffff1660e01b815260040160006040518083038186803b15801561120e57600080fd5b505afa158015611222573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405261124a9190810190612a6b565b90526040517f70a082310000000000000000000000000000000000000000000000000000000081523060048201529093506000906001600160a01b038316906370a082319060240160206040518083038186803b1580156112aa57600080fd5b505afa1580156112be573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112e291906129d2565b90506112f96001600160a01b03831633308c6119d7565b6040517f70a0823100000000000000000000000000000000000000000000000000000000815230600482015281906001600160a01b038416906370a082319060240160206040518083038186803b15801561135357600080fd5b505afa158015611367573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061138b91906129d2565b61139591906128c1565b925050505b611429604051806101a001604052806000815260200160006001600160a01b03168152602001600081526020016000815260200160006001600160a01b0316815260200160006001600160a01b0316815260200160006001600160a01b031681526020016000815260200160008152602001600081526020016000815260200160608152602001606081525090565b606081018b905233608082015260408051808201909152600b81527f746f6b656e5f7661756c740000000000000000000000000000000000000000006020820152611475908c90611682565b6001600160a01b031660a082015260808101516040517f0c6fab8200000000000000000000000000000000000000000000000000000000916114c0918691908e908790602401612ae2565b60408051601f198184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff00000000000000000000000000000000000000000000000000000000909316929092179091526101608201526101408101879052610120810186905261153f86346128c1565b60e08201526001600160a01b03851660c0820152610180810184905260408051808201909152600681527f6272696467650000000000000000000000000000000000000000000000000000602082015260009061159b90610ad1565b6001600160a01b03166396e1785234846040518363ffffffff1660e01b81526004016115c791906128d8565b6020604051808303818588803b1580156115e057600080fd5b505af11580156115f4573d6000803e3d6000fd5b50505050506040513d601f19601f8201168201806040525081019061161991906129d2565b604080518e81526001600160a01b038d81166020830152918101869052606081018390529192508c16907ffd41c851d9a68cdf761055c8f7cb21010b653b27f89f6e3fa224a75eb82a40ac9060800160405180910390a250506001805550505050505050505050565b600061168e8383611845565b9392505050565b61169d611913565b6001600160a01b0381166117195760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201527f6464726573730000000000000000000000000000000000000000000000000000606482015260840161030a565b6117228161196d565b50565b6040516001600160a01b0383166024820152604481018290526117ce9084907fa9059cbb00000000000000000000000000000000000000000000000000000000906064015b60408051601f198184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff0000000000000000000000000000000000000000000000000000000090931692909217909152611a2e565b505050565b8035600090815260cb602090815260408083208392909183916117fa9187019087016124c8565b6001600160a01b03908116825260208201929092526040016000205416905080610add5761182783611b13565b61168e565b611834611dd0565b61183c611e55565b61172281611eda565b60008061185184611f6a565b83604051602001611863929190612b99565b60408051601f19818403018152908290526097547fbf40fac10000000000000000000000000000000000000000000000000000000083529092506001600160a01b03169063bf40fac1906118bb908490600401612bf1565b60206040518083038186803b1580156118d357600080fd5b505afa1580156118e7573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061190b9190612c04565b949350505050565b6065546001600160a01b03163314610af55760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015260640161030a565b606580546001600160a01b038381167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b6040516001600160a01b0380851660248301528316604482015260648101829052611a289085907f23b872dd000000000000000000000000000000000000000000000000000000009060840161176a565b50505050565b6000611a83826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b031661209c9092919063ffffffff16565b8051909150156117ce5780806020019051810190611aa19190612c21565b6117ce5760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f74207375636365656400000000000000000000000000000000000000000000606482015260840161030a565b6000808235611b2860408501602086016124c8565b604051602001611b6792919091825260601b7fffffffffffffffffffffffffffffffffffffffff00000000000000000000000016602082015260340190565b604051602081830303815290604052805190602001209050611bad60008260405180602001611b9590612437565b601f1982820381018352601f909101166040526120ab565b6097549092506001600160a01b0380841691636c0db62b9116611bd660408701602088016124c8565b8635611be86060890160408a01612c43565b611bf560608a018a612c60565b611c0260808c018c612c60565b604051611c169291908e3590602001612ccc565b6040516020818303038152906040526040518863ffffffff1660e01b8152600401611c479796959493929190612d7a565b600060405180830381600087803b158015611c6157600080fd5b505af1158015611c75573d6000803e3d6000fd5b5050506001600160a01b038316600090815260c96020908152604080832080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016600117905560ca9091529020849150611cd08282612f21565b50508235600090815260cb60209081526040808320859390929091611cfa919088019088016124c8565b6001600160a01b03166001600160a01b0316815260200190815260200160002060006101000a8154816001600160a01b0302191690836001600160a01b03160217905550816001600160a01b0316836020016020810190611d5b91906124c8565b6001600160a01b031684357f9e465b29e576a3e01584e31d607353f21b80c055e813af907c0a495f6cf4f7bc611d946060880188612c60565b611da160808a018a612c60565b611db160608c0160408d01612c43565b604051611dc2959493929190612ff9565b60405180910390a450919050565b600054610100900460ff16611e4d5760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e67000000000000000000000000000000000000000000606482015260840161030a565b610af56121ad565b600054610100900460ff16611ed25760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e67000000000000000000000000000000000000000000606482015260840161030a565b610af5612230565b6001600160a01b038116611f305760405162461bcd60e51b815260206004820152600e60248201527f41523a7a65726f41646472657373000000000000000000000000000000000000604482015260640161030a565b609780547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b0392909216919091179055565b606081611faa57505060408051808201909152600181527f3000000000000000000000000000000000000000000000000000000000000000602082015290565b8160005b8115611fd45780611fbe81613036565b9150611fcd9050600a8361309e565b9150611fae565b60008167ffffffffffffffff811115611fef57611fef6124e5565b6040519080825280601f01601f191660200182016040528015612019576020820181803683370190505b5090505b841561190b5761202e6001836128c1565b915061203b600a866130b2565b6120469060306130c6565b60f81b81838151811061205b5761205b6130de565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a905350612095600a8661309e565b945061201d565b606061190b84846000856122b6565b600080844710156120fe5760405162461bcd60e51b815260206004820152601d60248201527f437265617465323a20696e73756666696369656e742062616c616e6365000000604482015260640161030a565b825161214c5760405162461bcd60e51b815260206004820181905260248201527f437265617465323a2062797465636f6465206c656e677468206973207a65726f604482015260640161030a565b8383516020850187f590506001600160a01b03811661190b5760405162461bcd60e51b815260206004820152601960248201527f437265617465323a204661696c6564206f6e206465706c6f7900000000000000604482015260640161030a565b600054610100900460ff1661222a5760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e67000000000000000000000000000000000000000000606482015260840161030a565b60018055565b600054610100900460ff166122ad5760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e67000000000000000000000000000000000000000000606482015260840161030a565b610af53361196d565b60608247101561232e5760405162461bcd60e51b815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f60448201527f722063616c6c0000000000000000000000000000000000000000000000000000606482015260840161030a565b6001600160a01b0385163b6123855760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e7472616374000000604482015260640161030a565b600080866001600160a01b031685876040516123a1919061310d565b60006040518083038185875af1925050503d80600081146123de576040519150601f19603f3d011682016040523d82523d6000602084013e6123e3565b606091505b50915091506123f38282866123fe565b979650505050505050565b6060831561240d57508161168e565b82511561241d5782518084602001fd5b8160405162461bcd60e51b815260040161030a9190612bf1565b6120a08061312a83390190565b6001600160a01b038116811461172257600080fd5b6000806000806080858703121561246f57600080fd5b843567ffffffffffffffff81111561248657600080fd5b850160a0818803121561249857600080fd5b935060208501356124a881612444565b925060408501356124b881612444565b9396929550929360600135925050565b6000602082840312156124da57600080fd5b813561168e81612444565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b604051601f8201601f1916810167ffffffffffffffff8111828210171561253d5761253d6124e5565b604052919050565b600067ffffffffffffffff82111561255f5761255f6124e5565b50601f01601f191660200190565b600082601f83011261257e57600080fd5b813561259161258c82612545565b612514565b8181528460208386010111156125a657600080fd5b816020850160208301376000918101602001919091529392505050565b60008060008060008060c087890312156125dc57600080fd5b8635955060208701356125ee81612444565b94506040870135935060608701359250608087013561260c81612444565b915060a087013567ffffffffffffffff81111561262857600080fd5b61263489828a0161256d565b9150509295509295509295565b60006020828403121561265357600080fd5b813567ffffffffffffffff81111561266a57600080fd5b61190b8482850161256d565b6000806040838503121561268957600080fd5b82359150602083013561269b81612444565b809150509250929050565b60005b838110156126c15781810151838201526020016126a9565b83811115611a285750506000910152565b600081518084526126ea8160208601602086016126a6565b601f01601f19169290920160200192915050565b8581526001600160a01b038516602082015260ff8416604082015260a06060820152600061272f60a08301856126d2565b828103608084015261274181856126d2565b98975050505050505050565b600080600080600080600080610100898b03121561276a57600080fd5b88359750602089013561277c81612444565b9650604089013561278c81612444565b9550606089013594506080890135935060a0890135925060c08901356127b181612444565b915060e089013567ffffffffffffffff8111156127cd57600080fd5b6127d98b828c0161256d565b9150509295985092959890939650565b600080604083850312156127fc57600080fd5b82359150602083013567ffffffffffffffff81111561281a57600080fd5b6128268582860161256d565b9150509250929050565b60006060828403121561284257600080fd5b6040516060810181811067ffffffffffffffff82111715612865576128656124e5565b60405282518152602083015161287a81612444565b60208201526040928301519281019290925250919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b6000828210156128d3576128d3612892565b500390565b6020815281516020820152600060208301516128ff60408401826001600160a01b03169052565b506040830151606083015260608301516080830152608083015161292e60a08401826001600160a01b03169052565b5060a08301516001600160a01b03811660c08401525060c08301516001600160a01b03811660e08401525060e0830151610100838101919091528301516101208084019190915283015161014080840191909152830151610160808401919091528301516101a06101808085018290526129ac6101c08601846126d2565b90860151858203601f1901838701529092506129c883826126d2565b9695505050505050565b6000602082840312156129e457600080fd5b5051919050565b600181811c908216806129ff57607f821691505b60208210811415612a39577f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b50919050565b60ff8116811461172257600080fd5b600060208284031215612a6057600080fd5b815161168e81612a3f565b600060208284031215612a7d57600080fd5b815167ffffffffffffffff811115612a9457600080fd5b8201601f81018413612aa557600080fd5b8051612ab361258c82612545565b818152856020838501011115612ac857600080fd5b612ad98260208301602086016126a6565b95945050505050565b6080815284516080820152600060208601516001600160a01b0380821660a085015260ff60408901511660c08501526060880151915060a060e0850152612b2d6101208501836126d2565b915060808801517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8085840301610100860152612b6983826126d2565b9188166020860152506001600160a01b03861660408501529150612b8a9050565b82606083015295945050505050565b60008351612bab8184602088016126a6565b7f2e000000000000000000000000000000000000000000000000000000000000009083019081528351612be58160018401602088016126a6565b01600101949350505050565b60208152600061168e60208301846126d2565b600060208284031215612c1657600080fd5b815161168e81612444565b600060208284031215612c3357600080fd5b8151801515811461168e57600080fd5b600060208284031215612c5557600080fd5b813561168e81612a3f565b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe1843603018112612c9557600080fd5b83018035915067ffffffffffffffff821115612cb057600080fd5b602001915036819003821315612cc557600080fd5b9250929050565b828482377f286272696467656400000000000000000000000000000000000000000000000092019182527ff09f8c88000000000000000000000000000000000000000000000000000000006008830152600c8201527f2900000000000000000000000000000000000000000000000000000000000000602c820152602d01919050565b818352818160208501375060006020828401015260006020601f19601f840116840101905092915050565b60006001600160a01b03808a16835280891660208401525086604083015260ff8616606083015260c06080830152612db660c083018587612d4f565b82810360a0840152612dc881856126d2565b9a9950505050505050505050565b601f8211156117ce57600081815260208120601f850160051c81016020861015612dfd5750805b601f850160051c820191505b81811015612e1c57828155600101612e09565b505050505050565b67ffffffffffffffff831115612e3c57612e3c6124e5565b612e5083612e4a83546129eb565b83612dd6565b6000601f841160018114612ea25760008515612e6c5750838201355b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600387901b1c1916600186901b178355612f1a565b600083815260209020601f19861690835b82811015612ed35786850135825560209485019460019092019101612eb3565b5086821015612f0e577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff60f88860031b161c19848701351681555b505060018560011b0183555b5050505050565b81358155600181016020830135612f3781612444565b6001600160a01b03811690508154817fffffffffffffffffffffffff000000000000000000000000000000000000000082161783556040850135612f7a81612a3f565b74ff00000000000000000000000000000000000000008160a01b16837fffffffffffffffffffffff00000000000000000000000000000000000000000084161717845550505050612fce6060830183612c60565b612fdc818360028601612e24565b5050612feb6080830183612c60565b611a28818360038601612e24565b60608152600061300d606083018789612d4f565b8281036020840152613020818688612d4f565b91505060ff831660408301529695505050505050565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82141561306857613068612892565b5060010190565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b6000826130ad576130ad61306f565b500490565b6000826130c1576130c161306f565b500690565b600082198211156130d9576130d9612892565b500190565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b6000825161311f8184602087016126a6565b919091019291505056fe608060405234801561001057600080fd5b50612080806100206000396000f3fe608060405234801561001057600080fd5b506004361061018d5760003560e01c80636c0db62b116100e357806395d89b411161008c578063dd62ed3e11610066578063dd62ed3e146103b0578063f16c7934146103f6578063f2fde38b1461040957600080fd5b806395d89b4114610382578063a457c2d71461038a578063a9059cbb1461039d57600080fd5b806377be18a8116100bd57806377be18a8146103315780637cf8ed0d146103445780638da5cb5b1461036457600080fd5b80636c0db62b146102e057806370a08231146102f3578063715018a61461032957600080fd5b80633950935111610145578063461a44781161011f578063461a44781461027457806349d126051461028757806367e828bf1461029057600080fd5b8063395093511461020d5780633ab76e9f1461022057806342e91bb31461025f57600080fd5b806318160ddd1161017657806318160ddd146101d357806323b872dd146101e5578063313ce567146101f857600080fd5b806306fdde0314610192578063095ea7b3146101b0575b600080fd5b61019a61041c565b6040516101a79190611b2e565b60405180910390f35b6101c36101be366004611ba1565b6104ae565b60405190151581526020016101a7565b60cb545b6040519081526020016101a7565b6101c36101f3366004611bcd565b6104c6565b60ce5460405160ff90911681526020016101a7565b6101c361021b366004611ba1565b610546565b60975473ffffffffffffffffffffffffffffffffffffffff165b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016101a7565b61027261026d366004611ba1565b610592565b005b61023a610282366004611ce8565b6106aa565b6101d760fc5481565b6102b460fb5460fc5473ffffffffffffffffffffffffffffffffffffffff90911691565b6040805173ffffffffffffffffffffffffffffffffffffffff90931683526020830191909152016101a7565b6102726102ee366004611d1d565b6106bc565b6101d7610301366004611dc7565b73ffffffffffffffffffffffffffffffffffffffff16600090815260c9602052604090205490565b610272610921565b61027261033f366004611ba1565b610935565b60fb5461023a9073ffffffffffffffffffffffffffffffffffffffff1681565b60655473ffffffffffffffffffffffffffffffffffffffff1661023a565b61019a610a40565b6101c3610398366004611ba1565b610a4f565b6101c36103ab366004611ba1565b610b11565b6101d76103be366004611de4565b73ffffffffffffffffffffffffffffffffffffffff918216600090815260ca6020908152604080832093909416825291909152205490565b61023a610404366004611e1d565b610b8a565b610272610417366004611dc7565b610b96565b606060cc805461042b90611e64565b80601f016020809104026020016040519081016040528092919081815260200182805461045790611e64565b80156104a45780601f10610479576101008083540402835291602001916104a4565b820191906000526020600020905b81548152906001019060200180831161048757829003601f168201915b5050505050905090565b6000336104bc818585610c33565b5060019392505050565b600073ffffffffffffffffffffffffffffffffffffffff83163014156105335760405162461bcd60e51b815260206004820152600560248201527f42453a746f00000000000000000000000000000000000000000000000000000060448201526064015b60405180910390fd5b61053e848484610db2565b949350505050565b33600081815260ca6020908152604080832073ffffffffffffffffffffffffffffffffffffffff871684529091528120549091906104bc908290869061058d908790611ee7565b610c33565b6040518060400160405280600b81526020017f746f6b656e5f7661756c740000000000000000000000000000000000000000008152506105d1816106aa565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161461064b5760405162461bcd60e51b815260206004820152600960248201527f41523a64656e6965640000000000000000000000000000000000000000000000604482015260640161052a565b6106558383610dcb565b8273ffffffffffffffffffffffffffffffffffffffff167f397b33b307fc137878ebfc75b295289ec0ee25a31bb5bf034f33256fe8ea2aa68360405161069d91815260200190565b60405180910390a2505050565b60006106b64683610e89565b92915050565b600054610100900460ff16158080156106dc5750600054600160ff909116105b806106f65750303b1580156106f6575060005460ff166001145b6107685760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a6564000000000000000000000000000000000000606482015260840161052a565b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016600117905580156107c657600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff166101001790555b73ffffffffffffffffffffffffffffffffffffffff8616158015906107ea57508415155b80156107f65750468514155b8015610803575060008351115b8015610810575060008251115b61085c5760405162461bcd60e51b815260206004820152600960248201527f42453a706172616d730000000000000000000000000000000000000000000000604482015260640161052a565b61086587610f7a565b610870828486610f93565b60fb80547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff881617905560fc859055801561091857600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b50505050505050565b610929611020565b6109336000611087565b565b6040518060400160405280600b81526020017f746f6b656e5f7661756c74000000000000000000000000000000000000000000815250610974816106aa565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16146109ee5760405162461bcd60e51b815260206004820152600960248201527f41523a64656e6965640000000000000000000000000000000000000000000000604482015260640161052a565b6109f883836110fe565b8273ffffffffffffffffffffffffffffffffffffffff167f9b5b9a05e4726d8bb959f1440e05c6b8109443f2083bc4e386237d76545265538360405161069d91815260200190565b606060cd805461042b90611e64565b33600081815260ca6020908152604080832073ffffffffffffffffffffffffffffffffffffffff8716845290915281205490919083811015610af95760405162461bcd60e51b815260206004820152602560248201527f45524332303a2064656372656173656420616c6c6f77616e63652062656c6f7760448201527f207a65726f000000000000000000000000000000000000000000000000000000606482015260840161052a565b610b068286868403610c33565b506001949350505050565b600073ffffffffffffffffffffffffffffffffffffffff8316301415610b795760405162461bcd60e51b815260206004820152600560248201527f42453a746f000000000000000000000000000000000000000000000000000000604482015260640161052a565b610b83838361126f565b9392505050565b6000610b838383610e89565b610b9e611020565b73ffffffffffffffffffffffffffffffffffffffff8116610c275760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201527f6464726573730000000000000000000000000000000000000000000000000000606482015260840161052a565b610c3081611087565b50565b73ffffffffffffffffffffffffffffffffffffffff8316610cbb5760405162461bcd60e51b8152602060048201526024808201527f45524332303a20617070726f76652066726f6d20746865207a65726f2061646460448201527f7265737300000000000000000000000000000000000000000000000000000000606482015260840161052a565b73ffffffffffffffffffffffffffffffffffffffff8216610d445760405162461bcd60e51b815260206004820152602260248201527f45524332303a20617070726f766520746f20746865207a65726f20616464726560448201527f7373000000000000000000000000000000000000000000000000000000000000606482015260840161052a565b73ffffffffffffffffffffffffffffffffffffffff838116600081815260ca602090815260408083209487168084529482529182902085905590518481527f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925910160405180910390a3505050565b600033610dc085828561127d565b610b0685858561133a565b73ffffffffffffffffffffffffffffffffffffffff8216610e2e5760405162461bcd60e51b815260206004820152601f60248201527f45524332303a206d696e7420746f20746865207a65726f206164647265737300604482015260640161052a565b8060cb6000828254610e409190611ee7565b909155505073ffffffffffffffffffffffffffffffffffffffff8216600090815260c9602052604081208054839290610e7a908490611ee7565b90915550610e859050565b5050565b600080610e958461159f565b83604051602001610ea7929190611eff565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152908290526097547fbf40fac100000000000000000000000000000000000000000000000000000000835290925073ffffffffffffffffffffffffffffffffffffffff169063bf40fac190610f2a908490600401611b2e565b60206040518083038186803b158015610f4257600080fd5b505afa158015610f56573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061053e9190611f57565b610f826116d1565b610f8a611756565b610c30816117db565b600054610100900460ff166110105760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e67000000000000000000000000000000000000000000606482015260840161052a565b61101b838383611885565b505050565b60655473ffffffffffffffffffffffffffffffffffffffff1633146109335760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015260640161052a565b6065805473ffffffffffffffffffffffffffffffffffffffff8381167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b73ffffffffffffffffffffffffffffffffffffffff82166111875760405162461bcd60e51b815260206004820152602160248201527f45524332303a206275726e2066726f6d20746865207a65726f2061646472657360448201527f7300000000000000000000000000000000000000000000000000000000000000606482015260840161052a565b73ffffffffffffffffffffffffffffffffffffffff8216600090815260c96020526040902054818110156112235760405162461bcd60e51b815260206004820152602260248201527f45524332303a206275726e20616d6f756e7420657863656564732062616c616e60448201527f6365000000000000000000000000000000000000000000000000000000000000606482015260840161052a565b73ffffffffffffffffffffffffffffffffffffffff8316600090815260c960205260408120838303905560cb805484929061125f908490611f74565b9091555061101b90508360008483565b6000336104bc81858561133a565b73ffffffffffffffffffffffffffffffffffffffff838116600090815260ca60209081526040808320938616835292905220547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff811461133457818110156113275760405162461bcd60e51b815260206004820152601d60248201527f45524332303a20696e73756666696369656e7420616c6c6f77616e6365000000604482015260640161052a565b6113348484848403610c33565b50505050565b73ffffffffffffffffffffffffffffffffffffffff83166113c35760405162461bcd60e51b815260206004820152602560248201527f45524332303a207472616e736665722066726f6d20746865207a65726f20616460448201527f6472657373000000000000000000000000000000000000000000000000000000606482015260840161052a565b73ffffffffffffffffffffffffffffffffffffffff821661144c5760405162461bcd60e51b815260206004820152602360248201527f45524332303a207472616e7366657220746f20746865207a65726f206164647260448201527f6573730000000000000000000000000000000000000000000000000000000000606482015260840161052a565b73ffffffffffffffffffffffffffffffffffffffff8316600090815260c96020526040902054818110156114e85760405162461bcd60e51b815260206004820152602660248201527f45524332303a207472616e7366657220616d6f756e742065786365656473206260448201527f616c616e63650000000000000000000000000000000000000000000000000000606482015260840161052a565b73ffffffffffffffffffffffffffffffffffffffff808516600090815260c9602052604080822085850390559185168152908120805484929061152c908490611ee7565b925050819055508273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef8460405161159291815260200190565b60405180910390a3611334565b6060816115df57505060408051808201909152600181527f3000000000000000000000000000000000000000000000000000000000000000602082015290565b8160005b811561160957806115f381611f8b565b91506116029050600a83611ff3565b91506115e3565b60008167ffffffffffffffff81111561162457611624611c0e565b6040519080825280601f01601f19166020018201604052801561164e576020820181803683370190505b5090505b841561053e57611663600183611f74565b9150611670600a86612007565b61167b906030611ee7565b60f81b8183815181106116905761169061201b565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a9053506116ca600a86611ff3565b9450611652565b600054610100900460ff1661174e5760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e67000000000000000000000000000000000000000000606482015260840161052a565b610933611960565b600054610100900460ff166117d35760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e67000000000000000000000000000000000000000000606482015260840161052a565b6109336119e3565b73ffffffffffffffffffffffffffffffffffffffff811661183e5760405162461bcd60e51b815260206004820152600e60248201527f41523a7a65726f41646472657373000000000000000000000000000000000000604482015260640161052a565b609780547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff92909216919091179055565b600054610100900460ff166119025760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e67000000000000000000000000000000000000000000606482015260840161052a565b82516119159060cc906020860190611a69565b5081516119299060cd906020850190611a69565b5060ce80547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660ff929092169190911790555050565b600054610100900460ff166119dd5760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e67000000000000000000000000000000000000000000606482015260840161052a565b60018055565b600054610100900460ff16611a605760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e67000000000000000000000000000000000000000000606482015260840161052a565b61093333611087565b828054611a7590611e64565b90600052602060002090601f016020900481019282611a975760008555611add565b82601f10611ab057805160ff1916838001178555611add565b82800160010185558215611add579182015b82811115611add578251825591602001919060010190611ac2565b50611ae9929150611aed565b5090565b5b80821115611ae95760008155600101611aee565b60005b83811015611b1d578181015183820152602001611b05565b838111156113345750506000910152565b6020815260008251806020840152611b4d816040850160208701611b02565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169190910160400192915050565b73ffffffffffffffffffffffffffffffffffffffff81168114610c3057600080fd5b60008060408385031215611bb457600080fd5b8235611bbf81611b7f565b946020939093013593505050565b600080600060608486031215611be257600080fd5b8335611bed81611b7f565b92506020840135611bfd81611b7f565b929592945050506040919091013590565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b600082601f830112611c4e57600080fd5b813567ffffffffffffffff80821115611c6957611c69611c0e565b604051601f83017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f01168101908282118183101715611caf57611caf611c0e565b81604052838152866020858801011115611cc857600080fd5b836020870160208301376000602085830101528094505050505092915050565b600060208284031215611cfa57600080fd5b813567ffffffffffffffff811115611d1157600080fd5b61053e84828501611c3d565b60008060008060008060c08789031215611d3657600080fd5b8635611d4181611b7f565b95506020870135611d5181611b7f565b945060408701359350606087013560ff81168114611d6e57600080fd5b9250608087013567ffffffffffffffff80821115611d8b57600080fd5b611d978a838b01611c3d565b935060a0890135915080821115611dad57600080fd5b50611dba89828a01611c3d565b9150509295509295509295565b600060208284031215611dd957600080fd5b8135610b8381611b7f565b60008060408385031215611df757600080fd5b8235611e0281611b7f565b91506020830135611e1281611b7f565b809150509250929050565b60008060408385031215611e3057600080fd5b82359150602083013567ffffffffffffffff811115611e4e57600080fd5b611e5a85828601611c3d565b9150509250929050565b600181811c90821680611e7857607f821691505b60208210811415611eb2577f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b50919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60008219821115611efa57611efa611eb8565b500190565b60008351611f11818460208801611b02565b7f2e000000000000000000000000000000000000000000000000000000000000009083019081528351611f4b816001840160208801611b02565b01600101949350505050565b600060208284031215611f6957600080fd5b8151610b8381611b7f565b600082821015611f8657611f86611eb8565b500390565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff821415611fbd57611fbd611eb8565b5060010190565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b60008261200257612002611fc4565b500490565b60008261201657612016611fc4565b500690565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fdfea2646970667358221220f24dcb708d1867134df56fe5efc5ccc3a875e0deca527b2af220b5bde7e6b93664736f6c63430008090033a2646970667358221220abf8c5a35e42ce1f54480f59a3b073492445c3fe339322ddb4639465be6e49ee64736f6c63430008090033", + "balance": "0x0" + }, + "0x0000777700000000000000000000000000000003": { + "contractName": "EtherVault", + "storage": { + "0x0000000000000000000000000000000000000000000000000000000000000000": "0x0000000000000000000000000000000000000000000000000000000000000001", + "0x0000000000000000000000000000000000000000000000000000000000000001": "0x0000000000000000000000000000000000000000000000000000000000000001", + "0x0000000000000000000000000000000000000000000000000000000000000065": "0x00000000000000000000000026250179c8e8e12104e556c4cd03bcf4dabd51b9", + "0x0000000000000000000000000000000000000000000000000000000000000097": "0x0000000000000000000000000000777700000000000000000000000000000006", + "0x029ae2e2f1d6964720a0fa7e6ffa902f995c156242f4f5a930aa9d9765d167d0": "0x0000000000000000000000000000000000000000000000000000000000000001" + }, + "code": "0x6080604052600436106100b55760003560e01c8063715018a611610069578063f16c79341161004e578063f16c79341461023f578063f2fde38b1461025f578063fe9fbb801461027f57600080fd5b8063715018a6146101ff5780638da5cb5b1461021457600080fd5b80632d1fb3891161009a5780632d1fb3891461016e5780633ab76e9f1461018e578063461a4478146101df57600080fd5b806319ab453c1461012e5780631efa4ec01461014e57600080fd5b36610129574715806100d6575033600090815260c9602052604090205460ff165b6101275760405162461bcd60e51b815260206004820152600960248201527f45563a64656e696564000000000000000000000000000000000000000000000060448201526064015b60405180910390fd5b005b600080fd5b34801561013a57600080fd5b50610127610149366004610dd8565b6102d5565b34801561015a57600080fd5b50610127610169366004610df5565b61044f565b34801561017a57600080fd5b50610127610189366004610e0e565b610517565b34801561019a57600080fd5b5060975473ffffffffffffffffffffffffffffffffffffffff165b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020015b60405180910390f35b3480156101eb57600080fd5b506101b56101fa366004610f26565b610646565b34801561020b57600080fd5b50610127610658565b34801561022057600080fd5b5060655473ffffffffffffffffffffffffffffffffffffffff166101b5565b34801561024b57600080fd5b506101b561025a366004610f5b565b61066c565b34801561026b57600080fd5b5061012761027a366004610dd8565b61067f565b34801561028b57600080fd5b506102c561029a366004610dd8565b73ffffffffffffffffffffffffffffffffffffffff16600090815260c9602052604090205460ff1690565b60405190151581526020016101d6565b600054610100900460ff16158080156102f55750600054600160ff909116105b8061030f5750303b15801561030f575060005460ff166001145b6103815760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a6564000000000000000000000000000000000000606482015260840161011e565b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016600117905580156103df57600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff166101001790555b6103e88261071c565b801561044b57600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b5050565b33600090815260c9602052604090205460ff166104ae5760405162461bcd60e51b815260206004820152600960248201527f45563a64656e6965640000000000000000000000000000000000000000000000604482015260640161011e565b600260015414156105015760405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c00604482015260640161011e565b60026001556105103382610735565b5060018055565b61051f6107f0565b73ffffffffffffffffffffffffffffffffffffffff821615801590610570575073ffffffffffffffffffffffffffffffffffffffff8216600090815260c9602052604090205460ff16151581151514155b6105bc5760405162461bcd60e51b815260206004820152600860248201527f45563a706172616d000000000000000000000000000000000000000000000000604482015260640161011e565b73ffffffffffffffffffffffffffffffffffffffff8216600081815260c9602090815260409182902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001685151590811790915591519182527f4c0079b9bcd37cd5d29a13938effd97c881798cbc6bd52a3026a29d94b27d1bf910160405180910390a25050565b60006106524683610857565b92915050565b6106606107f0565b61066a6000610950565b565b60006106788383610857565b9392505050565b6106876107f0565b73ffffffffffffffffffffffffffffffffffffffff81166107105760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201527f6464726573730000000000000000000000000000000000000000000000000000606482015260840161011e565b61071981610950565b50565b6107246109c7565b61072c610a4c565b61071981610ad1565b801561044b5760008273ffffffffffffffffffffffffffffffffffffffff168260405160006040518083038185875af1925050503d8060008114610795576040519150601f19603f3d011682016040523d82523d6000602084013e61079a565b606091505b50509050806107eb5760405162461bcd60e51b815260206004820152601360248201527f455448207472616e73666572206661696c656400000000000000000000000000604482015260640161011e565b505050565b60655473ffffffffffffffffffffffffffffffffffffffff16331461066a5760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015260640161011e565b60008061086384610b7b565b83604051602001610875929190610fd2565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152908290526097547fbf40fac100000000000000000000000000000000000000000000000000000000835290925073ffffffffffffffffffffffffffffffffffffffff169063bf40fac1906108f890849060040161102a565b60206040518083038186803b15801561091057600080fd5b505afa158015610924573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610948919061107b565b949350505050565b6065805473ffffffffffffffffffffffffffffffffffffffff8381167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b600054610100900460ff16610a445760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e67000000000000000000000000000000000000000000606482015260840161011e565b61066a610cad565b600054610100900460ff16610ac95760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e67000000000000000000000000000000000000000000606482015260840161011e565b61066a610d30565b73ffffffffffffffffffffffffffffffffffffffff8116610b345760405162461bcd60e51b815260206004820152600e60248201527f41523a7a65726f41646472657373000000000000000000000000000000000000604482015260640161011e565b609780547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff92909216919091179055565b606081610bbb57505060408051808201909152600181527f3000000000000000000000000000000000000000000000000000000000000000602082015290565b8160005b8115610be55780610bcf816110c7565b9150610bde9050600a8361112f565b9150610bbf565b60008167ffffffffffffffff811115610c0057610c00610e4c565b6040519080825280601f01601f191660200182016040528015610c2a576020820181803683370190505b5090505b841561094857610c3f600183611143565b9150610c4c600a8661115a565b610c5790603061116e565b60f81b818381518110610c6c57610c6c611186565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a905350610ca6600a8661112f565b9450610c2e565b600054610100900460ff16610d2a5760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e67000000000000000000000000000000000000000000606482015260840161011e565b60018055565b600054610100900460ff16610dad5760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e67000000000000000000000000000000000000000000606482015260840161011e565b61066a33610950565b73ffffffffffffffffffffffffffffffffffffffff8116811461071957600080fd5b600060208284031215610dea57600080fd5b813561067881610db6565b600060208284031215610e0757600080fd5b5035919050565b60008060408385031215610e2157600080fd5b8235610e2c81610db6565b915060208301358015158114610e4157600080fd5b809150509250929050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b600082601f830112610e8c57600080fd5b813567ffffffffffffffff80821115610ea757610ea7610e4c565b604051601f83017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f01168101908282118183101715610eed57610eed610e4c565b81604052838152866020858801011115610f0657600080fd5b836020870160208301376000602085830101528094505050505092915050565b600060208284031215610f3857600080fd5b813567ffffffffffffffff811115610f4f57600080fd5b61094884828501610e7b565b60008060408385031215610f6e57600080fd5b82359150602083013567ffffffffffffffff811115610f8c57600080fd5b610f9885828601610e7b565b9150509250929050565b60005b83811015610fbd578181015183820152602001610fa5565b83811115610fcc576000848401525b50505050565b60008351610fe4818460208801610fa2565b7f2e00000000000000000000000000000000000000000000000000000000000000908301908152835161101e816001840160208801610fa2565b01600101949350505050565b6020815260008251806020840152611049816040850160208701610fa2565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169190910160400192915050565b60006020828403121561108d57600080fd5b815161067881610db6565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8214156110f9576110f9611098565b5060010190565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b60008261113e5761113e611100565b500490565b60008282101561115557611155611098565b500390565b60008261116957611169611100565b500690565b6000821982111561118157611181611098565b500190565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fdfea2646970667358221220a9a80c6d09a8fe0110adcdabd6682b37ae15ded4282fed28d917343fa3f34e2564736f6c63430008090033", + "balance": "0xffffffffffffffc87d2531626fffffff" + } +}
diff --git ethereum/go-ethereum/core/types/gen_account_rlp.go taikoxyz/taiko-geth/core/types/gen_account_rlp.go index 5181d884112ffcbbd1273ee4ba0dd2e9d6d663e6..3fb36f4038758c3eff54452ceefe89481a40d90c 100644 --- ethereum/go-ethereum/core/types/gen_account_rlp.go +++ taikoxyz/taiko-geth/core/types/gen_account_rlp.go @@ -1,8 +1,5 @@ // Code generated by rlpgen. DO NOT EDIT.   -//go:build !norlpgen -// +build !norlpgen - package types   import "github.com/ethereum/go-ethereum/rlp"
diff --git ethereum/go-ethereum/core/types/gen_header_json.go taikoxyz/taiko-geth/core/types/gen_header_json.go index bac475959dd9f6da98105215f5e9ab84cbf6b8d9..fb1f915d01d945ad5ce42ee77b77cf0aa6b2b0e7 100644 --- ethereum/go-ethereum/core/types/gen_header_json.go +++ taikoxyz/taiko-geth/core/types/gen_header_json.go @@ -16,26 +16,27 @@ // MarshalJSON marshals as JSON. func (h Header) MarshalJSON() ([]byte, error) { type Header struct { - ParentHash common.Hash `json:"parentHash" gencodec:"required"` - UncleHash common.Hash `json:"sha3Uncles" gencodec:"required"` - Coinbase common.Address `json:"miner"` - Root common.Hash `json:"stateRoot" gencodec:"required"` - TxHash common.Hash `json:"transactionsRoot" gencodec:"required"` - ReceiptHash common.Hash `json:"receiptsRoot" gencodec:"required"` - Bloom Bloom `json:"logsBloom" gencodec:"required"` - Difficulty *hexutil.Big `json:"difficulty" gencodec:"required"` - Number *hexutil.Big `json:"number" gencodec:"required"` - GasLimit hexutil.Uint64 `json:"gasLimit" gencodec:"required"` - GasUsed hexutil.Uint64 `json:"gasUsed" gencodec:"required"` - Time hexutil.Uint64 `json:"timestamp" gencodec:"required"` - Extra hexutil.Bytes `json:"extraData" gencodec:"required"` - MixDigest common.Hash `json:"mixHash"` - Nonce BlockNonce `json:"nonce"` - BaseFee *hexutil.Big `json:"baseFeePerGas" rlp:"optional"` - WithdrawalsHash *common.Hash `json:"withdrawalsRoot" rlp:"optional"` - BlobGasUsed *hexutil.Uint64 `json:"blobGasUsed" rlp:"optional"` - ExcessBlobGas *hexutil.Uint64 `json:"excessBlobGas" rlp:"optional"` - Hash common.Hash `json:"hash"` + ParentHash common.Hash `json:"parentHash" gencodec:"required"` + UncleHash common.Hash `json:"sha3Uncles" gencodec:"required"` + Coinbase common.Address `json:"miner"` + Root common.Hash `json:"stateRoot" gencodec:"required"` + TxHash common.Hash `json:"transactionsRoot" gencodec:"required"` + ReceiptHash common.Hash `json:"receiptsRoot" gencodec:"required"` + Bloom Bloom `json:"logsBloom" gencodec:"required"` + Difficulty *hexutil.Big `json:"difficulty" gencodec:"required"` + Number *hexutil.Big `json:"number" gencodec:"required"` + GasLimit hexutil.Uint64 `json:"gasLimit" gencodec:"required"` + GasUsed hexutil.Uint64 `json:"gasUsed" gencodec:"required"` + Time hexutil.Uint64 `json:"timestamp" gencodec:"required"` + Extra hexutil.Bytes `json:"extraData" gencodec:"required"` + MixDigest common.Hash `json:"mixHash"` + Nonce BlockNonce `json:"nonce"` + BaseFee *hexutil.Big `json:"baseFeePerGas" rlp:"optional"` + WithdrawalsHash *common.Hash `json:"withdrawalsRoot" rlp:"optional"` + BlobGasUsed *hexutil.Uint64 `json:"blobGasUsed" rlp:"optional"` + ExcessBlobGas *hexutil.Uint64 `json:"excessBlobGas" rlp:"optional"` + ParentBeaconRoot *common.Hash `json:"parentBeaconBlockRoot" rlp:"optional"` + Hash common.Hash `json:"hash"` } var enc Header enc.ParentHash = h.ParentHash @@ -57,6 +58,7 @@ enc.BaseFee = (*hexutil.Big)(h.BaseFee) enc.WithdrawalsHash = h.WithdrawalsHash enc.BlobGasUsed = (*hexutil.Uint64)(h.BlobGasUsed) enc.ExcessBlobGas = (*hexutil.Uint64)(h.ExcessBlobGas) + enc.ParentBeaconRoot = h.ParentBeaconRoot enc.Hash = h.Hash() return json.Marshal(&enc) } @@ -64,25 +66,26 @@ // UnmarshalJSON unmarshals from JSON. func (h *Header) UnmarshalJSON(input []byte) error { type Header struct { - ParentHash *common.Hash `json:"parentHash" gencodec:"required"` - UncleHash *common.Hash `json:"sha3Uncles" gencodec:"required"` - Coinbase *common.Address `json:"miner"` - Root *common.Hash `json:"stateRoot" gencodec:"required"` - TxHash *common.Hash `json:"transactionsRoot" gencodec:"required"` - ReceiptHash *common.Hash `json:"receiptsRoot" gencodec:"required"` - Bloom *Bloom `json:"logsBloom" gencodec:"required"` - Difficulty *hexutil.Big `json:"difficulty" gencodec:"required"` - Number *hexutil.Big `json:"number" gencodec:"required"` - GasLimit *hexutil.Uint64 `json:"gasLimit" gencodec:"required"` - GasUsed *hexutil.Uint64 `json:"gasUsed" gencodec:"required"` - Time *hexutil.Uint64 `json:"timestamp" gencodec:"required"` - Extra *hexutil.Bytes `json:"extraData" gencodec:"required"` - MixDigest *common.Hash `json:"mixHash"` - Nonce *BlockNonce `json:"nonce"` - BaseFee *hexutil.Big `json:"baseFeePerGas" rlp:"optional"` - WithdrawalsHash *common.Hash `json:"withdrawalsRoot" rlp:"optional"` - BlobGasUsed *hexutil.Uint64 `json:"blobGasUsed" rlp:"optional"` - ExcessBlobGas *hexutil.Uint64 `json:"excessBlobGas" rlp:"optional"` + ParentHash *common.Hash `json:"parentHash" gencodec:"required"` + UncleHash *common.Hash `json:"sha3Uncles" gencodec:"required"` + Coinbase *common.Address `json:"miner"` + Root *common.Hash `json:"stateRoot" gencodec:"required"` + TxHash *common.Hash `json:"transactionsRoot" gencodec:"required"` + ReceiptHash *common.Hash `json:"receiptsRoot" gencodec:"required"` + Bloom *Bloom `json:"logsBloom" gencodec:"required"` + Difficulty *hexutil.Big `json:"difficulty" gencodec:"required"` + Number *hexutil.Big `json:"number" gencodec:"required"` + GasLimit *hexutil.Uint64 `json:"gasLimit" gencodec:"required"` + GasUsed *hexutil.Uint64 `json:"gasUsed" gencodec:"required"` + Time *hexutil.Uint64 `json:"timestamp" gencodec:"required"` + Extra *hexutil.Bytes `json:"extraData" gencodec:"required"` + MixDigest *common.Hash `json:"mixHash"` + Nonce *BlockNonce `json:"nonce"` + BaseFee *hexutil.Big `json:"baseFeePerGas" rlp:"optional"` + WithdrawalsHash *common.Hash `json:"withdrawalsRoot" rlp:"optional"` + BlobGasUsed *hexutil.Uint64 `json:"blobGasUsed" rlp:"optional"` + ExcessBlobGas *hexutil.Uint64 `json:"excessBlobGas" rlp:"optional"` + ParentBeaconRoot *common.Hash `json:"parentBeaconBlockRoot" rlp:"optional"` } var dec Header if err := json.Unmarshal(input, &dec); err != nil { @@ -156,6 +159,9 @@ h.BlobGasUsed = (*uint64)(dec.BlobGasUsed) } if dec.ExcessBlobGas != nil { h.ExcessBlobGas = (*uint64)(dec.ExcessBlobGas) + } + if dec.ParentBeaconRoot != nil { + h.ParentBeaconRoot = dec.ParentBeaconRoot } return nil }
diff --git ethereum/go-ethereum/core/types/gen_header_rlp.go taikoxyz/taiko-geth/core/types/gen_header_rlp.go index a5ed5cd15094af1bdff472617382d88e47828a1e..ed6a1a002cdbaab59d8261746fd512fb90888c44 100644 --- ethereum/go-ethereum/core/types/gen_header_rlp.go +++ taikoxyz/taiko-geth/core/types/gen_header_rlp.go @@ -1,8 +1,5 @@ // Code generated by rlpgen. DO NOT EDIT.   -//go:build !norlpgen -// +build !norlpgen - package types   import "github.com/ethereum/go-ethereum/rlp" @@ -44,7 +41,8 @@ _tmp1 := obj.BaseFee != nil _tmp2 := obj.WithdrawalsHash != nil _tmp3 := obj.BlobGasUsed != nil _tmp4 := obj.ExcessBlobGas != nil - if _tmp1 || _tmp2 || _tmp3 || _tmp4 { + _tmp5 := obj.ParentBeaconRoot != nil + if _tmp1 || _tmp2 || _tmp3 || _tmp4 || _tmp5 { if obj.BaseFee == nil { w.Write(rlp.EmptyString) } else { @@ -54,25 +52,32 @@ } w.WriteBigInt(obj.BaseFee) } } - if _tmp2 || _tmp3 || _tmp4 { + if _tmp2 || _tmp3 || _tmp4 || _tmp5 { if obj.WithdrawalsHash == nil { w.Write([]byte{0x80}) } else { w.WriteBytes(obj.WithdrawalsHash[:]) } } - if _tmp3 || _tmp4 { + if _tmp3 || _tmp4 || _tmp5 { if obj.BlobGasUsed == nil { w.Write([]byte{0x80}) } else { w.WriteUint64((*obj.BlobGasUsed)) } } - if _tmp4 { + if _tmp4 || _tmp5 { if obj.ExcessBlobGas == nil { w.Write([]byte{0x80}) } else { w.WriteUint64((*obj.ExcessBlobGas)) + } + } + if _tmp5 { + if obj.ParentBeaconRoot == nil { + w.Write([]byte{0x80}) + } else { + w.WriteBytes(obj.ParentBeaconRoot[:]) } } w.ListEnd(_tmp0)
diff --git ethereum/go-ethereum/core/types/gen_log_json.go taikoxyz/taiko-geth/core/types/gen_log_json.go index 90e1c14d9017d4bd50b2f847576b0b238df6cb42..3ffa9c2feb1a6ce3790c46dd1fd72d500fe56ca6 100644 --- ethereum/go-ethereum/core/types/gen_log_json.go +++ taikoxyz/taiko-geth/core/types/gen_log_json.go @@ -18,12 +18,12 @@ type Log struct { Address common.Address `json:"address" gencodec:"required"` Topics []common.Hash `json:"topics" gencodec:"required"` Data hexutil.Bytes `json:"data" gencodec:"required"` - BlockNumber hexutil.Uint64 `json:"blockNumber"` - TxHash common.Hash `json:"transactionHash" gencodec:"required"` - TxIndex hexutil.Uint `json:"transactionIndex"` - BlockHash common.Hash `json:"blockHash"` - Index hexutil.Uint `json:"logIndex"` - Removed bool `json:"removed"` + BlockNumber hexutil.Uint64 `json:"blockNumber" rlp:"-"` + TxHash common.Hash `json:"transactionHash" gencodec:"required" rlp:"-"` + TxIndex hexutil.Uint `json:"transactionIndex" rlp:"-"` + BlockHash common.Hash `json:"blockHash" rlp:"-"` + Index hexutil.Uint `json:"logIndex" rlp:"-"` + Removed bool `json:"removed" rlp:"-"` } var enc Log enc.Address = l.Address @@ -44,12 +44,12 @@ type Log struct { Address *common.Address `json:"address" gencodec:"required"` Topics []common.Hash `json:"topics" gencodec:"required"` Data *hexutil.Bytes `json:"data" gencodec:"required"` - BlockNumber *hexutil.Uint64 `json:"blockNumber"` - TxHash *common.Hash `json:"transactionHash" gencodec:"required"` - TxIndex *hexutil.Uint `json:"transactionIndex"` - BlockHash *common.Hash `json:"blockHash"` - Index *hexutil.Uint `json:"logIndex"` - Removed *bool `json:"removed"` + BlockNumber *hexutil.Uint64 `json:"blockNumber" rlp:"-"` + TxHash *common.Hash `json:"transactionHash" gencodec:"required" rlp:"-"` + TxIndex *hexutil.Uint `json:"transactionIndex" rlp:"-"` + BlockHash *common.Hash `json:"blockHash" rlp:"-"` + Index *hexutil.Uint `json:"logIndex" rlp:"-"` + Removed *bool `json:"removed" rlp:"-"` } var dec Log if err := json.Unmarshal(input, &dec); err != nil {
diff --git ethereum/go-ethereum/core/types/gen_log_rlp.go taikoxyz/taiko-geth/core/types/gen_log_rlp.go index 4a6c6b0094f8b5af898591d7c5ae0f05f8c91113..7e8962966842fe0dcc62c32caba35932fe5c82eb 100644 --- ethereum/go-ethereum/core/types/gen_log_rlp.go +++ taikoxyz/taiko-geth/core/types/gen_log_rlp.go @@ -1,14 +1,11 @@ // Code generated by rlpgen. DO NOT EDIT.   -//go:build !norlpgen -// +build !norlpgen - package types   import "github.com/ethereum/go-ethereum/rlp" import "io"   -func (obj *rlpLog) EncodeRLP(_w io.Writer) error { +func (obj *Log) EncodeRLP(_w io.Writer) error { w := rlp.NewEncoderBuffer(_w) _tmp0 := w.List() w.WriteBytes(obj.Address[:])
diff --git ethereum/go-ethereum/core/types/gen_withdrawal_rlp.go taikoxyz/taiko-geth/core/types/gen_withdrawal_rlp.go index d0b4e0147a0db71149d9e432268456921d770fad..6a97c04c8153222badb403a8eaaa092a21343c55 100644 --- ethereum/go-ethereum/core/types/gen_withdrawal_rlp.go +++ taikoxyz/taiko-geth/core/types/gen_withdrawal_rlp.go @@ -1,8 +1,5 @@ // Code generated by rlpgen. DO NOT EDIT.   -//go:build !norlpgen -// +build !norlpgen - package types   import "github.com/ethereum/go-ethereum/rlp"
diff --git ethereum/go-ethereum/eth/ethconfig/gen_config.go taikoxyz/taiko-geth/eth/ethconfig/gen_config.go index 324fbe380ea3889b995f7f15d1aca7e3fd26766b..2abddc9e0d3878344f5ac547a0ac369db0d4a985 100644 --- ethereum/go-ethereum/eth/ethconfig/gen_config.go +++ taikoxyz/taiko-geth/eth/ethconfig/gen_config.go @@ -25,6 +25,9 @@ SnapDiscoveryURLs []string NoPruning bool NoPrefetch bool TxLookupLimit uint64 `toml:",omitempty"` + TransactionHistory uint64 `toml:",omitempty"` + StateHistory uint64 `toml:",omitempty"` + StateScheme string `toml:",omitempty"` RequiredBlocks map[uint64]common.Hash `toml:"-"` LightServ int `toml:",omitempty"` LightIngress int `toml:",omitempty"` @@ -63,6 +66,9 @@ enc.SnapDiscoveryURLs = c.SnapDiscoveryURLs enc.NoPruning = c.NoPruning enc.NoPrefetch = c.NoPrefetch enc.TxLookupLimit = c.TxLookupLimit + enc.TransactionHistory = c.TransactionHistory + enc.StateHistory = c.StateHistory + enc.StateScheme = c.StateScheme enc.RequiredBlocks = c.RequiredBlocks enc.LightServ = c.LightServ enc.LightIngress = c.LightIngress @@ -105,6 +111,9 @@ SnapDiscoveryURLs []string NoPruning *bool NoPrefetch *bool TxLookupLimit *uint64 `toml:",omitempty"` + TransactionHistory *uint64 `toml:",omitempty"` + StateHistory *uint64 `toml:",omitempty"` + StateScheme *string `toml:",omitempty"` RequiredBlocks map[uint64]common.Hash `toml:"-"` LightServ *int `toml:",omitempty"` LightIngress *int `toml:",omitempty"` @@ -161,6 +170,15 @@ c.NoPrefetch = *dec.NoPrefetch } if dec.TxLookupLimit != nil { c.TxLookupLimit = *dec.TxLookupLimit + } + if dec.TransactionHistory != nil { + c.TransactionHistory = *dec.TransactionHistory + } + if dec.StateHistory != nil { + c.StateHistory = *dec.StateHistory + } + if dec.StateScheme != nil { + c.StateScheme = *dec.StateScheme } if dec.RequiredBlocks != nil { c.RequiredBlocks = dec.RequiredBlocks
diff --git ethereum/go-ethereum/go.mod taikoxyz/taiko-geth/go.mod index d62f4ebfd5b008f841a373a57a5b926867e7b3b4..9eed6e5c7862b29495b388ae72ed27f355824a42 100644 --- ethereum/go-ethereum/go.mod +++ taikoxyz/taiko-geth/go.mod @@ -1,26 +1,28 @@ module github.com/ethereum/go-ethereum   -go 1.19 +go 1.20   require ( - github.com/Azure/azure-sdk-for-go/sdk/storage/azblob v0.3.0 - github.com/VictoriaMetrics/fastcache v1.6.0 - github.com/aws/aws-sdk-go-v2 v1.2.0 - github.com/aws/aws-sdk-go-v2/config v1.1.1 - github.com/aws/aws-sdk-go-v2/credentials v1.1.1 - github.com/aws/aws-sdk-go-v2/service/route53 v1.1.1 + github.com/Azure/azure-sdk-for-go/sdk/storage/azblob v1.2.0 + github.com/Microsoft/go-winio v0.6.1 + github.com/VictoriaMetrics/fastcache v1.12.1 + github.com/aws/aws-sdk-go-v2 v1.21.2 + github.com/aws/aws-sdk-go-v2/config v1.18.45 + github.com/aws/aws-sdk-go-v2/credentials v1.13.43 + github.com/aws/aws-sdk-go-v2/service/route53 v1.30.2 github.com/btcsuite/btcd/btcec/v2 v2.2.0 github.com/cespare/cp v0.1.0 - github.com/cloudflare/cloudflare-go v0.14.0 - github.com/cockroachdb/pebble v0.0.0-20230209160836-829675f94811 - github.com/consensys/gnark-crypto v0.10.0 + github.com/cloudflare/cloudflare-go v0.79.0 + github.com/cockroachdb/errors v1.8.1 + github.com/cockroachdb/pebble v0.0.0-20230928194634-aa077af62593 + github.com/consensys/gnark-crypto v0.12.1 github.com/crate-crypto/go-kzg-4844 v0.3.0 github.com/davecgh/go-spew v1.1.1 github.com/deckarep/golang-set/v2 v2.1.0 - github.com/docker/docker v1.6.2 - github.com/dop251/goja v0.0.0-20230605162241-28ee0ee714f3 + github.com/docker/docker v24.0.5+incompatible + github.com/dop251/goja v0.0.0-20230806174421-c933cf95e127 github.com/ethereum/c-kzg-4844 v0.3.1 - github.com/fatih/color v1.7.0 + github.com/fatih/color v1.13.0 github.com/fjl/gencodec v0.0.0-20230517082657-f9840df7b83e github.com/fjl/memsize v0.0.0-20190710130421-bcb5799ab5e5 github.com/fsnotify/fsnotify v1.6.0 @@ -28,8 +30,8 @@ github.com/gballet/go-libpcsclite v0.0.0-20190607065134-2772fd86a8ff github.com/gballet/go-verkle v0.0.0-20230607174250-df487255f46b github.com/go-stack/stack v1.8.1 github.com/gofrs/flock v0.8.1 - github.com/golang-jwt/jwt/v4 v4.3.0 - github.com/golang/protobuf v1.5.2 + github.com/golang-jwt/jwt/v4 v4.5.0 + github.com/golang/protobuf v1.5.3 github.com/golang/snappy v0.0.5-0.20220116011046-fa5810519dcb github.com/google/gofuzz v1.1.1-0.20200604201612-c04b05f3adfa github.com/google/uuid v1.3.0 @@ -39,16 +41,16 @@ github.com/hashicorp/go-bexpr v0.1.10 github.com/holiman/billy v0.0.0-20230718173358-1c7e68d277a7 github.com/holiman/bloomfilter/v2 v2.0.3 github.com/holiman/uint256 v1.2.3 - github.com/huin/goupnp v1.0.3 + github.com/huin/goupnp v1.3.0 github.com/influxdata/influxdb-client-go/v2 v2.4.0 github.com/influxdata/influxdb1-client v0.0.0-20220302092344-a9ab5670611c github.com/jackpal/go-nat-pmp v1.0.2 - github.com/jedisct1/go-minisign v0.0.0-20190909160543-45766022959e + github.com/jedisct1/go-minisign v0.0.0-20230811132847-661be99b8267 github.com/julienschmidt/httprouter v1.3.0 - github.com/karalabe/usb v0.0.3-0.20230711191512-61db3e06439c + github.com/karalabe/usb v0.0.2 github.com/kylelemons/godebug v1.1.0 github.com/mattn/go-colorable v0.1.13 - github.com/mattn/go-isatty v0.0.16 + github.com/mattn/go-isatty v0.0.17 github.com/naoina/toml v0.1.2-0.20170918210437-9fafd6967416 github.com/olekukonko/tablewriter v0.0.5 github.com/peterh/liner v1.1.1-0.20190123174540-a2c9a5303de7 @@ -56,59 +58,68 @@ github.com/protolambda/bls12-381-util v0.0.0-20220416220906-d8552aa452c7 github.com/rs/cors v1.7.0 github.com/shirou/gopsutil v3.21.4-0.20210419000835-c7a38de76ee5+incompatible github.com/status-im/keycard-go v0.2.0 - github.com/stretchr/testify v1.8.1 + github.com/stretchr/testify v1.8.4 github.com/supranational/blst v0.3.11 github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7 github.com/tyler-smith/go-bip39 v1.1.0 - github.com/urfave/cli/v2 v2.24.1 + github.com/urfave/cli/v2 v2.25.7 go.uber.org/automaxprocs v1.5.2 - golang.org/x/crypto v0.9.0 - golang.org/x/exp v0.0.0-20230810033253-352e893a4cad + golang.org/x/crypto v0.14.0 + golang.org/x/exp v0.0.0-20230905200255-921286631fa9 golang.org/x/sync v0.3.0 - golang.org/x/sys v0.9.0 - golang.org/x/text v0.9.0 + golang.org/x/sys v0.13.0 + golang.org/x/text v0.13.0 golang.org/x/time v0.3.0 - golang.org/x/tools v0.9.1 + golang.org/x/tools v0.13.0 gopkg.in/natefinch/lumberjack.v2 v2.0.0 - gopkg.in/natefinch/npipe.v2 v2.0.0-20160621034901-c1b8fa8bdcce gopkg.in/yaml.v3 v3.0.1 )   require ( - github.com/Azure/azure-sdk-for-go/sdk/azcore v0.21.1 // indirect - github.com/Azure/azure-sdk-for-go/sdk/internal v0.8.3 // indirect - github.com/DataDog/zstd v1.5.2 // indirect - github.com/StackExchange/wmi v0.0.0-20180116203802-5d049714c4a6 // indirect - github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.0.2 // indirect - github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.0.2 // indirect - github.com/aws/aws-sdk-go-v2/service/sso v1.1.1 // indirect - github.com/aws/aws-sdk-go-v2/service/sts v1.1.1 // indirect - github.com/aws/smithy-go v1.1.0 // indirect + github.com/Azure/azure-sdk-for-go/sdk/azcore v1.7.0 // indirect + github.com/Azure/azure-sdk-for-go/sdk/internal v1.3.0 // indirect + github.com/DataDog/zstd v1.4.5 // indirect + github.com/StackExchange/wmi v1.2.1 // indirect + github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.13.13 // indirect + github.com/aws/aws-sdk-go-v2/internal/configsources v1.1.43 // indirect + github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.4.37 // indirect + github.com/aws/aws-sdk-go-v2/internal/ini v1.3.45 // indirect + github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.9.37 // indirect + github.com/aws/aws-sdk-go-v2/service/sso v1.15.2 // indirect + github.com/aws/aws-sdk-go-v2/service/ssooidc v1.17.3 // indirect + github.com/aws/aws-sdk-go-v2/service/sts v1.23.2 // indirect + github.com/aws/smithy-go v1.15.0 // indirect github.com/beorn7/perks v1.0.1 // indirect github.com/bits-and-blooms/bitset v1.7.0 // indirect github.com/cespare/xxhash/v2 v2.2.0 // indirect - github.com/cockroachdb/errors v1.9.1 // indirect - github.com/cockroachdb/logtags v0.0.0-20230118201751-21c54148d20b // indirect - github.com/cockroachdb/redact v1.1.3 // indirect + github.com/cockroachdb/logtags v0.0.0-20190617123548-eb05cc24525f // indirect + github.com/cockroachdb/redact v1.0.8 // indirect + github.com/cockroachdb/sentry-go v0.6.1-cockroachdb.2 // indirect + github.com/cockroachdb/tokenbucket v0.0.0-20230807174530-cc333fc44b06 // indirect github.com/consensys/bavard v0.1.13 // indirect github.com/cpuguy83/go-md2man/v2 v2.0.2 // indirect github.com/crate-crypto/go-ipa v0.0.0-20230601170251-1830d0757c80 // indirect github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.1 // indirect - github.com/deepmap/oapi-codegen v1.8.2 // indirect + github.com/deepmap/oapi-codegen v1.6.0 // indirect github.com/dlclark/regexp2 v1.7.0 // indirect github.com/garslo/gogen v0.0.0-20170306192744-1d203ffc1f61 // indirect - github.com/getsentry/sentry-go v0.18.0 // indirect - github.com/go-ole/go-ole v1.2.1 // indirect + github.com/go-ole/go-ole v1.2.5 // indirect github.com/go-sourcemap/sourcemap v2.1.3+incompatible // indirect + github.com/goccy/go-json v0.10.2 // indirect github.com/gogo/protobuf v1.3.2 // indirect + github.com/google/go-cmp v0.5.9 // indirect + github.com/google/go-querystring v1.1.0 // indirect github.com/google/pprof v0.0.0-20230207041349-798e818bf904 // indirect - github.com/influxdata/line-protocol v0.0.0-20210311194329-9aa0e372d097 // indirect + github.com/hashicorp/go-cleanhttp v0.5.2 // indirect + github.com/hashicorp/go-retryablehttp v0.7.4 // indirect + github.com/influxdata/line-protocol v0.0.0-20200327222509-2487e7298839 // indirect + github.com/jmespath/go-jmespath v0.4.0 // indirect github.com/kilic/bls12-381 v0.1.0 // indirect github.com/klauspost/compress v1.15.15 // indirect github.com/kr/pretty v0.3.1 // indirect github.com/kr/text v0.2.0 // indirect - github.com/mattn/go-runewidth v0.0.9 // indirect - github.com/matttproud/golang_protobuf_extensions v1.0.4 // indirect + github.com/mattn/go-runewidth v0.0.13 // indirect + github.com/matttproud/golang_protobuf_extensions v1.0.2-0.20181231171920-c182affec369 // indirect github.com/mitchellh/mapstructure v1.4.1 // indirect github.com/mitchellh/pointerstructure v1.2.0 // indirect github.com/mmcloughlin/addchain v0.4.0 // indirect @@ -116,19 +127,20 @@ github.com/naoina/go-stringutil v0.1.0 // indirect github.com/opentracing/opentracing-go v1.1.0 // indirect github.com/pkg/errors v0.9.1 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect - github.com/prometheus/client_golang v1.14.0 // indirect - github.com/prometheus/client_model v0.3.0 // indirect - github.com/prometheus/common v0.39.0 // indirect - github.com/prometheus/procfs v0.9.0 // indirect + github.com/prometheus/client_golang v1.12.0 // indirect + github.com/prometheus/client_model v0.2.1-0.20210607210712-147c58e9608a // indirect + github.com/prometheus/common v0.32.1 // indirect + github.com/prometheus/procfs v0.7.3 // indirect + github.com/rivo/uniseg v0.2.0 // indirect github.com/rogpeppe/go-internal v1.9.0 // indirect github.com/russross/blackfriday/v2 v2.1.0 // indirect - github.com/tklauser/go-sysconf v0.3.5 // indirect - github.com/tklauser/numcpus v0.2.2 // indirect + github.com/tklauser/go-sysconf v0.3.12 // indirect + github.com/tklauser/numcpus v0.6.1 // indirect github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673 // indirect - golang.org/x/mod v0.11.0 // indirect - golang.org/x/net v0.10.0 // indirect - golang.org/x/xerrors v0.0.0-20220517211312-f3a8303e98df // indirect - google.golang.org/protobuf v1.28.1 // indirect + golang.org/x/mod v0.12.0 // indirect + golang.org/x/net v0.17.0 // indirect + google.golang.org/protobuf v1.27.1 // indirect gopkg.in/yaml.v2 v2.4.0 // indirect + gotest.tools/v3 v3.5.1 // indirect rsc.io/tmplfunc v0.0.3 // indirect )
diff --git ethereum/go-ethereum/go.sum taikoxyz/taiko-geth/go.sum index 8f91afee82bf9ce1464b819c1d6afb426fdd48c2..44b705336ae087f18c95838412618e4b473b48de 100644 --- ethereum/go-ethereum/go.sum +++ taikoxyz/taiko-geth/go.sum @@ -1,46 +1,100 @@ cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= +cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= +cloud.google.com/go v0.38.0/go.mod h1:990N+gfupTy94rShfmMCWGDn0LpTmnzTp2qbd1dvSRU= +cloud.google.com/go v0.44.1/go.mod h1:iSa0KzasP4Uvy3f1mN/7PiObzGgflwredwwASm/v6AU= +cloud.google.com/go v0.44.2/go.mod h1:60680Gw3Yr4ikxnPRS/oxxkBccT6SA1yMk63TGekxKY= +cloud.google.com/go v0.45.1/go.mod h1:RpBamKRgapWJb87xiFSdk4g1CME7QZg3uwTez+TSTjc= +cloud.google.com/go v0.46.3/go.mod h1:a6bKKbmY7er1mI7TEI4lsAkts/mkhTSZK8w33B4RAg0= +cloud.google.com/go v0.50.0/go.mod h1:r9sluTvynVuxRIOHXQEHMFffphuXHOMZMycpNR5e6To= +cloud.google.com/go v0.52.0/go.mod h1:pXajvRH/6o3+F9jDHZWQ5PbGhn+o8w9qiu/CffaVdO4= +cloud.google.com/go v0.53.0/go.mod h1:fp/UouUEsRkN6ryDKNW/Upv/JBKnv6WDthjR6+vze6M= +cloud.google.com/go v0.54.0/go.mod h1:1rq2OEkV3YMf6n/9ZvGWI3GWw0VoqH/1x2nd8Is/bPc= +cloud.google.com/go v0.56.0/go.mod h1:jr7tqZxxKOVYizybht9+26Z/gUq7tiRzu+ACVAMbKVk= +cloud.google.com/go v0.57.0/go.mod h1:oXiQ6Rzq3RAkkY7N6t3TcE6jE+CIBBbA36lwQ1JyzZs= +cloud.google.com/go v0.62.0/go.mod h1:jmCYTdRCQuc1PHIIJ/maLInMho30T/Y0M4hTdTShOYc= +cloud.google.com/go v0.65.0/go.mod h1:O5N8zS7uWy9vkA9vayVHs65eM1ubvY4h553ofrNHObY= +cloud.google.com/go/bigquery v1.0.1/go.mod h1:i/xbL2UlR5RvWAURpBYZTtm/cXjCha9lbfbpx4poX+o= +cloud.google.com/go/bigquery v1.3.0/go.mod h1:PjpwJnslEMmckchkHFfq+HTD2DmtT67aNFKH1/VBDHE= +cloud.google.com/go/bigquery v1.4.0/go.mod h1:S8dzgnTigyfTmLBfrtrhyYhwRxG72rYxvftPBK2Dvzc= +cloud.google.com/go/bigquery v1.5.0/go.mod h1:snEHRnqQbz117VIFhE8bmtwIDY80NLUZUMb4Nv6dBIg= +cloud.google.com/go/bigquery v1.7.0/go.mod h1://okPTzCYNXSlb24MZs83e2Do+h+VXtc4gLoIoXIAPc= +cloud.google.com/go/bigquery v1.8.0/go.mod h1:J5hqkt3O0uAFnINi6JXValWIb1v0goeZM77hZzJN/fQ= +cloud.google.com/go/datastore v1.0.0/go.mod h1:LXYbyblFSglQ5pkeyhO+Qmw7ukd3C+pD7TKLgZqpHYE= +cloud.google.com/go/datastore v1.1.0/go.mod h1:umbIZjpQpHh4hmRpGhH4tLFup+FVzqBi1b3c64qFpCk= +cloud.google.com/go/pubsub v1.0.1/go.mod h1:R0Gpsv3s54REJCy4fxDixWD93lHJMoZTyQ2kNxGRt3I= +cloud.google.com/go/pubsub v1.1.0/go.mod h1:EwwdRX2sKPjnvnqCa270oGRyludottCI76h+R3AArQw= +cloud.google.com/go/pubsub v1.2.0/go.mod h1:jhfEVHT8odbXTkndysNHCcx0awwzvfOlguIAii9o8iA= +cloud.google.com/go/pubsub v1.3.1/go.mod h1:i+ucay31+CNRpDW4Lu78I4xXG+O1r/MAHgjpRVR+TSU= +cloud.google.com/go/storage v1.0.0/go.mod h1:IhtSnM/ZTZV8YYJWCY8RULGVqBDmpoyjwiyrjsg+URw= +cloud.google.com/go/storage v1.5.0/go.mod h1:tpKbwo567HUNpVclU5sGELwQWBDZ8gh0ZeosJ0Rtdos= +cloud.google.com/go/storage v1.6.0/go.mod h1:N7U0C8pVQ/+NIKOBQyamJIeKQKkZ+mxpohlUTyfDhBk= +cloud.google.com/go/storage v1.8.0/go.mod h1:Wv1Oy7z6Yz3DshWRJFhqM/UCfaWIRTdp0RXyy7KQOVs= +cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9ullr3+Kg0= +dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= github.com/AndreasBriese/bbloom v0.0.0-20190306092124-e2d15f34fcf9/go.mod h1:bOvUY6CB00SOBii9/FifXqc0awNKxLFCL/+pkDPuyl8= -github.com/Azure/azure-sdk-for-go/sdk/azcore v0.21.1 h1:qoVeMsc9/fh/yhxVaA0obYjVH/oI/ihrOoMwsLS9KSA= -github.com/Azure/azure-sdk-for-go/sdk/azcore v0.21.1/go.mod h1:fBF9PQNqB8scdgpZ3ufzaLntG0AG7C1WjPMsiFOmfHM= -github.com/Azure/azure-sdk-for-go/sdk/internal v0.8.3 h1:E+m3SkZCN0Bf5q7YdTs5lSm2CYY3CK4spn5OmUIiQtk= -github.com/Azure/azure-sdk-for-go/sdk/internal v0.8.3/go.mod h1:KLF4gFr6DcKFZwSuH8w8yEK6DpFl3LP5rhdvAb7Yz5I= -github.com/Azure/azure-sdk-for-go/sdk/storage/azblob v0.3.0 h1:Px2UA+2RvSSvv+RvJNuUB6n7rs5Wsel4dXLe90Um2n4= -github.com/Azure/azure-sdk-for-go/sdk/storage/azblob v0.3.0/go.mod h1:tPaiy8S5bQ+S5sOiDlINkp7+Ef339+Nz5L5XO+cnOHo= +github.com/Azure/azure-sdk-for-go/sdk/azcore v1.7.0 h1:8q4SaHjFsClSvuVne0ID/5Ka8u3fcIHyqkLjcFpNRHQ= +github.com/Azure/azure-sdk-for-go/sdk/azcore v1.7.0/go.mod h1:bjGvMhVMb+EEm3VRNQawDMUyMMjo+S5ewNjflkep/0Q= +github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.3.0 h1:vcYCAze6p19qBW7MhZybIsqD8sMV8js0NyQM8JDnVtg= +github.com/Azure/azure-sdk-for-go/sdk/internal v1.3.0 h1:sXr+ck84g/ZlZUOZiNELInmMgOsuGwdjjVkEIde0OtY= +github.com/Azure/azure-sdk-for-go/sdk/internal v1.3.0/go.mod h1:okt5dMMTOFjX/aovMlrjvvXoPMBVSPzk9185BT0+eZM= +github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/storage/armstorage v1.2.0 h1:Ma67P/GGprNwsslzEH6+Kb8nybI8jpDTm4Wmzu2ReK8= +github.com/Azure/azure-sdk-for-go/sdk/storage/azblob v1.2.0 h1:gggzg0SUMs6SQbEw+3LoSsYf9YMjkupeAnHMX8O9mmY= +github.com/Azure/azure-sdk-for-go/sdk/storage/azblob v1.2.0/go.mod h1:+6KLcKIVgxoBDMqMO/Nvy7bZ9a0nbU3I1DtFQK3YvB4= +github.com/AzureAD/microsoft-authentication-library-for-go v1.0.0 h1:OBhqkivkhkMqLPymWEppkm7vgPQY2XsHoEkaMQ0AdZY= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= -github.com/BurntSushi/toml v1.2.1 h1:9F2/+DoOYIOksmaJFPw1tGFy1eDnIJXg+UHjuD8lTak= -github.com/CloudyKit/fastprinter v0.0.0-20200109182630-33d98a066a53/go.mod h1:+3IMCy2vIlbG1XG/0ggNQv0SvxCAIpPM5b1nCz56Xno= -github.com/CloudyKit/jet/v3 v3.0.0/go.mod h1:HKQPgSJmdK8hdoAbKUUWajkHyHo4RaU5rMdUywE7VMo= -github.com/DataDog/zstd v1.5.2 h1:vUG4lAyuPCXO0TLbXvPv7EB7cNK1QV/luu55UHLrrn8= -github.com/DataDog/zstd v1.5.2/go.mod h1:g4AWEaM3yOg3HYfnJ3YIawPnVdXJh9QME85blwSAmyw= +github.com/BurntSushi/toml v1.3.2 h1:o7IhLm0Msx3BaB+n3Ag7L8EVlByGnpq14C4YWiu/gL8= +github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= +github.com/CloudyKit/fastprinter v0.0.0-20170127035650-74b38d55f37a/go.mod h1:EFZQ978U7x8IRnstaskI3IysnWY5Ao3QgZUKOXlsAdw= +github.com/CloudyKit/jet v2.1.3-0.20180809161101-62edd43e4f88+incompatible/go.mod h1:HPYO+50pSWkPoj9Q/eq0aRGByCL6ScRlUmiEX5Zgm+w= +github.com/DataDog/zstd v1.4.5 h1:EndNeuB0l9syBZhut0wns3gV1hL8zX8LIu6ZiVHWLIQ= +github.com/DataDog/zstd v1.4.5/go.mod h1:1jcaCB/ufaK+sKp1NBhlGmpz41jOoPQ35bpF36t7BBo= github.com/Joker/hpp v1.0.0/go.mod h1:8x5n+M1Hp5hC0g8okX3sR3vFQwynaX/UgSOM9MeBKzY= +github.com/Joker/jade v1.0.1-0.20190614124447-d475f43051e7/go.mod h1:6E6s8o2AE4KhCrqr6GRJjdC/gNfTdxkIXvuGZZda2VM= +github.com/Microsoft/go-winio v0.6.1 h1:9/kr64B9VUZrLm5YYwbGtUJnMgqWVOdUAXu6Migciow= +github.com/Microsoft/go-winio v0.6.1/go.mod h1:LRdKpFKfdobln8UmuiYcKPot9D2v6svN5+sAH+4kjUM= github.com/Shopify/goreferrer v0.0.0-20181106222321-ec9c9a553398/go.mod h1:a1uqRtAwp2Xwc6WNPJEufxJ7fx3npB4UV/JOLmbu5I0= -github.com/StackExchange/wmi v0.0.0-20180116203802-5d049714c4a6 h1:fLjPD/aNc3UIOA6tDi6QXUemppXK3P9BI7mr2hd6gx8= -github.com/StackExchange/wmi v0.0.0-20180116203802-5d049714c4a6/go.mod h1:3eOhrUMpNV+6aFIbp5/iudMxNCF27Vw2OZgy4xEx0Fg= -github.com/VictoriaMetrics/fastcache v1.6.0 h1:C/3Oi3EiBCqufydp1neRZkqcwmEiuRT9c3fqvvgKm5o= -github.com/VictoriaMetrics/fastcache v1.6.0/go.mod h1:0qHz5QP0GMX4pfmMA/zt5RgfNuXJrTP0zS7DqpHGGTw= +github.com/StackExchange/wmi v1.2.1 h1:VIkavFPXSjcnS+O8yTq7NI32k0R5Aj+v39y29VYDOSA= +github.com/StackExchange/wmi v1.2.1/go.mod h1:rcmrprowKIVzvc+NUiLncP2uuArMWLCbu9SBzvHz7e8= +github.com/VictoriaMetrics/fastcache v1.12.1 h1:i0mICQuojGDL3KblA7wUNlY5lOK6a4bwt3uRKnkZU40= +github.com/VictoriaMetrics/fastcache v1.12.1/go.mod h1:tX04vaqcNoQeGLD+ra5pU5sWkuxnzWhEzLwhP9w653o= github.com/ajg/form v1.5.1/go.mod h1:uL1WgH+h2mgNtvBq0339dVnzXdBETtL2LeUXaIv25UY= +github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= +github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= +github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= +github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= +github.com/alecthomas/units v0.0.0-20190924025748-f65c72e2690d/go.mod h1:rBZYJk541a8SKzHPHnH3zbiI+7dagKZ0cgpgrD7Fyho= github.com/allegro/bigcache v1.2.1-0.20190218064605-e24eb225f156 h1:eMwmnE/GDgah4HI848JfFxHt+iPb26b4zyfspmqY0/8= github.com/allegro/bigcache v1.2.1-0.20190218064605-e24eb225f156/go.mod h1:Cb/ax3seSYIx7SuZdm2G2xzfwmv3TPSk2ucNfQESPXM= github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8= -github.com/aws/aws-sdk-go-v2 v1.2.0 h1:BS+UYpbsElC82gB+2E2jiCBg36i8HlubTB/dO/moQ9c= -github.com/aws/aws-sdk-go-v2 v1.2.0/go.mod h1:zEQs02YRBw1DjK0PoJv3ygDYOFTre1ejlJWl8FwAuQo= -github.com/aws/aws-sdk-go-v2/config v1.1.1 h1:ZAoq32boMzcaTW9bcUacBswAmHTbvlvDJICgHFZuECo= -github.com/aws/aws-sdk-go-v2/config v1.1.1/go.mod h1:0XsVy9lBI/BCXm+2Tuvt39YmdHwS5unDQmxZOYe8F5Y= -github.com/aws/aws-sdk-go-v2/credentials v1.1.1 h1:NbvWIM1Mx6sNPTxowHgS2ewXCRp+NGTzUYb/96FZJbY= -github.com/aws/aws-sdk-go-v2/credentials v1.1.1/go.mod h1:mM2iIjwl7LULWtS6JCACyInboHirisUUdkBPoTHMOUo= -github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.0.2 h1:EtEU7WRaWliitZh2nmuxEXrN0Cb8EgPUFGIoTMeqbzI= -github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.0.2/go.mod h1:3hGg3PpiEjHnrkrlasTfxFqUsZ2GCk/fMUn4CbKgSkM= -github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.0.2 h1:4AH9fFjUlVktQMznF+YN33aWNXaR4VgDXyP28qokJC0= -github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.0.2/go.mod h1:45MfaXZ0cNbeuT0KQ1XJylq8A6+OpVV2E5kvY/Kq+u8= -github.com/aws/aws-sdk-go-v2/service/route53 v1.1.1 h1:cKr6St+CtC3/dl/rEBJvlk7A/IN5D5F02GNkGzfbtVU= -github.com/aws/aws-sdk-go-v2/service/route53 v1.1.1/go.mod h1:rLiOUrPLW/Er5kRcQ7NkwbjlijluLsrIbu/iyl35RO4= -github.com/aws/aws-sdk-go-v2/service/sso v1.1.1 h1:37QubsarExl5ZuCBlnRP+7l1tNwZPBSTqpTBrPH98RU= -github.com/aws/aws-sdk-go-v2/service/sso v1.1.1/go.mod h1:SuZJxklHxLAXgLTc1iFXbEWkXs7QRTQpCLGaKIprQW0= -github.com/aws/aws-sdk-go-v2/service/sts v1.1.1 h1:TJoIfnIFubCX0ACVeJ0w46HEH5MwjwYN4iFhuYIhfIY= -github.com/aws/aws-sdk-go-v2/service/sts v1.1.1/go.mod h1:Wi0EBZwiz/K44YliU0EKxqTCJGUfYTWXrrBwkq736bM= -github.com/aws/smithy-go v1.1.0 h1:D6CSsM3gdxaGaqXnPgOBCeL6Mophqzu7KJOu7zW78sU= -github.com/aws/smithy-go v1.1.0/go.mod h1:EzMw8dbp/YJL4A5/sbhGddag+NPT7q084agLbB9LgIw= +github.com/aws/aws-sdk-go-v2 v1.21.2 h1:+LXZ0sgo8quN9UOKXXzAWRT3FWd4NxeXWOZom9pE7GA= +github.com/aws/aws-sdk-go-v2 v1.21.2/go.mod h1:ErQhvNuEMhJjweavOYhxVkn2RUx7kQXVATHrjKtxIpM= +github.com/aws/aws-sdk-go-v2/config v1.18.45 h1:Aka9bI7n8ysuwPeFdm77nfbyHCAKQ3z9ghB3S/38zes= +github.com/aws/aws-sdk-go-v2/config v1.18.45/go.mod h1:ZwDUgFnQgsazQTnWfeLWk5GjeqTQTL8lMkoE1UXzxdE= +github.com/aws/aws-sdk-go-v2/credentials v1.13.43 h1:LU8vo40zBlo3R7bAvBVy/ku4nxGEyZe9N8MqAeFTzF8= +github.com/aws/aws-sdk-go-v2/credentials v1.13.43/go.mod h1:zWJBz1Yf1ZtX5NGax9ZdNjhhI4rgjfgsyk6vTY1yfVg= +github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.13.13 h1:PIktER+hwIG286DqXyvVENjgLTAwGgoeriLDD5C+YlQ= +github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.13.13/go.mod h1:f/Ib/qYjhV2/qdsf79H3QP/eRE4AkVyEf6sk7XfZ1tg= +github.com/aws/aws-sdk-go-v2/internal/configsources v1.1.43 h1:nFBQlGtkbPzp/NjZLuFxRqmT91rLJkgvsEQs68h962Y= +github.com/aws/aws-sdk-go-v2/internal/configsources v1.1.43/go.mod h1:auo+PiyLl0n1l8A0e8RIeR8tOzYPfZZH/JNlrJ8igTQ= +github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.4.37 h1:JRVhO25+r3ar2mKGP7E0LDl8K9/G36gjlqca5iQbaqc= +github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.4.37/go.mod h1:Qe+2KtKml+FEsQF/DHmDV+xjtche/hwoF75EG4UlHW8= +github.com/aws/aws-sdk-go-v2/internal/ini v1.3.45 h1:hze8YsjSh8Wl1rYa1CJpRmXP21BvOBuc76YhW0HsuQ4= +github.com/aws/aws-sdk-go-v2/internal/ini v1.3.45/go.mod h1:lD5M20o09/LCuQ2mE62Mb/iSdSlCNuj6H5ci7tW7OsE= +github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.9.37 h1:WWZA/I2K4ptBS1kg0kV1JbBtG/umed0vwHRrmcr9z7k= +github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.9.37/go.mod h1:vBmDnwWXWxNPFRMmG2m/3MKOe+xEcMDo1tanpaWCcck= +github.com/aws/aws-sdk-go-v2/service/route53 v1.30.2 h1:/RPQNjh1sDIezpXaFIkZb7MlXnSyAqjVdAwcJuGYTqg= +github.com/aws/aws-sdk-go-v2/service/route53 v1.30.2/go.mod h1:TQZBt/WaQy+zTHoW++rnl8JBrmZ0VO6EUbVua1+foCA= +github.com/aws/aws-sdk-go-v2/service/sso v1.15.2 h1:JuPGc7IkOP4AaqcZSIcyqLpFSqBWK32rM9+a1g6u73k= +github.com/aws/aws-sdk-go-v2/service/sso v1.15.2/go.mod h1:gsL4keucRCgW+xA85ALBpRFfdSLH4kHOVSnLMSuBECo= +github.com/aws/aws-sdk-go-v2/service/ssooidc v1.17.3 h1:HFiiRkf1SdaAmV3/BHOFZ9DjFynPHj8G/UIO1lQS+fk= +github.com/aws/aws-sdk-go-v2/service/ssooidc v1.17.3/go.mod h1:a7bHA82fyUXOm+ZSWKU6PIoBxrjSprdLoM8xPYvzYVg= +github.com/aws/aws-sdk-go-v2/service/sts v1.23.2 h1:0BkLfgeDjfZnZ+MhB3ONb01u9pwFYTCZVhlsSSBvlbU= +github.com/aws/aws-sdk-go-v2/service/sts v1.23.2/go.mod h1:Eows6e1uQEsc4ZaHANmsPRzAKcVDrcmjjWiih2+HUUQ= +github.com/aws/smithy-go v1.15.0 h1:PS/durmlzvAFpQHDs4wi4sNNP9ExsqZh6IlfdHXgKK8= +github.com/aws/smithy-go v1.15.0/go.mod h1:Tg+OJXh4MB2R/uN61Ko2f6hTZwB/ZYGOtib8J3gBHzA= github.com/aymerick/raymond v2.0.3-0.20180322193309-b565731e1464+incompatible/go.mod h1:osfaiScAUVup+UC9Nfq76eWqDhXlp+4UYaA8uhTBO6g= +github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= +github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8= github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= github.com/bits-and-blooms/bitset v1.7.0 h1:YjAGVd3XmtK9ktAbX8Zg2g2PwLIMjGREZJHlV4j7NEo= @@ -52,36 +106,43 @@ github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= github.com/cespare/cp v0.1.0 h1:SE+dxFebS7Iik5LK0tsi1k9ZCxEaFX4AjQmoyA+1dJk= github.com/cespare/cp v0.1.0/go.mod h1:SOGHArjBr4JWaSDEVpWpo/hNg6RoKrls6Oh40hiwW+s= github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= +github.com/cespare/xxhash/v2 v2.1.2/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/cespare/xxhash/v2 v2.2.0 h1:DC2CZ1Ep5Y4k3ZQ899DldepgrayRUGE6BBZ/cd9Cj44= github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= +github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= github.com/chzyer/logex v1.2.0/go.mod h1:9+9sk7u7pGNWYMkh0hdiL++6OeibzJccyQU4p4MedaY= +github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI= github.com/chzyer/readline v1.5.0/go.mod h1:x22KAscuvRqlLoK9CsoYsmxoXZMMFVyOl86cAH8qUic= +github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= github.com/chzyer/test v0.0.0-20210722231415-061457976a23/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= -github.com/cloudflare/cloudflare-go v0.14.0 h1:gFqGlGl/5f9UGXAaKapCGUfaTCgRKKnzu2VvzMZlOFA= -github.com/cloudflare/cloudflare-go v0.14.0/go.mod h1:EnwdgGMaFOruiPZRFSgn+TsQ3hQ7C/YWzIGLeu5c304= -github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= -github.com/cockroachdb/datadriven v1.0.2 h1:H9MtNqVoVhvd9nCBwOyDjUEdZCREqbIdCJD93PBm/jA= -github.com/cockroachdb/datadriven v1.0.2/go.mod h1:a9RdTaap04u637JoCzcUoIcDmvwSUtcUFtT/C3kJlTU= -github.com/cockroachdb/errors v1.9.1 h1:yFVvsI0VxmRShfawbt/laCIDy/mtTqqnvoNgiy5bEV8= -github.com/cockroachdb/errors v1.9.1/go.mod h1:2sxOtL2WIc096WSZqZ5h8fa17rdDq9HZOZLBCor4mBk= -github.com/cockroachdb/logtags v0.0.0-20211118104740-dabe8e521a4f/go.mod h1:Vz9DsVWQQhf3vs21MhPMZpMGSht7O/2vFW2xusFUVOs= -github.com/cockroachdb/logtags v0.0.0-20230118201751-21c54148d20b h1:r6VH0faHjZeQy818SGhaone5OnYfxFR/+AzdY3sf5aE= -github.com/cockroachdb/logtags v0.0.0-20230118201751-21c54148d20b/go.mod h1:Vz9DsVWQQhf3vs21MhPMZpMGSht7O/2vFW2xusFUVOs= -github.com/cockroachdb/pebble v0.0.0-20230209160836-829675f94811 h1:ytcWPaNPhNoGMWEhDvS3zToKcDpRsLuRolQJBVGdozk= -github.com/cockroachdb/pebble v0.0.0-20230209160836-829675f94811/go.mod h1:Nb5lgvnQ2+oGlE/EyZy4+2/CxRh9KfvCXnag1vtpxVM= -github.com/cockroachdb/redact v1.1.3 h1:AKZds10rFSIj7qADf0g46UixK8NNLwWTNdCIGS5wfSQ= -github.com/cockroachdb/redact v1.1.3/go.mod h1:BVNblN9mBWFyMyqK1k3AAiSxhvhfK2oOZZ2lK+dpvRg= +github.com/cloudflare/cloudflare-go v0.79.0 h1:ErwCYDjFCYppDJlDJ/5WhsSmzegAUe2+K9qgFyQDg3M= +github.com/cloudflare/cloudflare-go v0.79.0/go.mod h1:gkHQf9xEubaQPEuerBuoinR9P8bf8a05Lq0X6WKy1Oc= +github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= +github.com/cockroachdb/datadriven v1.0.0/go.mod h1:5Ib8Meh+jk1RlHIXej6Pzevx/NLlNvQB9pmSBZErGA4= +github.com/cockroachdb/datadriven v1.0.3-0.20230413201302-be42291fc80f h1:otljaYPt5hWxV3MUfO5dFPFiOXg9CyG5/kCfayTqsJ4= +github.com/cockroachdb/errors v1.6.1/go.mod h1:tm6FTP5G81vwJ5lC0SizQo374JNCOPrHyXGitRJoDqM= +github.com/cockroachdb/errors v1.8.1 h1:A5+txlVZfOqFBDa4mGz2bUWSp0aHElvHX2bKkdbQu+Y= +github.com/cockroachdb/errors v1.8.1/go.mod h1:qGwQn6JmZ+oMjuLwjWzUNqblqk0xl4CVV3SQbGwK7Ac= +github.com/cockroachdb/logtags v0.0.0-20190617123548-eb05cc24525f h1:o/kfcElHqOiXqcou5a3rIlMc7oJbMQkeLk0VQJ7zgqY= +github.com/cockroachdb/logtags v0.0.0-20190617123548-eb05cc24525f/go.mod h1:i/u985jwjWRlyHXQbwatDASoW0RMlZ/3i9yJHE2xLkI= +github.com/cockroachdb/pebble v0.0.0-20230928194634-aa077af62593 h1:aPEJyR4rPBvDmeyi+l/FS/VtA00IWvjeFvjen1m1l1A= +github.com/cockroachdb/pebble v0.0.0-20230928194634-aa077af62593/go.mod h1:6hk1eMY/u5t+Cf18q5lFMUA1Rc+Sm5I6Ra1QuPyxXCo= +github.com/cockroachdb/redact v1.0.8 h1:8QG/764wK+vmEYoOlfobpe12EQcS81ukx/a4hdVMxNw= +github.com/cockroachdb/redact v1.0.8/go.mod h1:BVNblN9mBWFyMyqK1k3AAiSxhvhfK2oOZZ2lK+dpvRg= +github.com/cockroachdb/sentry-go v0.6.1-cockroachdb.2 h1:IKgmqgMQlVJIZj19CdocBeSfSaiCbEBZGKODaixqtHM= +github.com/cockroachdb/sentry-go v0.6.1-cockroachdb.2/go.mod h1:8BT+cPK6xvFOcRlk0R8eg+OTkcqI6baNH4xAkpiYVvQ= +github.com/cockroachdb/tokenbucket v0.0.0-20230807174530-cc333fc44b06 h1:zuQyyAKVxetITBuuhv3BI9cMrmStnpT18zmgmTxunpo= +github.com/cockroachdb/tokenbucket v0.0.0-20230807174530-cc333fc44b06/go.mod h1:7nc4anLGjupUW/PeY5qiNYsdNXj7zopG+eqsS7To5IQ= github.com/codegangsta/inject v0.0.0-20150114235600-33e0aa1cb7c0/go.mod h1:4Zcjuz89kmFXt9morQgcfYZAYZ5n8WHjt81YYWIwtTM= github.com/consensys/bavard v0.1.13 h1:oLhMLOFGTLdlda/kma4VOJazblc7IM5y5QPd2A/YjhQ= github.com/consensys/bavard v0.1.13/go.mod h1:9ItSMtA/dXMAiL7BG6bqW2m3NdSEObYWoH223nGHukI= -github.com/consensys/gnark-crypto v0.10.0 h1:zRh22SR7o4K35SoNqouS9J/TKHTyU2QWaj5ldehyXtA= -github.com/consensys/gnark-crypto v0.10.0/go.mod h1:Iq/P3HHl0ElSjsg2E1gsMwhAyxnxoKK5nVyZKd+/KhU= +github.com/consensys/gnark-crypto v0.12.1 h1:lHH39WuuFgVHONRl3J0LRBtuYdQTumFSDtJF7HpyG8M= +github.com/consensys/gnark-crypto v0.12.1/go.mod h1:v2Gy7L/4ZRosZ7Ivs+9SfUDr0f5UlG+EM5t7MPHiLuY= github.com/coreos/etcd v3.3.10+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE= github.com/coreos/go-etcd v2.0.0+incompatible/go.mod h1:Jez6KQU2B/sWsbdaef3ED8NzMklzPG4d5KIOhIy30Tk= github.com/coreos/go-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= github.com/cpuguy83/go-md2man v1.0.10/go.mod h1:SmD6nW6nTyfqj6ABTjUi3V3JVMnlJmwcJI5acqYI6dE= -github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= github.com/cpuguy83/go-md2man/v2 v2.0.2 h1:p1EgwI/C7NhT0JmVkwCD2ZBK8j4aeHQX2pMHHBfMQ6w= github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= github.com/crate-crypto/go-ipa v0.0.0-20230601170251-1830d0757c80 h1:DuBDHVjgGMPki7bAyh91+3cF1Vh34sAEdH8JQgbc2R0= @@ -99,42 +160,40 @@ github.com/decred/dcrd/crypto/blake256 v1.0.0 h1:/8DMNYp9SGi5f0w7uCm6d6M4OU2rGFK09Y2A4Xv7EE0= github.com/decred/dcrd/crypto/blake256 v1.0.0/go.mod h1:sQl2p6Y26YV+ZOcSTP6thNdn47hh8kt6rqSlvmrXFAc= github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.1 h1:YLtO71vCjJRCBcrPMtQ9nqBsqpA1m5sE92cU+pd5Mcc= github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.1/go.mod h1:hyedUtir6IdtD/7lIxGeCxkaw7y45JueMRL4DIyJDKs= +github.com/deepmap/oapi-codegen v1.6.0 h1:w/d1ntwh91XI0b/8ja7+u5SvA4IFfM0UNNLmiDR1gg0= github.com/deepmap/oapi-codegen v1.6.0/go.mod h1:ryDa9AgbELGeB+YEXE1dR53yAjHwFvE9iAUlWl9Al3M= -github.com/deepmap/oapi-codegen v1.8.2 h1:SegyeYGcdi0jLLrpbCMoJxnUUn8GBXHsvr4rbzjuhfU= -github.com/deepmap/oapi-codegen v1.8.2/go.mod h1:YLgSKSDv/bZQB7N4ws6luhozi3cEdRktEqrX88CvjIw= github.com/dgraph-io/badger v1.6.0/go.mod h1:zwt7syl517jmP8s94KqSxTlM6IMsdhYy6psNgSztDR4= github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ= github.com/dgryski/go-farm v0.0.0-20190423205320-6a90982ecee2/go.mod h1:SqUrOPUnsFjfmXRMNPybcSiG0BgUW2AuFH8PAnS2iTw= github.com/dlclark/regexp2 v1.4.1-0.20201116162257-a2a8dda75c91/go.mod h1:2pZnwuY/m+8K6iRw6wQdMtk+rH5tNGR1i55kozfMjCc= github.com/dlclark/regexp2 v1.7.0 h1:7lJfhqlPssTb1WQx4yvTHN0uElPEv52sbaECrAQxjAo= github.com/dlclark/regexp2 v1.7.0/go.mod h1:DHkYz0B9wPfa6wondMfaivmHpzrQ3v9q8cnmRbL6yW8= -github.com/dnaeon/go-vcr v1.1.0/go.mod h1:M7tiix8f0r6mKKJ3Yq/kqU1OYf3MnfmBWVbPx/yU9ko= github.com/dnaeon/go-vcr v1.2.0 h1:zHCHvJYTMh1N7xnV7zf1m1GPBF9Ad0Jk/whtQ1663qI= -github.com/dnaeon/go-vcr v1.2.0/go.mod h1:R4UdLID7HZT3taECzJs4YgbbH6PIGXB6W/sc5OLb6RQ= -github.com/docker/docker v1.6.2 h1:HlFGsy+9/xrgMmhmN+NGhCc5SHGJ7I+kHosRR1xc/aI= -github.com/docker/docker v1.6.2/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= +github.com/docker/docker v24.0.5+incompatible h1:WmgcE4fxyI6EEXxBRxsHnZXrO1pQ3smi0k/jho4HLeY= +github.com/docker/docker v24.0.5+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= github.com/dop251/goja v0.0.0-20211022113120-dc8c55024d06/go.mod h1:R9ET47fwRVRPZnOGvHxxhuZcbrMCuiqOz3Rlrh4KSnk= -github.com/dop251/goja v0.0.0-20230605162241-28ee0ee714f3 h1:+3HCtB74++ClLy8GgjUQYeC8R4ILzVcIe8+5edAJJnE= -github.com/dop251/goja v0.0.0-20230605162241-28ee0ee714f3/go.mod h1:QMWlm50DNe14hD7t24KEqZuUdC9sOTy8W6XbCU1mlw4= +github.com/dop251/goja v0.0.0-20230806174421-c933cf95e127 h1:qwcF+vdFrvPSEUDSX5RVoRccG8a5DhOdWdQ4zN62zzo= +github.com/dop251/goja v0.0.0-20230806174421-c933cf95e127/go.mod h1:QMWlm50DNe14hD7t24KEqZuUdC9sOTy8W6XbCU1mlw4= github.com/dop251/goja_nodejs v0.0.0-20210225215109-d91c329300e7/go.mod h1:hn7BA7c8pLvoGndExHudxTDKZ84Pyvv+90pbBjbTz0Y= github.com/dop251/goja_nodejs v0.0.0-20211022123610-8dd9abb0616d/go.mod h1:DngW8aVqWbuLRMHItjPUyqdj+HWPvnQe8V8y1nDpIbM= github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= github.com/eknkc/amber v0.0.0-20171010120322-cdade1c07385/go.mod h1:0vRUJqYpeSZifjYj7uP3BG/gKcuzL9xWVV/Y+cK33KM= github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= -github.com/envoyproxy/go-control-plane v0.9.9-0.20210217033140-668b12f5399d/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk= +github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98= github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= github.com/etcd-io/bbolt v1.3.3/go.mod h1:ZF2nL25h33cCyBtcyWeZ2/I3HQOfTP+0PIEvHjkjCrw= github.com/ethereum/c-kzg-4844 v0.3.1 h1:sR65+68+WdnMKxseNWxSJuAv2tsUrihTpVBTfM/U5Zg= github.com/ethereum/c-kzg-4844 v0.3.1/go.mod h1:VewdlzQmpT5QSrVhbBuGoCdFJkpaJlO1aQputP83wc0= github.com/fasthttp-contrib/websocket v0.0.0-20160511215533-1f3b11f56072/go.mod h1:duJ4Jxv5lDcvg4QuQr0oowTf7dz4/CR8NtyCooz9HL8= -github.com/fatih/color v1.7.0 h1:DkWD4oS2D8LGGgTQ6IvwJJXSL5Vp2ffcQg58nFV38Ys= -github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= +github.com/fatih/color v1.13.0 h1:8LOYc1KYPPmyKMuN8QV2DNRWNbLo6LZ0iLs8+mlH53w= +github.com/fatih/color v1.13.0/go.mod h1:kLAiJbzzSOZDVNGyDpeOxJ47H46qBXwg5ILebYFFOfk= github.com/fatih/structs v1.1.0/go.mod h1:9NiDSp5zOcgEDl+j00MP/WkGVPOlPRLejGD8Ga6PJ7M= github.com/fjl/gencodec v0.0.0-20230517082657-f9840df7b83e h1:bBLctRc7kr01YGvaDfgLbTwjFNW5jdp5y5rj8XXBHfY= github.com/fjl/gencodec v0.0.0-20230517082657-f9840df7b83e/go.mod h1:AzA8Lj6YtixmJWL+wkKoBGsLWy9gFrAzi4g+5bCKwpY= github.com/fjl/memsize v0.0.0-20190710130421-bcb5799ab5e5 h1:FtmdgXiUlNeRsoNMFlKLDt+S+6hbjVMEW6RGQ7aUf7c= github.com/fjl/memsize v0.0.0-20190710130421-bcb5799ab5e5/go.mod h1:VvhXpOYNQvB+uIk2RvXzuaQtkQJzzIx6lSBe1xv7hi0= +github.com/flosch/pongo2 v0.0.0-20190707114632-bbf5a6c351f4/go.mod h1:T9YF2M40nIgbVgp3rreNmTged+9HrbNTIQf1PsaIiTA= github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= github.com/fsnotify/fsnotify v1.6.0 h1:n+5WquG0fcWoWp6xPWfHdbskMCQaFnG6PfBrh1Ky4HY= @@ -147,45 +206,64 @@ github.com/gballet/go-libpcsclite v0.0.0-20190607065134-2772fd86a8ff/go.mod h1:x7DCsMOv1taUwEWCzT4cmDeAkigA5/QCwUodaVOe8Ww= github.com/gballet/go-verkle v0.0.0-20230607174250-df487255f46b h1:vMT47RYsrftsHSTQhqXwC3BYflo38OLC3Y4LtXtLyU0= github.com/gballet/go-verkle v0.0.0-20230607174250-df487255f46b/go.mod h1:CDncRYVRSDqwakm282WEkjfaAj1hxU/v5RXxk5nXOiI= github.com/getkin/kin-openapi v0.53.0/go.mod h1:7Yn5whZr5kJi6t+kShccXS8ae1APpYTW6yheSwk8Yi4= -github.com/getkin/kin-openapi v0.61.0/go.mod h1:7Yn5whZr5kJi6t+kShccXS8ae1APpYTW6yheSwk8Yi4= -github.com/getsentry/sentry-go v0.12.0/go.mod h1:NSap0JBYWzHND8oMbyi0+XZhUalc1TBdRL1M71JZW2c= -github.com/getsentry/sentry-go v0.18.0 h1:MtBW5H9QgdcJabtZcuJG80BMOwaBpkRDZkxRkNC1sN0= -github.com/getsentry/sentry-go v0.18.0/go.mod h1:Kgon4Mby+FJ7ZWHFUAZgVaIa8sxHtnRJRLTXZr51aKQ= github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= github.com/gin-contrib/sse v0.0.0-20190301062529-5545eab6dad3/go.mod h1:VJ0WA2NBN22VlZ2dKZQPAPnyWw5XTlK1KymzLKsr59s= github.com/gin-gonic/gin v1.4.0/go.mod h1:OW2EZn3DO8Ln9oIKOvM++LBO+5UPHJJDH72/q/3rZdM= github.com/go-check/check v0.0.0-20180628173108-788fd7840127/go.mod h1:9ES+weclKsC9YodN5RgxqK/VD9HM9JsCSh7rNhMZE98= github.com/go-chi/chi/v5 v5.0.0/go.mod h1:BBug9lr0cqtdAhsu6R4AAdvufI0/XBzAQSsUqJpoZOs= +github.com/go-errors/errors v1.0.1 h1:LUHzmkK3GUKUrL/1gfBUxAHzcev3apQlezX/+O7ma6w= github.com/go-errors/errors v1.0.1/go.mod h1:f4zRHt4oKfwPJE5k8C9vpYG+aDHdBFUsgrm6/TyX73Q= -github.com/go-errors/errors v1.4.2 h1:J6MZopCL4uSllY1OfXM374weqZFFItUbrImctkmUxIA= +github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU= +github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= +github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= +github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= +github.com/go-kit/kit v0.9.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= +github.com/go-kit/log v0.1.0/go.mod h1:zbhenjAZHb184qTLMA9ZjW7ThYL0H2mk7Q6pNt4vbaY= +github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE= +github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk= +github.com/go-logfmt/logfmt v0.5.0/go.mod h1:wCYkCAKZfumFQihp8CzCvQ3paCTfi41vtzG1KdI/P7A= github.com/go-martini/martini v0.0.0-20170121215854-22fa46961aab/go.mod h1:/P9AEU963A2AYjv4d1V5eVL1CQbEJq6aCNHDDjibzu8= -github.com/go-ole/go-ole v1.2.1 h1:2lOsA72HgjxAuMlKpFiCbHTvu44PIVkZ5hqm3RSdI/E= -github.com/go-ole/go-ole v1.2.1/go.mod h1:7FAglXiTm7HKlQRDeOQ6ZNUHidzCWXuZWq/1dTyBNF8= +github.com/go-ole/go-ole v1.2.5 h1:t4MGB5xEDZvXI+0rMjjsfBsD7yAgp/s9ZDkL1JndXwY= +github.com/go-ole/go-ole v1.2.5/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0= github.com/go-openapi/jsonpointer v0.19.5/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34VGT37dQOVbmoatg= github.com/go-openapi/swag v0.19.5/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh66Z9tfKk= github.com/go-sourcemap/sourcemap v2.1.3+incompatible h1:W1iEw64niKVGogNgBN3ePyLFfuisuzeidWPMPWmECqU= github.com/go-sourcemap/sourcemap v2.1.3+incompatible/go.mod h1:F8jJfvm2KbVjc5NqelyYJmf/v5J0dwNLS2mL4sNA1Jg= +github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= github.com/go-stack/stack v1.8.1 h1:ntEHSVwIt7PNXNpgPmVfMrNhLtgjlmnZha2kOpuRiDw= github.com/go-stack/stack v1.8.1/go.mod h1:dcoOX6HbPZSZptuspn9bctJ+N/CnF5gGygcUP3XYfe4= github.com/gobwas/httphead v0.0.0-20180130184737-2c6c146eadee/go.mod h1:L0fX3K22YWvt/FAX9NnzrNzcI4wNYi9Yku4O0LKYflo= github.com/gobwas/pool v0.2.0/go.mod h1:q8bcK0KcYlCgd9e7WYLm9LpyS+YeLd8JVDW6WezmKEw= github.com/gobwas/ws v1.0.2/go.mod h1:szmBTxLgaFppYjEmNtny/v3w89xOydFnnZMcgRRu/EM= +github.com/goccy/go-json v0.10.2 h1:CrxCmQqYDkv1z7lO7Wbh2HN93uovUHgrECaO5ZrCXAU= +github.com/goccy/go-json v0.10.2/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I= github.com/gofrs/flock v0.8.1 h1:+gYjHKf32LDeiEEFhQaotPbLuUXjY5ZqxKgXy7n59aw= github.com/gofrs/flock v0.8.1/go.mod h1:F1TvTiK9OcQqauNUHlbJvyl9Qa1QvF/gOUDKA14jxHU= github.com/gogo/googleapis v0.0.0-20180223154316-0cd9801be74a/go.mod h1:gf4bu3Q80BeJ6H1S1vYPm8/ELATdvryBaNFGgqEef3s= -github.com/gogo/googleapis v1.4.1/go.mod h1:2lpHqI5OcWCtVElxXnPt+s8oJvMpySlOyM6xDCrzib4= +github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= github.com/gogo/protobuf v1.2.0/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= +github.com/gogo/protobuf v1.3.1/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXPKa29o= github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= github.com/gogo/status v1.1.0/go.mod h1:BFv9nrluPLmrS0EmGVvLaPNmRosr9KapBYd5/hpY1WM= -github.com/golang-jwt/jwt v3.2.2+incompatible/go.mod h1:8pz2t5EyA70fFQQSrl6XZXzqecmYZeUEB8OUGHkxJ+I= -github.com/golang-jwt/jwt/v4 v4.3.0 h1:kHL1vqdqWNfATmA0FNMdmZNMyZI1U6O31X4rlIPoBog= -github.com/golang-jwt/jwt/v4 v4.3.0/go.mod h1:/xlHOz8bRuivTWchD4jCa+NbatV+wEUSzwAxVc6locg= +github.com/golang-jwt/jwt/v4 v4.5.0 h1:7cYmW1XlMY7h7ii7UhUyChSgS5wUJEnm9uZVTGqOWzg= +github.com/golang-jwt/jwt/v4 v4.5.0/go.mod h1:m21LjoU+eqJr34lmDMbreY2eSTRJ1cv77w39/MY0Ch0= github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= +github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= +github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= +github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= +github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= +github.com/golang/mock v1.3.1/go.mod h1:sBzyDLLjw3U8JLTeZvSv8jJB+tU5PVekmnlKIyFUx0Y= +github.com/golang/mock v1.4.0/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= +github.com/golang/mock v1.4.1/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= +github.com/golang/mock v1.4.3/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= +github.com/golang/mock v1.4.4/go.mod h1:l3mdAwkq5BuhzHwde/uurv3sEJeZMXNpwsxVWU71h+4= github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= +github.com/golang/protobuf v1.3.4/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= github.com/golang/protobuf v1.3.5/go.mod h1:6O5/vntMXwX2lRkT1hjjk0nAC1IDOTvTlVgjlRvqsdk= github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8= github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA= @@ -194,44 +272,72 @@ github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w= github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0= github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8= github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= +github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= -github.com/golang/protobuf v1.5.2 h1:ROPKBNFfQgOUMifHyP+KYbvpjbdoFNs+aK7DXlji0Tw= github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= -github.com/golang/snappy v0.0.3/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= +github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg= +github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= github.com/golang/snappy v0.0.4/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= github.com/golang/snappy v0.0.5-0.20220116011046-fa5810519dcb h1:PBC98N2aIaM3XXiurYmW7fx4GZkL8feAMVq7nEjURHk= github.com/golang/snappy v0.0.5-0.20220116011046-fa5810519dcb/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= github.com/golangci/lint-1 v0.0.0-20181222135242-d2cdd8c08219/go.mod h1:/X8TswGSh1pIozq4ZwCfxS0WA5JGXguxk94ar/4c87Y= github.com/gomodule/redigo v1.7.1-0.20190724094224-574c33c3df38/go.mod h1:B4C85qUVwatsJoIUNIfCRsp7qO0iAmpGFZ4EELWSbC4= +github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= +github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.4.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.8/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= +github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/go-querystring v1.0.0/go.mod h1:odCYkC5MyYFN7vkCjXpyrEuKhc/BUO6wN/zVPAxq5ck= +github.com/google/go-querystring v1.1.0 h1:AnCroh3fv4ZBgVIf1Iwtovgjaw/GiKJo8M8yD/fhyJ8= +github.com/google/go-querystring v1.1.0/go.mod h1:Kcdr2DB4koayq7X8pmAG4sNG59So17icRSOU623lUBU= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= github.com/google/gofuzz v1.1.1-0.20200604201612-c04b05f3adfa h1:Q75Upo5UN4JbPFURXZ8nLKYUvF85dyFRop/vQ0Rv+64= github.com/google/gofuzz v1.1.1-0.20200604201612-c04b05f3adfa/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= +github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs= +github.com/google/martian/v3 v3.0.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0= +github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= +github.com/google/pprof v0.0.0-20190515194954-54271f7e092f/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= +github.com/google/pprof v0.0.0-20191218002539-d4f498aebedc/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= +github.com/google/pprof v0.0.0-20200212024743-f11f1df84d12/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= +github.com/google/pprof v0.0.0-20200229191704-1ebb73c60ed3/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= +github.com/google/pprof v0.0.0-20200430221834-fc25d7d30c6d/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= +github.com/google/pprof v0.0.0-20200708004538-1a94d8640e99/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= github.com/google/pprof v0.0.0-20230207041349-798e818bf904 h1:4/hN5RUoecvl+RmJRE2YxKWtnnQls6rQjjW5oV7qg2U= github.com/google/pprof v0.0.0-20230207041349-798e818bf904/go.mod h1:uglQLonpP8qtYCYyzA+8c/9qtqgA3qsXGYqCPKARAFg= +github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= github.com/google/subcommands v1.2.0/go.mod h1:ZjhPrFU+Olkh9WazFPsl27BQ4UPiG37m3yTrtFlrHVk= -github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I= github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg= +github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk= github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= github.com/gorilla/mux v1.8.0/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB71So= -github.com/gorilla/websocket v1.4.1/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= +github.com/gorilla/websocket v1.4.0/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ= github.com/gorilla/websocket v1.4.2 h1:+/TMaTYc4QFitKJxsQ7Yye35DkWvkdLcvGKqM+x0Ufc= github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= github.com/graph-gophers/graphql-go v1.3.0 h1:Eb9x/q6MFpCLz7jBCiP/WTxjSDrYLR1QY41SORZyNJ0= github.com/graph-gophers/graphql-go v1.3.0/go.mod h1:9CQHMSxwO4MprSdzoIEobiHpoLtHm77vfxsvsIN5Vuc= github.com/hashicorp/go-bexpr v0.1.10 h1:9kuI5PFotCboP3dkDYFr/wi0gg0QVbSNz5oFRpxn4uE= github.com/hashicorp/go-bexpr v0.1.10/go.mod h1:oxlubA2vC/gFVfX1A6JGp7ls7uCDlfJn732ehYYg+g0= +github.com/hashicorp/go-cleanhttp v0.5.2 h1:035FKYIWjmULyFRBKPs8TBQoi0x6d9G4xc9neXJWAZQ= +github.com/hashicorp/go-cleanhttp v0.5.2/go.mod h1:kO/YDlP8L1346E6Sodw+PrpBSV4/SoxCXGY6BqNFT48= +github.com/hashicorp/go-hclog v0.9.2/go.mod h1:5CU+agLiy3J7N7QjHK5d05KxGsuXiQLrjA0H7acj2lQ= +github.com/hashicorp/go-hclog v1.2.0 h1:La19f8d7WIlm4ogzNHB0JGqs5AUDAZ2UfCY4sJXcJdM= +github.com/hashicorp/go-retryablehttp v0.7.4 h1:ZQgVdpTdAL7WpMIwLzCfbalOcSUdkDZnpUv3/+BxzFA= +github.com/hashicorp/go-retryablehttp v0.7.4/go.mod h1:Jy/gPYAdjqffZ/yFGCFV2doI5wjtH1ewM9u8iYVjtX8= github.com/hashicorp/go-version v1.2.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA= +github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= +github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ= github.com/holiman/billy v0.0.0-20230718173358-1c7e68d277a7 h1:3JQNjnMRil1yD0IfZKHF9GxxWKDJGj8I0IqOUol//sw= github.com/holiman/billy v0.0.0-20230718173358-1c7e68d277a7/go.mod h1:5GuXa7vkL8u9FkFuWdVvfR5ix8hRB7DbOAaYULamFpc= @@ -240,10 +346,10 @@ github.com/holiman/bloomfilter/v2 v2.0.3/go.mod h1:zpoh+gs7qcpqrHr3dB55AMiJwo0iURXE7ZOP9L9hSkA= github.com/holiman/uint256 v1.2.3 h1:K8UWO1HUJpRMXBxbmaY1Y8IAMZC/RsKB+ArEnnK4l5o= github.com/holiman/uint256 v1.2.3/go.mod h1:SC8Ryt4n+UBbPbIBKaG9zbbDlp4jOru9xFZmPzLUTxw= github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= -github.com/huin/goupnp v1.0.3 h1:N8No57ls+MnjlB+JPiCVSOyy/ot7MJTqlo7rn+NYSqQ= -github.com/huin/goupnp v1.0.3/go.mod h1:ZxNlw5WqJj6wSsRK5+YfflQGXYfccj5VgQsMNixHM7Y= -github.com/huin/goutil v0.0.0-20170803182201-1ca381bf3150/go.mod h1:PpLOETDnJ0o3iZrZfqZzyLl6l7F3c6L1oWn7OICBi6o= -github.com/hydrogen18/memlistener v0.0.0-20200120041712-dcc25e7acd91/go.mod h1:qEIFzExnS6016fRpRfxrExeVn2gbClQA99gQhnIcdhE= +github.com/huin/goupnp v1.3.0 h1:UvLUlWDNpoUdYzb2TCn+MuTWtcjXKSza2n6CBdQ0xXc= +github.com/huin/goupnp v1.3.0/go.mod h1:gnGPsThkYa7bFi/KWmEysQRf48l2dvR5bxr2OFckNX8= +github.com/hydrogen18/memlistener v0.0.0-20141126152155-54553eb933fb/go.mod h1:qEIFzExnS6016fRpRfxrExeVn2gbClQA99gQhnIcdhE= +github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= github.com/ianlancetaylor/demangle v0.0.0-20220319035150-800ac71e25c2/go.mod h1:aYm2/VgdVmcIU8iMfdMvDMsRAQjcfZSKFby6HOFvi/w= github.com/imkira/go-interpol v1.1.0/go.mod h1:z0h2/2T3XF8kyEPpRgJ3kmNv+C43p+I/CoI+jC3w2iA= github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= @@ -251,42 +357,54 @@ github.com/influxdata/influxdb-client-go/v2 v2.4.0 h1:HGBfZYStlx3Kqvsv1h2pJixbCl/jhnFtxpKFAv9Tu5k= github.com/influxdata/influxdb-client-go/v2 v2.4.0/go.mod h1:vLNHdxTJkIf2mSLvGrpj8TCcISApPoXkaxP8g9uRlW8= github.com/influxdata/influxdb1-client v0.0.0-20220302092344-a9ab5670611c h1:qSHzRbhzK8RdXOsAdfDgO49TtqC1oZ+acxPrkfTxcCs= github.com/influxdata/influxdb1-client v0.0.0-20220302092344-a9ab5670611c/go.mod h1:qj24IKcXYK6Iy9ceXlo3Tc+vtHo9lIhSX5JddghvEPo= +github.com/influxdata/line-protocol v0.0.0-20200327222509-2487e7298839 h1:W9WBk7wlPfJLvMCdtV4zPulc4uCPrlywQOmbFOhgQNU= github.com/influxdata/line-protocol v0.0.0-20200327222509-2487e7298839/go.mod h1:xaLFMmpvUxqXtVkUJfg9QmT88cDaCJ3ZKgdZ78oO8Qo= -github.com/influxdata/line-protocol v0.0.0-20210311194329-9aa0e372d097 h1:vilfsDSy7TDxedi9gyBkMvAirat/oRcL0lFdJBf6tdM= -github.com/influxdata/line-protocol v0.0.0-20210311194329-9aa0e372d097/go.mod h1:xaLFMmpvUxqXtVkUJfg9QmT88cDaCJ3ZKgdZ78oO8Qo= github.com/iris-contrib/blackfriday v2.0.0+incompatible/go.mod h1:UzZ2bDEoaSGPbkg6SAB4att1aAwTmVIx/5gCVqeyUdI= github.com/iris-contrib/go.uuid v2.0.0+incompatible/go.mod h1:iz2lgM/1UnEf1kP0L/+fafWORmlnuysV2EMP8MW+qe0= -github.com/iris-contrib/jade v1.1.3/go.mod h1:H/geBymxJhShH5kecoiOCSssPX7QWYH7UaeZTSWddIk= -github.com/iris-contrib/pongo2 v0.0.1/go.mod h1:Ssh+00+3GAZqSQb30AvBRNxBx7rf0GqwkjqxNd0u65g= +github.com/iris-contrib/i18n v0.0.0-20171121225848-987a633949d0/go.mod h1:pMCz62A0xJL6I+umB2YTlFRwWXaDFA0jy+5HzGiJjqI= github.com/iris-contrib/schema v0.0.1/go.mod h1:urYA3uvUNG1TIIjOSCzHr9/LmbQo8LrOcOqfqxa4hXw= github.com/jackpal/go-nat-pmp v1.0.2 h1:KzKSgb7qkJvOUTqYl9/Hg/me3pWgBmERKrTGD7BdWus= github.com/jackpal/go-nat-pmp v1.0.2/go.mod h1:QPH045xvCAeXUZOxsnwmrtiCoxIr9eob+4orBN1SBKc= -github.com/jedisct1/go-minisign v0.0.0-20190909160543-45766022959e h1:UvSe12bq+Uj2hWd8aOlwPmoZ+CITRFrdit+sDGfAg8U= -github.com/jedisct1/go-minisign v0.0.0-20190909160543-45766022959e/go.mod h1:G1CVv03EnqU1wYL2dFwXxW2An0az9JTl/ZsqXQeBlkU= +github.com/jedisct1/go-minisign v0.0.0-20230811132847-661be99b8267 h1:TMtDYDHKYY15rFihtRfck/bfFqNfvcabqvXAFQfAUpY= +github.com/jedisct1/go-minisign v0.0.0-20230811132847-661be99b8267/go.mod h1:h1nSAbGFqGVzn6Jyl1R/iCcBUHN4g+gW1u9CoBTrb9E= +github.com/jmespath/go-jmespath v0.4.0 h1:BEgLn5cpjn8UN1mAw4NjwDrS35OdebyEtFe+9YPoQUg= github.com/jmespath/go-jmespath v0.4.0/go.mod h1:T8mJZnbsbmF+m6zOOFylbeCJqk5+pHWvzYPziyZiYoo= +github.com/jmespath/go-jmespath/internal/testify v1.5.1 h1:shLQSRRSCCPj3f2gpwzGwWFoC7ycTf1rcQZHOlsJ6N8= github.com/jmespath/go-jmespath/internal/testify v1.5.1/go.mod h1:L3OGu8Wl2/fWfCI6z80xFu9LTZmf1ZRjMHUOPmWr69U= +github.com/jpillora/backoff v1.0.0/go.mod h1:J/6gKK9jxlEcS3zixgDgUAsiuZ7yrSoa/FX5e0EB2j4= github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= -github.com/json-iterator/go v1.1.9/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= +github.com/json-iterator/go v1.1.10/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= +github.com/json-iterator/go v1.1.11/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= +github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo= +github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU= +github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk= github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU= +github.com/juju/errors v0.0.0-20181118221551-089d3ea4e4d5/go.mod h1:W54LbzXuIE0boCoNJfwqpmkKJ1O4TCTZMetAt6jGk7Q= +github.com/juju/loggo v0.0.0-20180524022052-584905176618/go.mod h1:vgyd7OREkbtVEN/8IXZe5Ooef3LQePvuBm9UWj6ZL8U= +github.com/juju/testing v0.0.0-20180920084828-472a3e8b2073/go.mod h1:63prj8cnj0tU0S9OHjGJn+b1h0ZghCndfnbQolrYTwA= +github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w= github.com/julienschmidt/httprouter v1.3.0 h1:U0609e9tgbseu3rBINet9P48AI/D3oJs4dN7jwJOQ1U= github.com/julienschmidt/httprouter v1.3.0/go.mod h1:JR6WtHb+2LUe8TCKY3cZOxFyyO8IZAc4RVcycCCAKdM= github.com/k0kubun/colorstring v0.0.0-20150214042306-9440f1994b88/go.mod h1:3w7q1U84EfirKl04SVQ/s7nPm1ZPhiXd34z40TNz36k= -github.com/karalabe/usb v0.0.3-0.20230711191512-61db3e06439c h1:AqsttAyEyIEsNz5WLRwuRwjiT5CMDUfLk6cFJDVPebs= -github.com/karalabe/usb v0.0.3-0.20230711191512-61db3e06439c/go.mod h1:Od972xHfMJowv7NGVDiWVxk2zxnWgjLlJzE+F4F7AGU= -github.com/kataras/golog v0.0.10/go.mod h1:yJ8YKCmyL+nWjERB90Qwn+bdyBZsaQwU3bTVFgkFIp8= -github.com/kataras/iris/v12 v12.1.8/go.mod h1:LMYy4VlP67TQ3Zgriz8RE2h2kMZV2SgMYbq3UhfoFmE= -github.com/kataras/neffos v0.0.14/go.mod h1:8lqADm8PnbeFfL7CLXh1WHw53dG27MC3pgi2R1rmoTE= -github.com/kataras/pio v0.0.2/go.mod h1:hAoW0t9UmXi4R5Oyq5Z4irTbaTsOemSrDGUtaTl7Dro= -github.com/kataras/sitemap v0.0.5/go.mod h1:KY2eugMKiPwsJgx7+U103YZehfvNGOXURubcGyk0Bz8= +github.com/karalabe/usb v0.0.2 h1:M6QQBNxF+CQ8OFvxrT90BA0qBOXymndZnk5q235mFc4= +github.com/karalabe/usb v0.0.2/go.mod h1:Od972xHfMJowv7NGVDiWVxk2zxnWgjLlJzE+F4F7AGU= +github.com/kataras/golog v0.0.9/go.mod h1:12HJgwBIZFNGL0EJnMRhmvGA0PQGx8VFwrZtM4CqbAk= +github.com/kataras/iris/v12 v12.0.1/go.mod h1:udK4vLQKkdDqMGJJVd/msuMtN6hpYJhg/lSzuxjhO+U= +github.com/kataras/neffos v0.0.10/go.mod h1:ZYmJC07hQPW67eKuzlfY7SO3bC0mw83A3j6im82hfqw= +github.com/kataras/pio v0.0.0-20190103105442-ea782b38602d/go.mod h1:NV88laa9UiiDuX9AhMbDPkGYSPugBOV6yTZB1l2K9Z0= github.com/kilic/bls12-381 v0.1.0 h1:encrdjqKMEvabVQ7qYOKu1OvhqpK4s47wDYtNiPtlp4= github.com/kilic/bls12-381 v0.1.0/go.mod h1:vDTTHJONJ6G+P2R74EhnyotQDTliQDnFEwhdmfzw1ig= +github.com/kisielk/errcheck v1.2.0/go.mod h1:/BMXB+zMLi60iA8Vv6Ksmxu/1UDYcXs4uQLJ+jE2L00= github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= github.com/klauspost/compress v1.8.2/go.mod h1:RyIbtBH6LamlWaDj8nUwkbUhJ87Yi3uG0guNDohfE1A= -github.com/klauspost/compress v1.9.7/go.mod h1:RyIbtBH6LamlWaDj8nUwkbUhJ87Yi3uG0guNDohfE1A= +github.com/klauspost/compress v1.9.0/go.mod h1:RyIbtBH6LamlWaDj8nUwkbUhJ87Yi3uG0guNDohfE1A= github.com/klauspost/compress v1.15.15 h1:EF27CXIuDsYJ6mmvtBRlEuB2UVOqHG1tAXgZ7yIO+lw= github.com/klauspost/compress v1.15.15/go.mod h1:ZcK2JAFqKOpnBlxcLsJzYfrS9X1akm9fHZNnD9+Vo/4= github.com/klauspost/cpuid v1.2.1/go.mod h1:Pj4uuM528wm8OyEC2QMXAi2YiTZ96dNQPGgoMS4s3ek= +github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= +github.com/konsorten/go-windows-terminal-sequences v1.0.3/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= +github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= github.com/kr/pretty v0.3.0/go.mod h1:640gp4NfQd8pI5XOwp5fnNeVWj67G7CFk/SaSQn7NBk= @@ -298,8 +416,8 @@ github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0SNc= github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw= +github.com/labstack/echo/v4 v4.1.11/go.mod h1:i541M3Fj6f76NZtHSj7TXnyM8n2gaodfvfxNnFqi74g= github.com/labstack/echo/v4 v4.2.1/go.mod h1:AA49e0DZ8kk5jTOOCKNuPR6oTnBS0dYiM4FW1e6jwpg= -github.com/labstack/echo/v4 v4.5.0/go.mod h1:czIriw4a0C1dFun+ObrXp7ok03xON0N1awStJ6ArI7Y= github.com/labstack/gommon v0.3.0/go.mod h1:MULnywXg0yavhxWKc+lOruYdAhDwPK9wf0OL7NoOu+k= github.com/leanovate/gopter v0.2.9 h1:fQjYxZaynp97ozCzfOyOuAGOU4aU/z37zf/tOujFk7c= github.com/leanovate/gopter v0.2.9/go.mod h1:U2L/78B+KVFIx2VmW6onHJQzXtFb+p5y3y2Sh+Jxxv8= @@ -310,7 +428,7 @@ github.com/matryer/moq v0.0.0-20190312154309-6cfb0558e1bd/go.mod h1:9ELz6aaclSIGnZBoaSLZ3NAl1VTufbOrXBPvtcy6WiQ= github.com/mattn/go-colorable v0.1.2/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE= github.com/mattn/go-colorable v0.1.7/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= github.com/mattn/go-colorable v0.1.8/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= -github.com/mattn/go-colorable v0.1.11/go.mod h1:u5H1YNBxpqRaxsYJYSkiCWKzEfiAb1Gb520KVy5xxl4= +github.com/mattn/go-colorable v0.1.9/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA= github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg= github.com/mattn/go-isatty v0.0.7/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= @@ -318,15 +436,19 @@ github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= github.com/mattn/go-isatty v0.0.9/go.mod h1:YNRxwqDuOph6SZLI9vUUz6OYw3QyUt7WiY2yME+cCiQ= github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94= -github.com/mattn/go-isatty v0.0.16 h1:bq3VjFmv/sOjHtdEhmkEV4x1AJtvUvOJ2PFAZ5+peKQ= github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= +github.com/mattn/go-isatty v0.0.17 h1:BTarxUcIeDqL27Mc+vyvdWYSL28zpIhv3RoTdsLMPng= +github.com/mattn/go-isatty v0.0.17/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= github.com/mattn/go-runewidth v0.0.3/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU= -github.com/mattn/go-runewidth v0.0.9 h1:Lm995f3rfxdpd6TSmuVCHVb/QhupuXlYr8sCI/QdE+0= github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI= +github.com/mattn/go-runewidth v0.0.13 h1:lTGmDsbAYt5DmK6OnoV7EuIF1wEIFAcxld6ypU4OSgU= +github.com/mattn/go-runewidth v0.0.13/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w= github.com/mattn/goveralls v0.0.2/go.mod h1:8d1ZMHsd7fW6IRPKQh46F2WRpyib5/X4FOpevwGNQEw= -github.com/matttproud/golang_protobuf_extensions v1.0.4 h1:mmDVorXM7PCGKw94cs5zkfA9PSy5pEvNWRP0ET0TIVo= -github.com/matttproud/golang_protobuf_extensions v1.0.4/go.mod h1:BSXmuO+STAnVfrANrmjBb36TMTDstsz7MSK+HVaYKv4= -github.com/mediocregopher/radix/v3 v3.4.2/go.mod h1:8FL3F6UQRXHXIBSPUs5h0RybMF8i4n7wVopoX3x7Bv8= +github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= +github.com/matttproud/golang_protobuf_extensions v1.0.2-0.20181231171920-c182affec369 h1:I0XW9+e1XWDxdcEniV4rQAIOPUGDq67JSCiRCgGCZLI= +github.com/matttproud/golang_protobuf_extensions v1.0.2-0.20181231171920-c182affec369/go.mod h1:BSXmuO+STAnVfrANrmjBb36TMTDstsz7MSK+HVaYKv4= +github.com/mediocregopher/mediocre-go-lib v0.0.0-20181029021733-cb65787f37ed/go.mod h1:dSsfyI2zABAdhcbvkXqgxOxrCsbYeHCPgrZkku60dSg= +github.com/mediocregopher/radix/v3 v3.3.0/go.mod h1:EmfVyvspXz1uZEyPBMyGK+kjWiKQGvsUt6O3Pj+LDCQ= github.com/microcosm-cc/bluemonday v1.0.2/go.mod h1:iVP4YcDBq+n/5fb23BhYFvIMq/leAFZyRl6bYmGDlGc= github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= @@ -341,23 +463,24 @@ github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= -github.com/modocache/gover v0.0.0-20171022184752-b58185e213c5/go.mod h1:caMODM3PzxT8aQXRPkAt8xlV/e7d7w8GM5g0fa5F0D8= +github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= github.com/moul/http2curl v1.0.0/go.mod h1:8UbvGypXm98wA/IqH45anm5Y2Z6ep6O31QGOAZ3H0fQ= +github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= +github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= github.com/naoina/go-stringutil v0.1.0 h1:rCUeRUHjBjGTSHl0VC00jUPLz8/F9dDzYI70Hzifhks= github.com/naoina/go-stringutil v0.1.0/go.mod h1:XJ2SJL9jCtBh+P9q5btrd/Ylo8XwT/h1USek5+NqSA0= github.com/naoina/toml v0.1.2-0.20170918210437-9fafd6967416 h1:shk/vn9oCoOTmwcouEdwIeOtOGA/ELRUw/GwvxwfT+0= github.com/naoina/toml v0.1.2-0.20170918210437-9fafd6967416/go.mod h1:NBIhNtsFMo3G2szEBne+bO4gS192HuIYRqfvOWb4i1E= -github.com/nats-io/jwt v0.3.0/go.mod h1:fRYCDE99xlTsqUzISS1Bi75UBJ6ljOJQOAAu5VglpSg= -github.com/nats-io/nats.go v1.9.1/go.mod h1:ZjDU1L/7fJ09jvUSRVBR2e7+RnLiiIQyqyzEE/Zbp4w= -github.com/nats-io/nkeys v0.1.0/go.mod h1:xpnFELMwJABBLVhffcfd1MZx6VsNRFpEugbxziKVo7w= +github.com/nats-io/nats.go v1.8.1/go.mod h1:BrFz9vVn0fU3AcH9Vn4Kd7W0NpJ651tD5omQ3M8LwxM= +github.com/nats-io/nkeys v0.0.2/go.mod h1:dab7URMsZm6Z/jp9Z5UGa87Uutgc2mVpXLC4B7TDb/4= github.com/nats-io/nuid v1.0.1/go.mod h1:19wcPz3Ph3q0Jbyiqsd0kePYG7A95tJPxeL+1OSON2c= github.com/nxadm/tail v1.4.4 h1:DQuhQpB1tVlglWS2hLQ5OV6B5r8aGxSrPc5Qo6uTN78= github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A= github.com/olekukonko/tablewriter v0.0.5 h1:P2Ga83D34wi1o9J6Wh1mRuqd4mF/x/lgBS7N7AbDhec= github.com/olekukonko/tablewriter v0.0.5/go.mod h1:hPp6KlRPjbx+hW8ykQs1w3UBbZlj6HuIJcUGPhkA7kY= github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= -github.com/onsi/ginkgo v1.10.3/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk= +github.com/onsi/ginkgo v1.13.0/go.mod h1:+REjRxOmWfHCjfv9TTWB1jD1Frx4XydAD3zm1lskyM0= github.com/onsi/ginkgo v1.14.0 h1:2mOpI4JVVPBN+WQRa0WKH2eXR+Ey+uK4n7Zj0aYpIQA= github.com/onsi/ginkgo v1.14.0/go.mod h1:iSB4RoI2tjJc9BBv4NKIKWKya62Rps+oPG/Lv9klQyY= github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY= @@ -370,40 +493,60 @@ github.com/peterh/liner v1.1.1-0.20190123174540-a2c9a5303de7 h1:oYW+YCJ1pachXTQmzR3rNLYGGz4g/UgFcjb28p/viDM= github.com/peterh/liner v1.1.1-0.20190123174540-a2c9a5303de7/go.mod h1:CRroGNssyjTd/qIG2FyxByd2S8JEAZXBl4qUrZf8GS0= github.com/pingcap/errors v0.11.4 h1:lFuQV/oaUMGcD2tqt+01ROSmJs75VG1ToEOkZIZ4nE4= github.com/pingcap/errors v0.11.4/go.mod h1:Oi8TUi2kEtXXLMJk9l1cGmz20kV3TaQ0usTwv5KuLY8= +github.com/pkg/browser v0.0.0-20210911075715-681adbf594b8 h1:KoWmjvw+nsYOo29YJK9vDA65RGE3NrOnUtO7a+RF9HU= github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA= +github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/prashantv/gostub v1.1.0 h1:BTyx3RfQjRHnUWaGF9oQos79AlQ5k8WNktv7VGvVH4g= -github.com/prometheus/client_golang v1.14.0 h1:nJdhIvne2eSX/XRAFV9PcvFFRbrjbcTUj0VP62TMhnw= -github.com/prometheus/client_golang v1.14.0/go.mod h1:8vpkKitgIVNcqrRBWh1C4TIUQgYNtG/XQE4E/Zae36Y= +github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= +github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo= +github.com/prometheus/client_golang v1.7.1/go.mod h1:PY5Wy2awLA44sXw4AOSfFBetzPP4j5+D6mVACh+pe2M= +github.com/prometheus/client_golang v1.11.0/go.mod h1:Z6t4BnS23TR94PD6BsDNk8yVqroYurpAkEiz0P2BEV0= +github.com/prometheus/client_golang v1.12.0 h1:C+UIj/QWtmqY13Arb8kwMt5j34/0Z2iKamrJ+ryC0Gg= +github.com/prometheus/client_golang v1.12.0/go.mod h1:3Z9XVyYiZYEO+YQWt3RD2R3jrbd179Rt297l4aS6nDY= +github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= +github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= -github.com/prometheus/client_model v0.3.0 h1:UBgGFHqYdG/TPFD1B1ogZywDqEkwp3fBMvqdiQ7Xew4= -github.com/prometheus/client_model v0.3.0/go.mod h1:LDGWKZIo7rky3hgvBe+caln+Dr3dPggB5dvjtD7w9+w= -github.com/prometheus/common v0.39.0 h1:oOyhkDq05hPZKItWVBkJ6g6AtGxi+fy7F4JvUV8uhsI= -github.com/prometheus/common v0.39.0/go.mod h1:6XBZ7lYdLCbkAVhwRsWTZn+IN5AB9F/NXd5w0BbEX0Y= -github.com/prometheus/procfs v0.9.0 h1:wzCHvIvM5SxWqYvwgVL7yJY8Lz3PKn49KQtpgMYJfhI= -github.com/prometheus/procfs v0.9.0/go.mod h1:+pB4zwohETzFnmlpe6yd2lSc+0/46IYZRB/chUwxUZY= +github.com/prometheus/client_model v0.2.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= +github.com/prometheus/client_model v0.2.1-0.20210607210712-147c58e9608a h1:CmF68hwI0XsOQ5UwlBopMi2Ow4Pbg32akc4KIVCOm+Y= +github.com/prometheus/client_model v0.2.1-0.20210607210712-147c58e9608a/go.mod h1:LDGWKZIo7rky3hgvBe+caln+Dr3dPggB5dvjtD7w9+w= +github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= +github.com/prometheus/common v0.10.0/go.mod h1:Tlit/dnDKsSWFlCLTWaA1cyBgKHSMdTB80sz/V91rCo= +github.com/prometheus/common v0.26.0/go.mod h1:M7rCNAaPfAosfx8veZJCuw84e35h3Cfd9VFqTh1DIvc= +github.com/prometheus/common v0.32.1 h1:hWIdL3N2HoUx3B8j3YN9mWor0qhY/NlEKZEaXxuIRh4= +github.com/prometheus/common v0.32.1/go.mod h1:vu+V0TpY+O6vW9J44gczi3Ap/oXXR10b+M/gUGO4Hls= +github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= +github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= +github.com/prometheus/procfs v0.1.3/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU= +github.com/prometheus/procfs v0.6.0/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA= +github.com/prometheus/procfs v0.7.3 h1:4jVXhlkAyzOScmCkXBTOLRLTz8EeU+eyjrwB/EPq0VU= +github.com/prometheus/procfs v0.7.3/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA= github.com/protolambda/bls12-381-util v0.0.0-20220416220906-d8552aa452c7 h1:cZC+usqsYgHtlBaGulVnZ1hfKAi8iWtujBnRLQE698c= github.com/protolambda/bls12-381-util v0.0.0-20220416220906-d8552aa452c7/go.mod h1:IToEjHuttnUzwZI5KBSM/LOOW3qLbbrHOEfp3SbECGY= +github.com/rivo/uniseg v0.2.0 h1:S1pD9weZBuJdFmowNwbpi7BJ8TNftyUImj/0WQi72jY= +github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc= +github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= github.com/rogpeppe/go-internal v1.6.1/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc= -github.com/rogpeppe/go-internal v1.8.1/go.mod h1:JeRgkft04UBgHMgCIwADu4Pn6Mtm5d4nPKWu0nJ5d+o= github.com/rogpeppe/go-internal v1.9.0 h1:73kH8U+JUqXU8lRuOHeVHaa/SZPifC7BkcraZVejAe8= github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs= github.com/rs/cors v1.7.0 h1:+88SsELBHx5r+hZ8TCkggzSstaWNbDvThkVK8H6f9ik= github.com/rs/cors v1.7.0/go.mod h1:gFx+x8UowdsKA9AchylcLynDq+nNFfI8FkUZdN/jGCU= github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g= -github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk= github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/ryanuber/columnize v2.1.0+incompatible/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts= -github.com/schollz/closestmatch v2.1.0+incompatible/go.mod h1:RtP1ddjLong6gTkbtmuhtR2uUrrJOpYzYRvbcPAid+g= -github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo= +github.com/sclevine/agouti v3.0.0+incompatible/go.mod h1:b4WX9W9L1sfQKXeJf1mUTLZKJ48R1S7H23Ji7oFO5Bw= +github.com/sergi/go-diff v1.1.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM= github.com/shirou/gopsutil v3.21.4-0.20210419000835-c7a38de76ee5+incompatible h1:Bn1aCHHRnjv4Bl16T8rcaFjYSrGrIZvpiGO6P3Q4GpU= github.com/shirou/gopsutil v3.21.4-0.20210419000835-c7a38de76ee5+incompatible/go.mod h1:5b4v6he4MtMOwMlS0TUMTu2PcXUg8+E1lC7eC3UO/RA= github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc= +github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= +github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= +github.com/sirupsen/logrus v1.6.0/go.mod h1:7uNnSEd1DgxDLC74fIahvMZmmYsHGZGEOFrfsX/uA88= github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc= github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA= github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ= @@ -415,34 +558,28 @@ github.com/spf13/viper v1.3.2/go.mod h1:ZiWeW+zYFKm7srdB9IoDzzZXaJaI5eL9QjNiN/DMA2s= github.com/status-im/keycard-go v0.2.0 h1:QDLFswOQu1r5jsycloeQh3bVU8n/NatHHaZobtDnDzA= github.com/status-im/keycard-go v0.2.0/go.mod h1:wlp8ZLbsmrF6g6WjugPAx+IzoLrkdf9+mHxBEeo3Hbg= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= -github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= -github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= +github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= -github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= -github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= -github.com/stretchr/testify v1.8.1 h1:w7B6lhMri9wdJUVmEZPGGhZzrYTPvgJArz7wNPgYKsk= -github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= +github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= +github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= github.com/supranational/blst v0.3.11 h1:LyU6FolezeWAhvQk0k6O/d49jqgO52MSDDfYgbeoEm4= github.com/supranational/blst v0.3.11/go.mod h1:jZJtfjgudtNl4en1tzwPIV3KjUnQUvG3/j+w+fVonLw= github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7 h1:epCh84lMvA70Z7CTTCmYQn2CKbY8j86K7/FAIr141uY= github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7/go.mod h1:q4W45IWZaF22tdD+VEXcAWRA037jwmWEB5VWYORlTpc= -github.com/tklauser/go-sysconf v0.3.5 h1:uu3Xl4nkLzQfXNsWn15rPc/HQCJKObbt1dKJeWp3vU4= -github.com/tklauser/go-sysconf v0.3.5/go.mod h1:MkWzOF4RMCshBAMXuhXJs64Rte09mITnppBXY/rYEFI= -github.com/tklauser/numcpus v0.2.2 h1:oyhllyrScuYI6g+h/zUvNXNp1wy7x8qQy3t/piefldA= -github.com/tklauser/numcpus v0.2.2/go.mod h1:x3qojaO3uyYt0i56EW/VUYs7uBvdl2fkfZFu0T9wgjM= +github.com/tklauser/go-sysconf v0.3.12 h1:0QaGUFOdQaIVdPgfITYzaTegZvdCjmYO52cSFAEVmqU= +github.com/tklauser/go-sysconf v0.3.12/go.mod h1:Ho14jnntGE1fpdOqQEEaiKRpvIavV0hSfmBq8nJbHYI= +github.com/tklauser/numcpus v0.6.1 h1:ng9scYS7az0Bk4OZLvrNXNSAO2Pxr1XXRAPyjhIx+Fk= +github.com/tklauser/numcpus v0.6.1/go.mod h1:1XfjsgE2zo8GVw7POkMbHENHzVg3GzmoZ9fESEdAacY= github.com/tyler-smith/go-bip39 v1.1.0 h1:5eUemwrMargf3BSLRRCalXT93Ns6pQJIjYQN2nyfOP8= github.com/tyler-smith/go-bip39 v1.1.0/go.mod h1:gUYDtqQw1JS3ZJ8UWVcGTGqqr6YIN3CWg+kkNaLt55U= github.com/ugorji/go v1.1.4/go.mod h1:uQMGLiO92mf5W77hV/PUCpI3pbzQx3CRekS0kk+RGrc= -github.com/ugorji/go v1.1.7/go.mod h1:kZn38zHttfInRq0xu/PH0az30d+z6vm202qpg1oXVMw= github.com/ugorji/go/codec v0.0.0-20181204163529-d75b2dcb6bc8/go.mod h1:VFNgLljTbGfSG7qAOspJ7OScBnGdDN/yBr0sguwnwf0= -github.com/ugorji/go/codec v1.1.7/go.mod h1:Ax+UKWsSmolVDwsd+7N3ZtXu+yMGCf907BLYF3GoBXY= -github.com/urfave/cli/v2 v2.3.0/go.mod h1:LJmUH05zAU44vOAcrfzZQKsZbVcdbOG8rtL3/XcUArI= -github.com/urfave/cli/v2 v2.24.1 h1:/QYYr7g0EhwXEML8jO+8OYt5trPnLHS0p3mrgExJ5NU= -github.com/urfave/cli/v2 v2.24.1/go.mod h1:GHupkWPMM0M/sj1a2b4wUrWBPzazNrIjouW6fmdJLxc= +github.com/urfave/cli/v2 v2.25.7 h1:VAzn5oq403l5pHjc4OhD54+XGO9cdKVL/7lDjF+iKUs= +github.com/urfave/cli/v2 v2.25.7/go.mod h1:8qnjx1vcq5s2/wpsqoZFndg2CE5tNFyrTvS6SinrnYQ= github.com/urfave/negroni v1.0.0/go.mod h1:Meg73S6kFm/4PpbYdq35yYWoCZ9mS/YSx+lKnmiohz4= github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc= github.com/valyala/fasthttp v1.6.0/go.mod h1:FstJa9V+Pj9vQ7OJie2qMHdwemEDaDiSdBnvPM1Su9w= @@ -459,174 +596,333 @@ github.com/yalp/jsonpath v0.0.0-20180802001716-5cc68e5049a0/go.mod h1:/LWChgwKmvncFJFHJ7Gvn9wZArjbV5/FppcK2fKk/tI= github.com/yudai/gojsondiff v1.0.0/go.mod h1:AY32+k2cwILAkW1fbgxQ5mUmMiZFgLIV+FBNExI05xg= github.com/yudai/golcs v0.0.0-20170316035057-ecda9a501e82/go.mod h1:lgjkn3NuSvDfVJdfcVVdX+jpBxNmX4rDAzaS45IcYoM= github.com/yudai/pp v2.0.1+incompatible/go.mod h1:PuxR/8QJ7cyCkFp/aUDS+JY727OFEZkTdatxwunjIkc= +github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= -github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= +go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU= +go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8= +go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= +go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= +go.opencensus.io v0.22.4/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= go.uber.org/automaxprocs v1.5.2 h1:2LxUOGiR3O6tw8ui5sZa2LAaHnsviZdVOUZw4fvbnME= go.uber.org/automaxprocs v1.5.2/go.mod h1:eRbA25aqJrxAbsLO0xy5jVwPt7FQnRgjW+efnwa1WM0= +golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20181203042331-505ab145d0a9/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= -golang.org/x/crypto v0.0.0-20190909091759-094676da4a83/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= -golang.org/x/crypto v0.0.0-20191227163750-53104e6ec876/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20200820211705-5c72a883971a/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20201221181555-eec23a3978ad/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I= -golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4= golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= -golang.org/x/crypto v0.9.0 h1:LF6fAI+IutBocDJ2OT0Q1g8plpYljMZ4+lty+dsqw3g= -golang.org/x/crypto v0.9.0/go.mod h1:yrmDGqONDYtNj3tH8X9dzUun2m2lzPa9ngI6/RUPGR0= +golang.org/x/crypto v0.14.0 h1:wBqGXzWJW6m1XrIKlAH0Hs1JJ7+9KBwnIO8v66Q9cHc= +golang.org/x/crypto v0.14.0/go.mod h1:MVFd36DqK4CsrnJYDkBA3VC4m2GkXAM0PvzMCn4JQf4= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= -golang.org/x/exp v0.0.0-20230810033253-352e893a4cad h1:g0bG7Z4uG+OgH2QDODnjp6ggkk1bJDsINcuWmJN1iJU= -golang.org/x/exp v0.0.0-20230810033253-352e893a4cad/go.mod h1:FXUEEKJgO7OQYeo8N01OfiKP8RXMtf6e8aTskBGqWdc= +golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= +golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8= +golang.org/x/exp v0.0.0-20190829153037-c13cbed26979/go.mod h1:86+5VVa7VpoJ4kLfm080zCjGlMRFzhUhsZKEZO7MGek= +golang.org/x/exp v0.0.0-20191030013958-a1ab85dbe136/go.mod h1:JXzH8nQsPlswgeRAPE3MuO9GYsAcnJvJ4vnMwN/5qkY= +golang.org/x/exp v0.0.0-20191129062945-2f5052295587/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= +golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= +golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= +golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM= +golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU= +golang.org/x/exp v0.0.0-20230905200255-921286631fa9 h1:GoHiUyI/Tp2nVkLI2mCxVkOjsbSXD66ic0XW0js0R9g= +golang.org/x/exp v0.0.0-20230905200255-921286631fa9/go.mod h1:S2oDrQGGwySpoQPVqRShND87VCbxmc6bL1Yd2oYrm6k= +golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js= +golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= +golang.org/x/lint v0.0.0-20190301231843-5614ed5bae6f/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= -golang.org/x/lint v0.0.0-20210508222113-6edffad5e616/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= +golang.org/x/lint v0.0.0-20190409202823-959b441ac422/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +golang.org/x/lint v0.0.0-20190909230951-414d861bb4ac/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +golang.org/x/lint v0.0.0-20191125180803-fdd1cda4f05f/go.mod h1:5qLYkcX4OjUUV8bRuDixDT3tpyyb+LUpUlRWLxfhWrs= +golang.org/x/lint v0.0.0-20200130185559-910be7a94367/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= +golang.org/x/lint v0.0.0-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= +golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE= +golang.org/x/mobile v0.0.0-20190719004257-d2bd2a29d028/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o= +golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc= +golang.org/x/mod v0.1.0/go.mod h1:0QHyrYULN0/3qlju5TqG8bIK38QM8yzMo5ekMj3DlcY= golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= +golang.org/x/mod v0.1.1-0.20191107180719-034126e5016b/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= -golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= -golang.org/x/mod v0.11.0 h1:bUO06HqtnRcc/7l71XBe4WcqTZ+3AH1J59zWDDwLKgU= -golang.org/x/mod v0.11.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= +golang.org/x/mod v0.12.0 h1:rmsUpXtvNzj340zd98LZ4KntptpfRHwpFOHG188oHXc= +golang.org/x/mod v0.12.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20181220203305-927f97764cc3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190327091125-710a502c58a2/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190501004415-9ce7a6920f09/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190503192946-f4e77d36d62c/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= +golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20190628185345-da137c7871d7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20190724013045-ca1201d0de80/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190827160401-ba9fcec4b297/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20191209160850-c0dbc17a3553/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200114155413-6afb5195e5aa/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200222125558-5a598a2470a0/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200301022130-244492dfa37a/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20200501053045-e0ff5e5a1de5/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20200506145744-7e3656a0809f/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20200513185701-a91f0712d120/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20200520182314-0ba52f642ac2/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= +golang.org/x/net v0.0.0-20200707034311-ab3426394381/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= golang.org/x/net v0.0.0-20200813134508-3edf25e44fcc/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= -golang.org/x/net v0.0.0-20201010224723-4f7140c49acb/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.0.0-20210119194325-5f4716e94777/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= -golang.org/x/net v0.0.0-20210220033124-5f55cee0dc0d/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= -golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM= -golang.org/x/net v0.0.0-20210610132358-84b48f89b13b/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= -golang.org/x/net v0.0.0-20210805182204-aaa1db679c0d/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= -golang.org/x/net v0.0.0-20211008194852-3b03d305991f/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= +golang.org/x/net v0.0.0-20210525063256-abc453219eb5/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= -golang.org/x/net v0.10.0 h1:X2//UzNDwYmtCLn7To6G58Wr6f5ahEAQgKNzv9Y951M= -golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg= +golang.org/x/net v0.17.0 h1:pVaXccu2ozPjCXewfr1S7xza/zcXTity9cCdXQYSjIM= +golang.org/x/net v0.17.0/go.mod h1:NxSsAGuq816PNPmqtQdLE42eU2Fs7NoRIZrHJAlaCOE= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= +golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= +golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= +golang.org/x/oauth2 v0.0.0-20191202225959-858c2ad4c8b6/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= +golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= +golang.org/x/oauth2 v0.0.0-20210514164344-f6687ab2804c/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.3.0 h1:ftCYgMx6zT/asHUrPw8BLLscYtGznsLAnjq5RH9P66E= golang.org/x/sync v0.3.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20181205085412-a5c9d58dba9a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190626221950-04f50cda93cb/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190813064441-fde4db37ae7a/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190904154756-749cb33beabd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191001151750-bb3f8db39f24/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191228213918-04cbcbbfeed8/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200106162015-b016eb3dc98e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200113162924-86b910548bc1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200122134326-e047566fdf82/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200202164722-d101bd2416d5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200212091648-12a6c2dcc1e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200302150141-5c8b2ff67527/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200331124033-c3d80250170d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200501052902-10377860bb8e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200511232937-7e40ca221e25/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200515095857-1151b9dac4a9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200519105757-fe76b779f299/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200523222454-059865788121/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200615200032-f1bc736245b1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200625212154-ddb9806d33ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200803210538-64077c9b5642/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200814200057-3d37ad5750ed/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200826173525-f9321e4c35a6/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201101102859-da207088b7d1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210316164454-77fc1eacc6aa/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210324051608-47abb6519492/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210403161142-5e06dd20ab57/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210603081109-ebe580a85c40/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20211007075335-d3039528d8ac/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20211020174200-9d6173849985/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220209214540-3681064d5158/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220114195835-da31bd327af9/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220310020820-b874c991c1a5/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220908164124-27713097b956/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.9.0 h1:KS/R3tvhPqvJvwcKfnBHJwwthS11LRhmM5D59eEXa0s= -golang.org/x/sys v0.9.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.13.0 h1:Af8nKPmuFypiUBjVoU9V20FiaFXOcuZI21p0ycVYYGE= +golang.org/x/sys v0.13.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= +golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= golang.org/x/text v0.3.8/go.mod h1:E6s5w1FMmriuDzIBO73fBruAKo1PCIq6d2Q6DHfQ8WQ= -golang.org/x/text v0.9.0 h1:2sjJmO8cDvYveuX97RDLsxlyUxLl+GHoLxBiRdHllBE= -golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= +golang.org/x/text v0.13.0 h1:ablQoSUd0tRdKxZewP80B+BaqeKJuVhuRxj/dkrun3k= +golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= +golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20201208040808-7e3f01d25324/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20210220033141-f8bda1e9f3ba/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.3.0 h1:rg5rLMjNzMS1RkNLzCG38eapWhnYLFYXDXj2gOlr8j4= golang.org/x/time v0.3.0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20181030221726-6c7e314b6563/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20181221001348-537d06c36207/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20190312151545-0bb0c0a6e846/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20190312170243-e65039ee4138/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= golang.org/x/tools v0.0.0-20190327201419-c70d86f8b7cf/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= golang.org/x/tools v0.0.0-20190328211700-ab21143f2384/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= +golang.org/x/tools v0.0.0-20190506145303-2d16b83fe98c/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= +golang.org/x/tools v0.0.0-20190606124116-d0a3d012864b/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= +golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= +golang.org/x/tools v0.0.0-20190628153133-6cdbf07be9d0/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= +golang.org/x/tools v0.0.0-20190816200558-6889da9d5479/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20190911174233-4f2ddba30aff/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191012152004-8de300cfc20a/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191113191852-77e3bb0ad9e7/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191115202509-3a792d9c32b2/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191125144606-a911d9008d1f/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191130070609-6e064ea0cf2d/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191216173652-a0e659d51361/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20191227053925-7b8e75db28f4/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200117161641-43d50277825c/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200122220014-bf1340f18c4a/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200204074204-1cc6d1ef6c74/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200207183749-b753a1ba74fa/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200212150539-ea181f53ac56/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200224181240-023911ca70b2/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200227222343-706bc42d1f0d/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200304193943-95d2e580d8eb/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw= +golang.org/x/tools v0.0.0-20200312045724-11d5b4c81c7d/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw= +golang.org/x/tools v0.0.0-20200331025713-a30bf2db82d4/go.mod h1:Sl4aGygMT6LrqrWclx+PTx3U+LnKx/seiNR+3G19Ar8= +golang.org/x/tools v0.0.0-20200501065659-ab2804fb9c9d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20200512131952-2bc93b1c0c88/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20200515010526-7d3b6ebf133d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20200618134242-20370b0cb4b2/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20200729194436-6467de6f59a7/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= +golang.org/x/tools v0.0.0-20200804011535-6c149bb5ef0d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= +golang.org/x/tools v0.0.0-20200825202427-b303f430e36d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= -golang.org/x/tools v0.1.3/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= -golang.org/x/tools v0.9.1 h1:8WMNJAz3zrtPmnYC7ISf5dEn3MT0gY7jBJfw27yrrLo= -golang.org/x/tools v0.9.1/go.mod h1:owI94Op576fPu3cIGQeHs3joujW/2Oc6MtlxbF5dfNc= +golang.org/x/tools v0.13.0 h1:Iey4qkscZuv0VvIt8E0neZjtPVQFSc870HQ448QgEmQ= +golang.org/x/tools v0.13.0/go.mod h1:HvlwmtVNQAhOuCjW7xxvovg8wbNq7LwfXh/k7wXUl58= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -golang.org/x/xerrors v0.0.0-20220517211312-f3a8303e98df h1:5Pf6pFKu98ODmgnpvkJ3kFUOQGGLIzLIkbzUHp47618= -golang.org/x/xerrors v0.0.0-20220517211312-f3a8303e98df/go.mod h1:K8+ghG5WaK9qNqU5K3HdILfMLy1f3aNYFI/wnl100a8= +google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE= +google.golang.org/api v0.7.0/go.mod h1:WtwebWUNSVBH/HAw79HIFXZNqEvBhG+Ra+ax0hx3E3M= +google.golang.org/api v0.8.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= +google.golang.org/api v0.9.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= +google.golang.org/api v0.13.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= +google.golang.org/api v0.14.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= +google.golang.org/api v0.15.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= +google.golang.org/api v0.17.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= +google.golang.org/api v0.18.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= +google.golang.org/api v0.19.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= +google.golang.org/api v0.20.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= +google.golang.org/api v0.22.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= +google.golang.org/api v0.24.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE= +google.golang.org/api v0.28.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE= +google.golang.org/api v0.29.0/go.mod h1:Lcubydp8VUV7KeIHD9z2Bys/sm/vGKnG1UHuDBSrHWM= +google.golang.org/api v0.30.0/go.mod h1:QGmEvQ87FHZNiUVJkT14jQNYJ4ZJjdRF23ZXz5138Fc= google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= +google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= +google.golang.org/appengine v1.6.1/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww/cMBSeb0= +google.golang.org/appengine v1.6.5/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= +google.golang.org/appengine v1.6.6/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= google.golang.org/genproto v0.0.0-20180518175338-11a468237815/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= +google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= +google.golang.org/genproto v0.0.0-20190418145605-e7d98fc518a7/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= +google.golang.org/genproto v0.0.0-20190425155659-357c62f0e4bb/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= +google.golang.org/genproto v0.0.0-20190502173448-54afdca5d873/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= +google.golang.org/genproto v0.0.0-20190801165951-fa694d86fc64/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= +google.golang.org/genproto v0.0.0-20190911173649-1774047e7e51/go.mod h1:IbNlFCBrqXvoKpeg0TB2l7cyZUmoaFKYIwrEpbDKLA8= +google.golang.org/genproto v0.0.0-20191108220845-16a3f7862a1a/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20191115194625-c23dd37a84c9/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20191216164720-4f79533eabd1/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20191230161307-f3c370f40bfb/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20200115191322-ca5a22157cba/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20200122232147-0452cf42e150/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20200204135345-fa8e72b47b90/go.mod h1:GmwEX6Z4W5gMy59cAlVYjN9JhxgbQH6Gn+gFDQe2lzA= +google.golang.org/genproto v0.0.0-20200212174721-66ed5ce911ce/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200224152610-e50cd9704f63/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200228133532-8c2c7df3a383/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200305110556-506484158171/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200312145019-da6875a35672/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200331122359-1ee6d9798940/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200430143042-b979b6f78d84/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200511104702-f5ebc3bea380/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200515170657-fc4c6c6a6587/go.mod h1:YsZOwe1myG/8QRHRsmBRE1LrgQY60beZKjly0O1fX9U= google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo= -google.golang.org/genproto v0.0.0-20210624195500-8bfb893ecb84/go.mod h1:SzzZ/N+nwJDaO1kznhnlzqS8ocJICar6hYhVyhi++24= +google.golang.org/genproto v0.0.0-20200618031413-b414f8b61790/go.mod h1:jDfRM7FcilCzHH/e9qn6dsT145K34l5v+OpcnNgKAAA= +google.golang.org/genproto v0.0.0-20200729003335-053ba62fc06f/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20200804131852-c06518451d9c/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20200825200019-8632dd797987/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/grpc v1.12.0/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw= google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= +google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38= +google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY= +google.golang.org/grpc v1.26.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= -google.golang.org/grpc v1.38.0/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM= +google.golang.org/grpc v1.27.1/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= +google.golang.org/grpc v1.28.0/go.mod h1:rpkK4SK4GF4Ach/+MFLZUBavHOvF2JJB5uozKKal+60= +google.golang.org/grpc v1.29.1/go.mod h1:itym6AZVZYACWQqET3MqgPpjcuV5QH3BxFS3IjizoKk= +google.golang.org/grpc v1.30.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= +google.golang.org/grpc v1.31.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= @@ -635,11 +931,13 @@ google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo= google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= +google.golang.org/protobuf v1.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGjtUeSXeh4= google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c= google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= -google.golang.org/protobuf v1.28.1 h1:d0NfwRgPtno5B1Wa6L2DAG+KivqkdutMf1UhdNx175w= -google.golang.org/protobuf v1.28.1/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= +google.golang.org/protobuf v1.27.1 h1:SnqbnDw1V7RiZcXPx5MEeqPv2s79L9i7BJUlG/+RurQ= +google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= +gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= @@ -649,28 +947,33 @@ gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= gopkg.in/go-playground/assert.v1 v1.2.1/go.mod h1:9RXL0bg/zibRAgZUYszZSwO/z8Y/a8bDuhia5mkpMnE= gopkg.in/go-playground/validator.v8 v8.18.2/go.mod h1:RX2a/7Ha8BgOhfk7j780h4/u/RRjR0eouCJSH80/M2Y= -gopkg.in/ini.v1 v1.51.1/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= gopkg.in/mgo.v2 v2.0.0-20180705113604-9856a29383ce/go.mod h1:yeKp02qBN3iKW1OzL3MGk2IdtZzaj7SFntXj72NppTA= gopkg.in/natefinch/lumberjack.v2 v2.0.0 h1:1Lc07Kr7qY4U2YPouBjpCLxpiyxIVoxqXgkXLknAOE8= gopkg.in/natefinch/lumberjack.v2 v2.0.0/go.mod h1:l0ndWWf7gzL7RNwBG7wST/UCcT4T24xpD6X8LsfU/+k= -gopkg.in/natefinch/npipe.v2 v2.0.0-20160621034901-c1b8fa8bdcce h1:+JknDZhAj8YMt7GC73Ei8pv4MzjDUNPHgQWJdtMAaDU= -gopkg.in/natefinch/npipe.v2 v2.0.0-20160621034901-c1b8fa8bdcce/go.mod h1:5AcXVHNjg+BDxry382+8OKon8SEWiKktQR07RKPsv1c= gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ= gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.2.3/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.5/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= -gopkg.in/yaml.v3 v3.0.0-20191120175047-4206685974f2/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= -gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gotest.tools/v3 v3.5.1 h1:EENdUnS3pdur5nybKYIh2Vfgc8IUNBjxDPSjtiJcOzU= +gotest.tools/v3 v3.5.1/go.mod h1:isy3WKz7GK6uNw/sbHzfKBLvlvXwUyV06n6brMxxopU= honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= +honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= +honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= +honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg= +honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= +honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= +rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8= +rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0= +rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA= rsc.io/tmplfunc v0.0.3 h1:53XFQh69AfOa8Tw0Jm7t+GV7KZhOi6jzsCzTtKbMvzU= rsc.io/tmplfunc v0.0.3/go.mod h1:AG3sTPzElb1Io3Yg4voV9AGZJuleGAwaVRxL9M49PhA=
diff --git ethereum/go-ethereum/internal/ethapi/testdata/eth_getBlockByHash-hash-1.json taikoxyz/taiko-geth/internal/ethapi/testdata/eth_getBlockByHash-hash-1.json new file mode 100644 index 0000000000000000000000000000000000000000..379636d5f380708426324ee2cbf8aedc6593c16b --- /dev/null +++ taikoxyz/taiko-geth/internal/ethapi/testdata/eth_getBlockByHash-hash-1.json @@ -0,0 +1,25 @@ +{ + "baseFeePerGas": "0x342770c0", + "difficulty": "0x20000", + "extraData": "0x", + "gasLimit": "0x47e7c4", + "gasUsed": "0x5208", + "hash": "0x0da274b315de8e4d5bf8717218ec43540464ef36378cb896469bb731e1d3f3cb", + "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "miner": "0x0000000000000000000000000000000000000000", + "mixHash": "0x0000000000000000000000000000000000000000000000000000000000000000", + "nonce": "0x0000000000000000", + "number": "0x1", + "parentHash": "0xbdc7d83b8f876938810462fe8d053263a482e44201e3883d4ae204ff4de7eff5", + "receiptsRoot": "0x056b23fbba480696b65fe5a59b8f2148a1299103c4f57df839233af2cf4ca2d2", + "sha3Uncles": "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347", + "size": "0x26a", + "stateRoot": "0x92c5c55a698963f5b06e3aee415630f5c48b0760e537af94917ce9c4f42a2e22", + "timestamp": "0xa", + "totalDifficulty": "0x1", + "transactions": [ + "0x644a31c354391520d00e95b9affbbb010fc79ac268144ab8e28207f4cf51097e" + ], + "transactionsRoot": "0xca0ebcce920d2cdfbf9e1dbe90ed3441a1a576f344bd80e60508da814916f4e7", + "uncles": [] +} \ No newline at end of file
diff --git ethereum/go-ethereum/internal/ethapi/testdata/eth_getBlockByHash-hash-empty-fullTx.json taikoxyz/taiko-geth/internal/ethapi/testdata/eth_getBlockByHash-hash-empty-fullTx.json new file mode 100644 index 0000000000000000000000000000000000000000..ec747fa47ddb81e9bf2d282011ed32aa4c59f932 --- /dev/null +++ taikoxyz/taiko-geth/internal/ethapi/testdata/eth_getBlockByHash-hash-empty-fullTx.json @@ -0,0 +1 @@ +null \ No newline at end of file
diff --git ethereum/go-ethereum/internal/ethapi/testdata/eth_getBlockByHash-hash-genesis.json taikoxyz/taiko-geth/internal/ethapi/testdata/eth_getBlockByHash-hash-genesis.json new file mode 100644 index 0000000000000000000000000000000000000000..759dbf69e9499367c3d22abf5d9644c36c77149c --- /dev/null +++ taikoxyz/taiko-geth/internal/ethapi/testdata/eth_getBlockByHash-hash-genesis.json @@ -0,0 +1,23 @@ +{ + "baseFeePerGas": "0x3b9aca00", + "difficulty": "0x20000", + "extraData": "0x", + "gasLimit": "0x47e7c4", + "gasUsed": "0x0", + "hash": "0xbdc7d83b8f876938810462fe8d053263a482e44201e3883d4ae204ff4de7eff5", + "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "miner": "0x0000000000000000000000000000000000000000", + "mixHash": "0x0000000000000000000000000000000000000000000000000000000000000000", + "nonce": "0x0000000000000000", + "number": "0x0", + "parentHash": "0x0000000000000000000000000000000000000000000000000000000000000000", + "receiptsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", + "sha3Uncles": "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347", + "size": "0x200", + "stateRoot": "0xfe168c5e9584a85927212e5bea5304bb7d0d8a893453b4b2c52176a72f585ae2", + "timestamp": "0x0", + "totalDifficulty": "0x1", + "transactions": [], + "transactionsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", + "uncles": [] +} \ No newline at end of file
diff --git ethereum/go-ethereum/internal/ethapi/testdata/eth_getBlockByHash-hash-latest-1-fullTx.json taikoxyz/taiko-geth/internal/ethapi/testdata/eth_getBlockByHash-hash-latest-1-fullTx.json new file mode 100644 index 0000000000000000000000000000000000000000..3526da1219a7cbf3f7d00f65ff7c16d3c7f5fb11 --- /dev/null +++ taikoxyz/taiko-geth/internal/ethapi/testdata/eth_getBlockByHash-hash-latest-1-fullTx.json @@ -0,0 +1,41 @@ +{ + "baseFeePerGas": "0x121a9cca", + "difficulty": "0x20000", + "extraData": "0x", + "gasLimit": "0x47e7c4", + "gasUsed": "0x5208", + "hash": "0xda97ed946e0d502fb898b0ac881bd44da3c7fee5eaf184431e1ec3d361dad17e", + "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "miner": "0x0000000000000000000000000000000000000000", + "mixHash": "0x0000000000000000000000000000000000000000000000000000000000000000", + "nonce": "0x0000000000000000", + "number": "0x9", + "parentHash": "0x5abd19c39d9f1c6e52998e135ea14e1fbc5db3fa2a108f4538e238ca5c2e68d7", + "receiptsRoot": "0x056b23fbba480696b65fe5a59b8f2148a1299103c4f57df839233af2cf4ca2d2", + "sha3Uncles": "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347", + "size": "0x26a", + "stateRoot": "0xbd4aa2c2873df709151075250a8c01c9a14d2b0e2f715dbdd16e0ef8030c2cf0", + "timestamp": "0x5a", + "totalDifficulty": "0x1", + "transactions": [ + { + "blockHash": "0xda97ed946e0d502fb898b0ac881bd44da3c7fee5eaf184431e1ec3d361dad17e", + "blockNumber": "0x9", + "from": "0x703c4b2bd70c169f5717101caee543299fc946c7", + "gas": "0x5208", + "gasPrice": "0x121a9cca", + "hash": "0xecd155a61a5734b3efab75924e3ae34026c7c4133d8c2a46122bd03d7d199725", + "input": "0x", + "nonce": "0x8", + "to": "0x0d3ab14bbad3d99f4203bd7a11acb94882050e7e", + "transactionIndex": "0x0", + "value": "0x3e8", + "type": "0x0", + "v": "0x1b", + "r": "0xc6028b8e983d62fa8542f8a7633fb23cc941be2c897134352d95a7d9b19feafd", + "s": "0xeb6adcaaae3bed489c6cce4435f9db05d23a52820c78bd350e31eec65ed809d" + } + ], + "transactionsRoot": "0x0767ed8359337dc6a8fdc77fe52db611bed1be87aac73c4556b1bf1dd3d190a5", + "uncles": [] +} \ No newline at end of file
diff --git ethereum/go-ethereum/internal/ethapi/testdata/eth_getBlockByHash-hash-latest.json taikoxyz/taiko-geth/internal/ethapi/testdata/eth_getBlockByHash-hash-latest.json new file mode 100644 index 0000000000000000000000000000000000000000..32fee83268fba4b8750b086d2024cd8d781732b8 --- /dev/null +++ taikoxyz/taiko-geth/internal/ethapi/testdata/eth_getBlockByHash-hash-latest.json @@ -0,0 +1,25 @@ +{ + "baseFeePerGas": "0xfdc7303", + "difficulty": "0x20000", + "extraData": "0x", + "gasLimit": "0x47e7c4", + "gasUsed": "0x5208", + "hash": "0x97f540a3577c0f645c5dada5da86f38350e8f847e71f21124f917835003e2607", + "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "miner": "0x0000000000000000000000000000000000000000", + "mixHash": "0x0000000000000000000000000000000000000000000000000000000000000000", + "nonce": "0x0000000000000000", + "number": "0xa", + "parentHash": "0xda97ed946e0d502fb898b0ac881bd44da3c7fee5eaf184431e1ec3d361dad17e", + "receiptsRoot": "0x056b23fbba480696b65fe5a59b8f2148a1299103c4f57df839233af2cf4ca2d2", + "sha3Uncles": "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347", + "size": "0x26a", + "stateRoot": "0xbb62872e4023fa8a8b17b9cc37031f4817d9595779748d01cba408b495707a91", + "timestamp": "0x64", + "totalDifficulty": "0x1", + "transactions": [ + "0x3ee4094ca1e0b07a66dd616a057e081e53144ca7e9685a126fd4dda9ca042644" + ], + "transactionsRoot": "0xb0893d21a4a44dc26a962a6e91abae66df87fb61ac9c60e936aee89c76331445", + "uncles": [] +} \ No newline at end of file
diff --git ethereum/go-ethereum/internal/ethapi/testdata/eth_getBlockByHash-hash-pending-fullTx.json taikoxyz/taiko-geth/internal/ethapi/testdata/eth_getBlockByHash-hash-pending-fullTx.json new file mode 100644 index 0000000000000000000000000000000000000000..ec747fa47ddb81e9bf2d282011ed32aa4c59f932 --- /dev/null +++ taikoxyz/taiko-geth/internal/ethapi/testdata/eth_getBlockByHash-hash-pending-fullTx.json @@ -0,0 +1 @@ +null \ No newline at end of file
diff --git ethereum/go-ethereum/internal/ethapi/testdata/eth_getBlockByHash-hash-pending.json taikoxyz/taiko-geth/internal/ethapi/testdata/eth_getBlockByHash-hash-pending.json new file mode 100644 index 0000000000000000000000000000000000000000..ec747fa47ddb81e9bf2d282011ed32aa4c59f932 --- /dev/null +++ taikoxyz/taiko-geth/internal/ethapi/testdata/eth_getBlockByHash-hash-pending.json @@ -0,0 +1 @@ +null \ No newline at end of file
diff --git ethereum/go-ethereum/internal/ethapi/testdata/eth_getBlockByNumber-number-0.json taikoxyz/taiko-geth/internal/ethapi/testdata/eth_getBlockByNumber-number-0.json new file mode 100644 index 0000000000000000000000000000000000000000..759dbf69e9499367c3d22abf5d9644c36c77149c --- /dev/null +++ taikoxyz/taiko-geth/internal/ethapi/testdata/eth_getBlockByNumber-number-0.json @@ -0,0 +1,23 @@ +{ + "baseFeePerGas": "0x3b9aca00", + "difficulty": "0x20000", + "extraData": "0x", + "gasLimit": "0x47e7c4", + "gasUsed": "0x0", + "hash": "0xbdc7d83b8f876938810462fe8d053263a482e44201e3883d4ae204ff4de7eff5", + "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "miner": "0x0000000000000000000000000000000000000000", + "mixHash": "0x0000000000000000000000000000000000000000000000000000000000000000", + "nonce": "0x0000000000000000", + "number": "0x0", + "parentHash": "0x0000000000000000000000000000000000000000000000000000000000000000", + "receiptsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", + "sha3Uncles": "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347", + "size": "0x200", + "stateRoot": "0xfe168c5e9584a85927212e5bea5304bb7d0d8a893453b4b2c52176a72f585ae2", + "timestamp": "0x0", + "totalDifficulty": "0x1", + "transactions": [], + "transactionsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", + "uncles": [] +} \ No newline at end of file
diff --git ethereum/go-ethereum/internal/ethapi/testdata/eth_getBlockByNumber-number-1.json taikoxyz/taiko-geth/internal/ethapi/testdata/eth_getBlockByNumber-number-1.json new file mode 100644 index 0000000000000000000000000000000000000000..379636d5f380708426324ee2cbf8aedc6593c16b --- /dev/null +++ taikoxyz/taiko-geth/internal/ethapi/testdata/eth_getBlockByNumber-number-1.json @@ -0,0 +1,25 @@ +{ + "baseFeePerGas": "0x342770c0", + "difficulty": "0x20000", + "extraData": "0x", + "gasLimit": "0x47e7c4", + "gasUsed": "0x5208", + "hash": "0x0da274b315de8e4d5bf8717218ec43540464ef36378cb896469bb731e1d3f3cb", + "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "miner": "0x0000000000000000000000000000000000000000", + "mixHash": "0x0000000000000000000000000000000000000000000000000000000000000000", + "nonce": "0x0000000000000000", + "number": "0x1", + "parentHash": "0xbdc7d83b8f876938810462fe8d053263a482e44201e3883d4ae204ff4de7eff5", + "receiptsRoot": "0x056b23fbba480696b65fe5a59b8f2148a1299103c4f57df839233af2cf4ca2d2", + "sha3Uncles": "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347", + "size": "0x26a", + "stateRoot": "0x92c5c55a698963f5b06e3aee415630f5c48b0760e537af94917ce9c4f42a2e22", + "timestamp": "0xa", + "totalDifficulty": "0x1", + "transactions": [ + "0x644a31c354391520d00e95b9affbbb010fc79ac268144ab8e28207f4cf51097e" + ], + "transactionsRoot": "0xca0ebcce920d2cdfbf9e1dbe90ed3441a1a576f344bd80e60508da814916f4e7", + "uncles": [] +} \ No newline at end of file
diff --git ethereum/go-ethereum/internal/ethapi/testdata/eth_getBlockByNumber-number-latest+1.json taikoxyz/taiko-geth/internal/ethapi/testdata/eth_getBlockByNumber-number-latest+1.json new file mode 100644 index 0000000000000000000000000000000000000000..ec747fa47ddb81e9bf2d282011ed32aa4c59f932 --- /dev/null +++ taikoxyz/taiko-geth/internal/ethapi/testdata/eth_getBlockByNumber-number-latest+1.json @@ -0,0 +1 @@ +null \ No newline at end of file
diff --git ethereum/go-ethereum/internal/ethapi/testdata/eth_getBlockByNumber-number-latest-1.json taikoxyz/taiko-geth/internal/ethapi/testdata/eth_getBlockByNumber-number-latest-1.json new file mode 100644 index 0000000000000000000000000000000000000000..3526da1219a7cbf3f7d00f65ff7c16d3c7f5fb11 --- /dev/null +++ taikoxyz/taiko-geth/internal/ethapi/testdata/eth_getBlockByNumber-number-latest-1.json @@ -0,0 +1,41 @@ +{ + "baseFeePerGas": "0x121a9cca", + "difficulty": "0x20000", + "extraData": "0x", + "gasLimit": "0x47e7c4", + "gasUsed": "0x5208", + "hash": "0xda97ed946e0d502fb898b0ac881bd44da3c7fee5eaf184431e1ec3d361dad17e", + "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "miner": "0x0000000000000000000000000000000000000000", + "mixHash": "0x0000000000000000000000000000000000000000000000000000000000000000", + "nonce": "0x0000000000000000", + "number": "0x9", + "parentHash": "0x5abd19c39d9f1c6e52998e135ea14e1fbc5db3fa2a108f4538e238ca5c2e68d7", + "receiptsRoot": "0x056b23fbba480696b65fe5a59b8f2148a1299103c4f57df839233af2cf4ca2d2", + "sha3Uncles": "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347", + "size": "0x26a", + "stateRoot": "0xbd4aa2c2873df709151075250a8c01c9a14d2b0e2f715dbdd16e0ef8030c2cf0", + "timestamp": "0x5a", + "totalDifficulty": "0x1", + "transactions": [ + { + "blockHash": "0xda97ed946e0d502fb898b0ac881bd44da3c7fee5eaf184431e1ec3d361dad17e", + "blockNumber": "0x9", + "from": "0x703c4b2bd70c169f5717101caee543299fc946c7", + "gas": "0x5208", + "gasPrice": "0x121a9cca", + "hash": "0xecd155a61a5734b3efab75924e3ae34026c7c4133d8c2a46122bd03d7d199725", + "input": "0x", + "nonce": "0x8", + "to": "0x0d3ab14bbad3d99f4203bd7a11acb94882050e7e", + "transactionIndex": "0x0", + "value": "0x3e8", + "type": "0x0", + "v": "0x1b", + "r": "0xc6028b8e983d62fa8542f8a7633fb23cc941be2c897134352d95a7d9b19feafd", + "s": "0xeb6adcaaae3bed489c6cce4435f9db05d23a52820c78bd350e31eec65ed809d" + } + ], + "transactionsRoot": "0x0767ed8359337dc6a8fdc77fe52db611bed1be87aac73c4556b1bf1dd3d190a5", + "uncles": [] +} \ No newline at end of file
diff --git ethereum/go-ethereum/internal/ethapi/testdata/eth_getBlockByNumber-tag-latest.json taikoxyz/taiko-geth/internal/ethapi/testdata/eth_getBlockByNumber-tag-latest.json new file mode 100644 index 0000000000000000000000000000000000000000..32fee83268fba4b8750b086d2024cd8d781732b8 --- /dev/null +++ taikoxyz/taiko-geth/internal/ethapi/testdata/eth_getBlockByNumber-tag-latest.json @@ -0,0 +1,25 @@ +{ + "baseFeePerGas": "0xfdc7303", + "difficulty": "0x20000", + "extraData": "0x", + "gasLimit": "0x47e7c4", + "gasUsed": "0x5208", + "hash": "0x97f540a3577c0f645c5dada5da86f38350e8f847e71f21124f917835003e2607", + "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "miner": "0x0000000000000000000000000000000000000000", + "mixHash": "0x0000000000000000000000000000000000000000000000000000000000000000", + "nonce": "0x0000000000000000", + "number": "0xa", + "parentHash": "0xda97ed946e0d502fb898b0ac881bd44da3c7fee5eaf184431e1ec3d361dad17e", + "receiptsRoot": "0x056b23fbba480696b65fe5a59b8f2148a1299103c4f57df839233af2cf4ca2d2", + "sha3Uncles": "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347", + "size": "0x26a", + "stateRoot": "0xbb62872e4023fa8a8b17b9cc37031f4817d9595779748d01cba408b495707a91", + "timestamp": "0x64", + "totalDifficulty": "0x1", + "transactions": [ + "0x3ee4094ca1e0b07a66dd616a057e081e53144ca7e9685a126fd4dda9ca042644" + ], + "transactionsRoot": "0xb0893d21a4a44dc26a962a6e91abae66df87fb61ac9c60e936aee89c76331445", + "uncles": [] +} \ No newline at end of file
diff --git ethereum/go-ethereum/internal/ethapi/testdata/eth_getBlockByNumber-tag-pending-fullTx.json taikoxyz/taiko-geth/internal/ethapi/testdata/eth_getBlockByNumber-tag-pending-fullTx.json new file mode 100644 index 0000000000000000000000000000000000000000..1d524d6eced19249ab7f1d7beeb04863087e81c1 --- /dev/null +++ taikoxyz/taiko-geth/internal/ethapi/testdata/eth_getBlockByNumber-tag-pending-fullTx.json @@ -0,0 +1,50 @@ +{ + "difficulty": "0x0", + "extraData": "0x", + "gasLimit": "0x0", + "gasUsed": "0x0", + "hash": null, + "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "miner": null, + "mixHash": "0x0000000000000000000000000000000000000000000000000000000000000000", + "nonce": null, + "number": "0xb", + "parentHash": "0x0000000000000000000000000000000000000000000000000000000000000000", + "receiptsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", + "sha3Uncles": "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347", + "size": "0x256", + "stateRoot": "0x0000000000000000000000000000000000000000000000000000000000000000", + "timestamp": "0x2a", + "totalDifficulty": null, + "transactions": [ + { + "blockHash": "0x6cebd9f966ea686f44b981685e3f0eacea28591a7a86d7fbbe521a86e9f81165", + "blockNumber": "0xb", + "from": "0x0000000000000000000000000000000000000000", + "gas": "0x457", + "gasPrice": "0x2b67", + "hash": "0x4afee081df5dff7a025964032871f7d4ba4d21baf5f6376a2f4a9f79fc506298", + "input": "0x111111", + "nonce": "0xb", + "to": "0x0d3ab14bbad3d99f4203bd7a11acb94882050e7e", + "transactionIndex": "0x0", + "value": "0x6f", + "type": "0x0", + "chainId": "0x7fffffffffffffee", + "v": "0x0", + "r": "0x0", + "s": "0x0" + } + ], + "transactionsRoot": "0x98d9f6dd0aa479c0fb448f2627e9f1964aca699fccab8f6e95861547a4699e37", + "uncles": [], + "withdrawals": [ + { + "index": "0x0", + "validatorIndex": "0x1", + "address": "0x1234000000000000000000000000000000000000", + "amount": "0xa" + } + ], + "withdrawalsRoot": "0x73d756269cdfc22e7e17a3548e36f42f750ca06d7e3cd98d1b6d0eb5add9dc84" +} \ No newline at end of file
diff --git ethereum/go-ethereum/internal/ethapi/testdata/eth_getBlockByNumber-tag-pending.json taikoxyz/taiko-geth/internal/ethapi/testdata/eth_getBlockByNumber-tag-pending.json new file mode 100644 index 0000000000000000000000000000000000000000..c0e2b07bb8aa78eba79fd1896a451092dc8f47ad --- /dev/null +++ taikoxyz/taiko-geth/internal/ethapi/testdata/eth_getBlockByNumber-tag-pending.json @@ -0,0 +1,33 @@ +{ + "difficulty": "0x0", + "extraData": "0x", + "gasLimit": "0x0", + "gasUsed": "0x0", + "hash": null, + "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "miner": null, + "mixHash": "0x0000000000000000000000000000000000000000000000000000000000000000", + "nonce": null, + "number": "0xb", + "parentHash": "0x0000000000000000000000000000000000000000000000000000000000000000", + "receiptsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", + "sha3Uncles": "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347", + "size": "0x256", + "stateRoot": "0x0000000000000000000000000000000000000000000000000000000000000000", + "timestamp": "0x2a", + "totalDifficulty": null, + "transactions": [ + "0x4afee081df5dff7a025964032871f7d4ba4d21baf5f6376a2f4a9f79fc506298" + ], + "transactionsRoot": "0x98d9f6dd0aa479c0fb448f2627e9f1964aca699fccab8f6e95861547a4699e37", + "uncles": [], + "withdrawals": [ + { + "index": "0x0", + "validatorIndex": "0x1", + "address": "0x1234000000000000000000000000000000000000", + "amount": "0xa" + } + ], + "withdrawalsRoot": "0x73d756269cdfc22e7e17a3548e36f42f750ca06d7e3cd98d1b6d0eb5add9dc84" +} \ No newline at end of file
diff --git ethereum/go-ethereum/internal/ethapi/testdata/eth_getBlockReceipts-block-notfound.json taikoxyz/taiko-geth/internal/ethapi/testdata/eth_getBlockReceipts-block-notfound.json new file mode 100644 index 0000000000000000000000000000000000000000..ec747fa47ddb81e9bf2d282011ed32aa4c59f932 --- /dev/null +++ taikoxyz/taiko-geth/internal/ethapi/testdata/eth_getBlockReceipts-block-notfound.json @@ -0,0 +1 @@ +null \ No newline at end of file
diff --git ethereum/go-ethereum/internal/ethapi/testdata/eth_getBlockReceipts-block-with-blob-tx.json taikoxyz/taiko-geth/internal/ethapi/testdata/eth_getBlockReceipts-block-with-blob-tx.json new file mode 100644 index 0000000000000000000000000000000000000000..591fab673d3460f7be0ac54d5793ed0ba6290e3d --- /dev/null +++ taikoxyz/taiko-geth/internal/ethapi/testdata/eth_getBlockReceipts-block-with-blob-tx.json @@ -0,0 +1,20 @@ +[ + { + "blobGasPrice": "0x1", + "blobGasUsed": "0x20000", + "blockHash": "0xe724dfd4349861f4dceef2bc4df086d0a3d88858214f6bee9fcf1bebd1edc2a6", + "blockNumber": "0x6", + "contractAddress": null, + "cumulativeGasUsed": "0x5208", + "effectiveGasPrice": "0x1b09d63b", + "from": "0x703c4b2bd70c169f5717101caee543299fc946c7", + "gasUsed": "0x5208", + "logs": [], + "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "status": "0x1", + "to": "0x0d3ab14bbad3d99f4203bd7a11acb94882050e7e", + "transactionHash": "0xb51ee3d2a89ba5d5623c73133c8d7a6ba9fb41194c17f4302c21b30994a1180f", + "transactionIndex": "0x0", + "type": "0x3" + } +] \ No newline at end of file
diff --git ethereum/go-ethereum/internal/ethapi/testdata/eth_getBlockReceipts-block-with-contract-create-tx.json taikoxyz/taiko-geth/internal/ethapi/testdata/eth_getBlockReceipts-block-with-contract-create-tx.json new file mode 100644 index 0000000000000000000000000000000000000000..f1e0db22c2dc49205bf390b866eb203b2f00193c --- /dev/null +++ taikoxyz/taiko-geth/internal/ethapi/testdata/eth_getBlockReceipts-block-with-contract-create-tx.json @@ -0,0 +1,18 @@ +[ + { + "blockHash": "0x1e7dcf3abe8bf05d32367a5dc387caa32578b15871bf8b3cbeedf2d8d530f844", + "blockNumber": "0x2", + "contractAddress": "0xae9bea628c4ce503dcfd7e305cab4e29e7476592", + "cumulativeGasUsed": "0xcf50", + "effectiveGasPrice": "0x2db16291", + "from": "0x703c4b2bd70c169f5717101caee543299fc946c7", + "gasUsed": "0xcf50", + "logs": [], + "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "status": "0x1", + "to": null, + "transactionHash": "0x340e58cda5086495010b571fe25067fecc9954dc4ee3cedece00691fa3f5904a", + "transactionIndex": "0x0", + "type": "0x0" + } +] \ No newline at end of file
diff --git ethereum/go-ethereum/internal/ethapi/testdata/eth_getBlockReceipts-block-with-dynamic-fee-tx.json taikoxyz/taiko-geth/internal/ethapi/testdata/eth_getBlockReceipts-block-with-dynamic-fee-tx.json new file mode 100644 index 0000000000000000000000000000000000000000..520e30e4ea8fac8ff63ce8e9002fb805b266307c --- /dev/null +++ taikoxyz/taiko-geth/internal/ethapi/testdata/eth_getBlockReceipts-block-with-dynamic-fee-tx.json @@ -0,0 +1,18 @@ +[ + { + "blockHash": "0xffa737e6ce9a9162ffd411dd06169114b3ed5ee9fc1474a2625c92548e4455e0", + "blockNumber": "0x4", + "contractAddress": null, + "cumulativeGasUsed": "0x538d", + "effectiveGasPrice": "0x2325c42f", + "from": "0x703c4b2bd70c169f5717101caee543299fc946c7", + "gasUsed": "0x538d", + "logs": [], + "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "status": "0x0", + "to": "0x0000000000000000000000000000000000031ec7", + "transactionHash": "0xdcde2574628c9d7dff22b9afa19f235959a924ceec65a9df903a517ae91f5c84", + "transactionIndex": "0x0", + "type": "0x2" + } +] \ No newline at end of file
diff --git ethereum/go-ethereum/internal/ethapi/testdata/eth_getBlockReceipts-block-with-legacy-contract-call-tx.json taikoxyz/taiko-geth/internal/ethapi/testdata/eth_getBlockReceipts-block-with-legacy-contract-call-tx.json new file mode 100644 index 0000000000000000000000000000000000000000..a71cf4b37f0ef98f788ffe4f8fc68a8af7a1aa00 --- /dev/null +++ taikoxyz/taiko-geth/internal/ethapi/testdata/eth_getBlockReceipts-block-with-legacy-contract-call-tx.json @@ -0,0 +1,34 @@ +[ + { + "blockHash": "0x173dcd9d22ce71929cd17e84ea88702a0f84d6244c6898d2a4f48722e494fe9c", + "blockNumber": "0x3", + "contractAddress": null, + "cumulativeGasUsed": "0x5e28", + "effectiveGasPrice": "0x281c2585", + "from": "0x703c4b2bd70c169f5717101caee543299fc946c7", + "gasUsed": "0x5e28", + "logs": [ + { + "address": "0x0000000000000000000000000000000000031ec7", + "topics": [ + "0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef", + "0x000000000000000000000000703c4b2bd70c169f5717101caee543299fc946c7", + "0x0000000000000000000000000000000000000000000000000000000000000003" + ], + "data": "0x000000000000000000000000000000000000000000000000000000000000000d", + "blockNumber": "0x3", + "transactionHash": "0xeaf3921cbf03ba45bad4e6ab807b196ce3b2a0b5bacc355b6272fa96b11b4287", + "transactionIndex": "0x0", + "blockHash": "0x173dcd9d22ce71929cd17e84ea88702a0f84d6244c6898d2a4f48722e494fe9c", + "logIndex": "0x0", + "removed": false + } + ], + "logsBloom": "0x00000000000000000000008000000000000000000000000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000800000000000000008000000000000000000000000000000000020000000080000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000800000000000000000400000000002000000000000800000000000000000000000000000000000000000000000000000000000000000000000000000000020000000000000000000000000", + "status": "0x1", + "to": "0x0000000000000000000000000000000000031ec7", + "transactionHash": "0xeaf3921cbf03ba45bad4e6ab807b196ce3b2a0b5bacc355b6272fa96b11b4287", + "transactionIndex": "0x0", + "type": "0x0" + } +] \ No newline at end of file
diff --git ethereum/go-ethereum/internal/ethapi/testdata/eth_getBlockReceipts-block-with-legacy-transfer-tx.json taikoxyz/taiko-geth/internal/ethapi/testdata/eth_getBlockReceipts-block-with-legacy-transfer-tx.json new file mode 100644 index 0000000000000000000000000000000000000000..3e16c3062e964a56d7c3d9c3b628b9fac871e82c --- /dev/null +++ taikoxyz/taiko-geth/internal/ethapi/testdata/eth_getBlockReceipts-block-with-legacy-transfer-tx.json @@ -0,0 +1,18 @@ +[ + { + "blockHash": "0xa8a067b3cb3b9ddc6cfb8317bfd08b266fcf9994fc870c1f7ed394acecfadf39", + "blockNumber": "0x1", + "contractAddress": null, + "cumulativeGasUsed": "0x5208", + "effectiveGasPrice": "0x342770c0", + "from": "0x703c4b2bd70c169f5717101caee543299fc946c7", + "gasUsed": "0x5208", + "logs": [], + "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "status": "0x1", + "to": "0x0d3ab14bbad3d99f4203bd7a11acb94882050e7e", + "transactionHash": "0x644a31c354391520d00e95b9affbbb010fc79ac268144ab8e28207f4cf51097e", + "transactionIndex": "0x0", + "type": "0x0" + } +] \ No newline at end of file
diff --git ethereum/go-ethereum/internal/ethapi/testdata/eth_getBlockReceipts-hash-empty.json taikoxyz/taiko-geth/internal/ethapi/testdata/eth_getBlockReceipts-hash-empty.json new file mode 100644 index 0000000000000000000000000000000000000000..ec747fa47ddb81e9bf2d282011ed32aa4c59f932 --- /dev/null +++ taikoxyz/taiko-geth/internal/ethapi/testdata/eth_getBlockReceipts-hash-empty.json @@ -0,0 +1 @@ +null \ No newline at end of file
diff --git ethereum/go-ethereum/internal/ethapi/testdata/eth_getBlockReceipts-hash-notfound.json taikoxyz/taiko-geth/internal/ethapi/testdata/eth_getBlockReceipts-hash-notfound.json new file mode 100644 index 0000000000000000000000000000000000000000..ec747fa47ddb81e9bf2d282011ed32aa4c59f932 --- /dev/null +++ taikoxyz/taiko-geth/internal/ethapi/testdata/eth_getBlockReceipts-hash-notfound.json @@ -0,0 +1 @@ +null \ No newline at end of file
diff --git ethereum/go-ethereum/internal/ethapi/testdata/eth_getBlockReceipts-number-0.json taikoxyz/taiko-geth/internal/ethapi/testdata/eth_getBlockReceipts-number-0.json new file mode 100644 index 0000000000000000000000000000000000000000..0637a088a01e8ddab3bf3fa98dbe804cbde1a0dc --- /dev/null +++ taikoxyz/taiko-geth/internal/ethapi/testdata/eth_getBlockReceipts-number-0.json @@ -0,0 +1 @@ +[] \ No newline at end of file
diff --git ethereum/go-ethereum/internal/ethapi/testdata/eth_getBlockReceipts-number-1.json taikoxyz/taiko-geth/internal/ethapi/testdata/eth_getBlockReceipts-number-1.json new file mode 100644 index 0000000000000000000000000000000000000000..0637a088a01e8ddab3bf3fa98dbe804cbde1a0dc --- /dev/null +++ taikoxyz/taiko-geth/internal/ethapi/testdata/eth_getBlockReceipts-number-1.json @@ -0,0 +1 @@ +[] \ No newline at end of file
diff --git ethereum/go-ethereum/internal/ethapi/testdata/eth_getBlockReceipts-tag-earliest.json taikoxyz/taiko-geth/internal/ethapi/testdata/eth_getBlockReceipts-tag-earliest.json new file mode 100644 index 0000000000000000000000000000000000000000..0637a088a01e8ddab3bf3fa98dbe804cbde1a0dc --- /dev/null +++ taikoxyz/taiko-geth/internal/ethapi/testdata/eth_getBlockReceipts-tag-earliest.json @@ -0,0 +1 @@ +[] \ No newline at end of file
diff --git ethereum/go-ethereum/internal/ethapi/testdata/eth_getBlockReceipts-tag-latest.json taikoxyz/taiko-geth/internal/ethapi/testdata/eth_getBlockReceipts-tag-latest.json new file mode 100644 index 0000000000000000000000000000000000000000..591fab673d3460f7be0ac54d5793ed0ba6290e3d --- /dev/null +++ taikoxyz/taiko-geth/internal/ethapi/testdata/eth_getBlockReceipts-tag-latest.json @@ -0,0 +1,20 @@ +[ + { + "blobGasPrice": "0x1", + "blobGasUsed": "0x20000", + "blockHash": "0xe724dfd4349861f4dceef2bc4df086d0a3d88858214f6bee9fcf1bebd1edc2a6", + "blockNumber": "0x6", + "contractAddress": null, + "cumulativeGasUsed": "0x5208", + "effectiveGasPrice": "0x1b09d63b", + "from": "0x703c4b2bd70c169f5717101caee543299fc946c7", + "gasUsed": "0x5208", + "logs": [], + "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "status": "0x1", + "to": "0x0d3ab14bbad3d99f4203bd7a11acb94882050e7e", + "transactionHash": "0xb51ee3d2a89ba5d5623c73133c8d7a6ba9fb41194c17f4302c21b30994a1180f", + "transactionIndex": "0x0", + "type": "0x3" + } +] \ No newline at end of file
diff --git ethereum/go-ethereum/internal/ethapi/testdata/eth_getHeaderByHash-hash-0.json taikoxyz/taiko-geth/internal/ethapi/testdata/eth_getHeaderByHash-hash-0.json new file mode 100644 index 0000000000000000000000000000000000000000..dc61aa9a2e5d93a73833dd5e6723e1de9ad4ebe5 --- /dev/null +++ taikoxyz/taiko-geth/internal/ethapi/testdata/eth_getHeaderByHash-hash-0.json @@ -0,0 +1,20 @@ +{ + "baseFeePerGas": "0x3b9aca00", + "difficulty": "0x20000", + "extraData": "0x", + "gasLimit": "0x47e7c4", + "gasUsed": "0x0", + "hash": "0xbdc7d83b8f876938810462fe8d053263a482e44201e3883d4ae204ff4de7eff5", + "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "miner": "0x0000000000000000000000000000000000000000", + "mixHash": "0x0000000000000000000000000000000000000000000000000000000000000000", + "nonce": "0x0000000000000000", + "number": "0x0", + "parentHash": "0x0000000000000000000000000000000000000000000000000000000000000000", + "receiptsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", + "sha3Uncles": "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347", + "stateRoot": "0xfe168c5e9584a85927212e5bea5304bb7d0d8a893453b4b2c52176a72f585ae2", + "timestamp": "0x0", + "totalDifficulty": "0x1", + "transactionsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421" +} \ No newline at end of file
diff --git ethereum/go-ethereum/internal/ethapi/testdata/eth_getHeaderByHash-hash-1.json taikoxyz/taiko-geth/internal/ethapi/testdata/eth_getHeaderByHash-hash-1.json new file mode 100644 index 0000000000000000000000000000000000000000..c1dc70f64f131ae89048704c891eb7b08828a6af --- /dev/null +++ taikoxyz/taiko-geth/internal/ethapi/testdata/eth_getHeaderByHash-hash-1.json @@ -0,0 +1,20 @@ +{ + "baseFeePerGas": "0x342770c0", + "difficulty": "0x20000", + "extraData": "0x", + "gasLimit": "0x47e7c4", + "gasUsed": "0x5208", + "hash": "0x0da274b315de8e4d5bf8717218ec43540464ef36378cb896469bb731e1d3f3cb", + "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "miner": "0x0000000000000000000000000000000000000000", + "mixHash": "0x0000000000000000000000000000000000000000000000000000000000000000", + "nonce": "0x0000000000000000", + "number": "0x1", + "parentHash": "0xbdc7d83b8f876938810462fe8d053263a482e44201e3883d4ae204ff4de7eff5", + "receiptsRoot": "0x056b23fbba480696b65fe5a59b8f2148a1299103c4f57df839233af2cf4ca2d2", + "sha3Uncles": "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347", + "stateRoot": "0x92c5c55a698963f5b06e3aee415630f5c48b0760e537af94917ce9c4f42a2e22", + "timestamp": "0xa", + "totalDifficulty": "0x1", + "transactionsRoot": "0xca0ebcce920d2cdfbf9e1dbe90ed3441a1a576f344bd80e60508da814916f4e7" +} \ No newline at end of file
diff --git ethereum/go-ethereum/internal/ethapi/testdata/eth_getHeaderByHash-hash-empty.json taikoxyz/taiko-geth/internal/ethapi/testdata/eth_getHeaderByHash-hash-empty.json new file mode 100644 index 0000000000000000000000000000000000000000..ec747fa47ddb81e9bf2d282011ed32aa4c59f932 --- /dev/null +++ taikoxyz/taiko-geth/internal/ethapi/testdata/eth_getHeaderByHash-hash-empty.json @@ -0,0 +1 @@ +null \ No newline at end of file
diff --git ethereum/go-ethereum/internal/ethapi/testdata/eth_getHeaderByHash-hash-latest-1.json taikoxyz/taiko-geth/internal/ethapi/testdata/eth_getHeaderByHash-hash-latest-1.json new file mode 100644 index 0000000000000000000000000000000000000000..a63ff86700f4ca48ff859697de4f34dba6cb61ed --- /dev/null +++ taikoxyz/taiko-geth/internal/ethapi/testdata/eth_getHeaderByHash-hash-latest-1.json @@ -0,0 +1,20 @@ +{ + "baseFeePerGas": "0x121a9cca", + "difficulty": "0x20000", + "extraData": "0x", + "gasLimit": "0x47e7c4", + "gasUsed": "0x5208", + "hash": "0xda97ed946e0d502fb898b0ac881bd44da3c7fee5eaf184431e1ec3d361dad17e", + "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "miner": "0x0000000000000000000000000000000000000000", + "mixHash": "0x0000000000000000000000000000000000000000000000000000000000000000", + "nonce": "0x0000000000000000", + "number": "0x9", + "parentHash": "0x5abd19c39d9f1c6e52998e135ea14e1fbc5db3fa2a108f4538e238ca5c2e68d7", + "receiptsRoot": "0x056b23fbba480696b65fe5a59b8f2148a1299103c4f57df839233af2cf4ca2d2", + "sha3Uncles": "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347", + "stateRoot": "0xbd4aa2c2873df709151075250a8c01c9a14d2b0e2f715dbdd16e0ef8030c2cf0", + "timestamp": "0x5a", + "totalDifficulty": "0x1", + "transactionsRoot": "0x0767ed8359337dc6a8fdc77fe52db611bed1be87aac73c4556b1bf1dd3d190a5" +} \ No newline at end of file
diff --git ethereum/go-ethereum/internal/ethapi/testdata/eth_getHeaderByHash-hash-latest.json taikoxyz/taiko-geth/internal/ethapi/testdata/eth_getHeaderByHash-hash-latest.json new file mode 100644 index 0000000000000000000000000000000000000000..f2affcc1c96bfe32eb5e175da11220eca8a930f1 --- /dev/null +++ taikoxyz/taiko-geth/internal/ethapi/testdata/eth_getHeaderByHash-hash-latest.json @@ -0,0 +1,20 @@ +{ + "baseFeePerGas": "0xfdc7303", + "difficulty": "0x20000", + "extraData": "0x", + "gasLimit": "0x47e7c4", + "gasUsed": "0x5208", + "hash": "0x97f540a3577c0f645c5dada5da86f38350e8f847e71f21124f917835003e2607", + "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "miner": "0x0000000000000000000000000000000000000000", + "mixHash": "0x0000000000000000000000000000000000000000000000000000000000000000", + "nonce": "0x0000000000000000", + "number": "0xa", + "parentHash": "0xda97ed946e0d502fb898b0ac881bd44da3c7fee5eaf184431e1ec3d361dad17e", + "receiptsRoot": "0x056b23fbba480696b65fe5a59b8f2148a1299103c4f57df839233af2cf4ca2d2", + "sha3Uncles": "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347", + "stateRoot": "0xbb62872e4023fa8a8b17b9cc37031f4817d9595779748d01cba408b495707a91", + "timestamp": "0x64", + "totalDifficulty": "0x1", + "transactionsRoot": "0xb0893d21a4a44dc26a962a6e91abae66df87fb61ac9c60e936aee89c76331445" +} \ No newline at end of file
diff --git ethereum/go-ethereum/internal/ethapi/testdata/eth_getHeaderByHash-hash-pending.json taikoxyz/taiko-geth/internal/ethapi/testdata/eth_getHeaderByHash-hash-pending.json new file mode 100644 index 0000000000000000000000000000000000000000..ec747fa47ddb81e9bf2d282011ed32aa4c59f932 --- /dev/null +++ taikoxyz/taiko-geth/internal/ethapi/testdata/eth_getHeaderByHash-hash-pending.json @@ -0,0 +1 @@ +null \ No newline at end of file
diff --git ethereum/go-ethereum/internal/ethapi/testdata/eth_getHeaderByNumber-number-0.json taikoxyz/taiko-geth/internal/ethapi/testdata/eth_getHeaderByNumber-number-0.json new file mode 100644 index 0000000000000000000000000000000000000000..dc61aa9a2e5d93a73833dd5e6723e1de9ad4ebe5 --- /dev/null +++ taikoxyz/taiko-geth/internal/ethapi/testdata/eth_getHeaderByNumber-number-0.json @@ -0,0 +1,20 @@ +{ + "baseFeePerGas": "0x3b9aca00", + "difficulty": "0x20000", + "extraData": "0x", + "gasLimit": "0x47e7c4", + "gasUsed": "0x0", + "hash": "0xbdc7d83b8f876938810462fe8d053263a482e44201e3883d4ae204ff4de7eff5", + "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "miner": "0x0000000000000000000000000000000000000000", + "mixHash": "0x0000000000000000000000000000000000000000000000000000000000000000", + "nonce": "0x0000000000000000", + "number": "0x0", + "parentHash": "0x0000000000000000000000000000000000000000000000000000000000000000", + "receiptsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", + "sha3Uncles": "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347", + "stateRoot": "0xfe168c5e9584a85927212e5bea5304bb7d0d8a893453b4b2c52176a72f585ae2", + "timestamp": "0x0", + "totalDifficulty": "0x1", + "transactionsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421" +} \ No newline at end of file
diff --git ethereum/go-ethereum/internal/ethapi/testdata/eth_getHeaderByNumber-number-1.json taikoxyz/taiko-geth/internal/ethapi/testdata/eth_getHeaderByNumber-number-1.json new file mode 100644 index 0000000000000000000000000000000000000000..c1dc70f64f131ae89048704c891eb7b08828a6af --- /dev/null +++ taikoxyz/taiko-geth/internal/ethapi/testdata/eth_getHeaderByNumber-number-1.json @@ -0,0 +1,20 @@ +{ + "baseFeePerGas": "0x342770c0", + "difficulty": "0x20000", + "extraData": "0x", + "gasLimit": "0x47e7c4", + "gasUsed": "0x5208", + "hash": "0x0da274b315de8e4d5bf8717218ec43540464ef36378cb896469bb731e1d3f3cb", + "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "miner": "0x0000000000000000000000000000000000000000", + "mixHash": "0x0000000000000000000000000000000000000000000000000000000000000000", + "nonce": "0x0000000000000000", + "number": "0x1", + "parentHash": "0xbdc7d83b8f876938810462fe8d053263a482e44201e3883d4ae204ff4de7eff5", + "receiptsRoot": "0x056b23fbba480696b65fe5a59b8f2148a1299103c4f57df839233af2cf4ca2d2", + "sha3Uncles": "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347", + "stateRoot": "0x92c5c55a698963f5b06e3aee415630f5c48b0760e537af94917ce9c4f42a2e22", + "timestamp": "0xa", + "totalDifficulty": "0x1", + "transactionsRoot": "0xca0ebcce920d2cdfbf9e1dbe90ed3441a1a576f344bd80e60508da814916f4e7" +} \ No newline at end of file
diff --git ethereum/go-ethereum/internal/ethapi/testdata/eth_getHeaderByNumber-number-latest+1.json taikoxyz/taiko-geth/internal/ethapi/testdata/eth_getHeaderByNumber-number-latest+1.json new file mode 100644 index 0000000000000000000000000000000000000000..ec747fa47ddb81e9bf2d282011ed32aa4c59f932 --- /dev/null +++ taikoxyz/taiko-geth/internal/ethapi/testdata/eth_getHeaderByNumber-number-latest+1.json @@ -0,0 +1 @@ +null \ No newline at end of file
diff --git ethereum/go-ethereum/internal/ethapi/testdata/eth_getHeaderByNumber-number-latest-1.json taikoxyz/taiko-geth/internal/ethapi/testdata/eth_getHeaderByNumber-number-latest-1.json new file mode 100644 index 0000000000000000000000000000000000000000..a63ff86700f4ca48ff859697de4f34dba6cb61ed --- /dev/null +++ taikoxyz/taiko-geth/internal/ethapi/testdata/eth_getHeaderByNumber-number-latest-1.json @@ -0,0 +1,20 @@ +{ + "baseFeePerGas": "0x121a9cca", + "difficulty": "0x20000", + "extraData": "0x", + "gasLimit": "0x47e7c4", + "gasUsed": "0x5208", + "hash": "0xda97ed946e0d502fb898b0ac881bd44da3c7fee5eaf184431e1ec3d361dad17e", + "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "miner": "0x0000000000000000000000000000000000000000", + "mixHash": "0x0000000000000000000000000000000000000000000000000000000000000000", + "nonce": "0x0000000000000000", + "number": "0x9", + "parentHash": "0x5abd19c39d9f1c6e52998e135ea14e1fbc5db3fa2a108f4538e238ca5c2e68d7", + "receiptsRoot": "0x056b23fbba480696b65fe5a59b8f2148a1299103c4f57df839233af2cf4ca2d2", + "sha3Uncles": "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347", + "stateRoot": "0xbd4aa2c2873df709151075250a8c01c9a14d2b0e2f715dbdd16e0ef8030c2cf0", + "timestamp": "0x5a", + "totalDifficulty": "0x1", + "transactionsRoot": "0x0767ed8359337dc6a8fdc77fe52db611bed1be87aac73c4556b1bf1dd3d190a5" +} \ No newline at end of file
diff --git ethereum/go-ethereum/internal/ethapi/testdata/eth_getHeaderByNumber-tag-latest.json taikoxyz/taiko-geth/internal/ethapi/testdata/eth_getHeaderByNumber-tag-latest.json new file mode 100644 index 0000000000000000000000000000000000000000..f2affcc1c96bfe32eb5e175da11220eca8a930f1 --- /dev/null +++ taikoxyz/taiko-geth/internal/ethapi/testdata/eth_getHeaderByNumber-tag-latest.json @@ -0,0 +1,20 @@ +{ + "baseFeePerGas": "0xfdc7303", + "difficulty": "0x20000", + "extraData": "0x", + "gasLimit": "0x47e7c4", + "gasUsed": "0x5208", + "hash": "0x97f540a3577c0f645c5dada5da86f38350e8f847e71f21124f917835003e2607", + "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "miner": "0x0000000000000000000000000000000000000000", + "mixHash": "0x0000000000000000000000000000000000000000000000000000000000000000", + "nonce": "0x0000000000000000", + "number": "0xa", + "parentHash": "0xda97ed946e0d502fb898b0ac881bd44da3c7fee5eaf184431e1ec3d361dad17e", + "receiptsRoot": "0x056b23fbba480696b65fe5a59b8f2148a1299103c4f57df839233af2cf4ca2d2", + "sha3Uncles": "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347", + "stateRoot": "0xbb62872e4023fa8a8b17b9cc37031f4817d9595779748d01cba408b495707a91", + "timestamp": "0x64", + "totalDifficulty": "0x1", + "transactionsRoot": "0xb0893d21a4a44dc26a962a6e91abae66df87fb61ac9c60e936aee89c76331445" +} \ No newline at end of file
diff --git ethereum/go-ethereum/internal/ethapi/testdata/eth_getHeaderByNumber-tag-pending.json taikoxyz/taiko-geth/internal/ethapi/testdata/eth_getHeaderByNumber-tag-pending.json new file mode 100644 index 0000000000000000000000000000000000000000..da177f2189282f081feea19c570f81cfff3254d7 --- /dev/null +++ taikoxyz/taiko-geth/internal/ethapi/testdata/eth_getHeaderByNumber-tag-pending.json @@ -0,0 +1,20 @@ +{ + "difficulty": "0x0", + "extraData": "0x", + "gasLimit": "0x0", + "gasUsed": "0x0", + "hash": null, + "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "miner": null, + "mixHash": "0x0000000000000000000000000000000000000000000000000000000000000000", + "nonce": null, + "number": "0xb", + "parentHash": "0x0000000000000000000000000000000000000000000000000000000000000000", + "receiptsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", + "sha3Uncles": "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347", + "stateRoot": "0x0000000000000000000000000000000000000000000000000000000000000000", + "timestamp": "0x2a", + "totalDifficulty": null, + "transactionsRoot": "0x98d9f6dd0aa479c0fb448f2627e9f1964aca699fccab8f6e95861547a4699e37", + "withdrawalsRoot": "0x73d756269cdfc22e7e17a3548e36f42f750ca06d7e3cd98d1b6d0eb5add9dc84" +} \ No newline at end of file
diff --git ethereum/go-ethereum/internal/ethapi/testdata/eth_getTransactionReceipt-blob-tx.json taikoxyz/taiko-geth/internal/ethapi/testdata/eth_getTransactionReceipt-blob-tx.json new file mode 100644 index 0000000000000000000000000000000000000000..c3a4a0deee8c6567fc0d7efcee2fbcafa44136b3 --- /dev/null +++ taikoxyz/taiko-geth/internal/ethapi/testdata/eth_getTransactionReceipt-blob-tx.json @@ -0,0 +1,18 @@ +{ + "blobGasPrice": "0x1", + "blobGasUsed": "0x20000", + "blockHash": "0xe724dfd4349861f4dceef2bc4df086d0a3d88858214f6bee9fcf1bebd1edc2a6", + "blockNumber": "0x6", + "contractAddress": null, + "cumulativeGasUsed": "0x5208", + "effectiveGasPrice": "0x1b09d63b", + "from": "0x703c4b2bd70c169f5717101caee543299fc946c7", + "gasUsed": "0x5208", + "logs": [], + "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "status": "0x1", + "to": "0x0d3ab14bbad3d99f4203bd7a11acb94882050e7e", + "transactionHash": "0xb51ee3d2a89ba5d5623c73133c8d7a6ba9fb41194c17f4302c21b30994a1180f", + "transactionIndex": "0x0", + "type": "0x3" +} \ No newline at end of file
diff --git ethereum/go-ethereum/internal/ethapi/testdata/eth_getTransactionReceipt-create-contract-tx.json taikoxyz/taiko-geth/internal/ethapi/testdata/eth_getTransactionReceipt-create-contract-tx.json new file mode 100644 index 0000000000000000000000000000000000000000..ad6d6152ec3f5d82b10a54bf667b9b2e7dda0018 --- /dev/null +++ taikoxyz/taiko-geth/internal/ethapi/testdata/eth_getTransactionReceipt-create-contract-tx.json @@ -0,0 +1,16 @@ +{ + "blockHash": "0x1e7dcf3abe8bf05d32367a5dc387caa32578b15871bf8b3cbeedf2d8d530f844", + "blockNumber": "0x2", + "contractAddress": "0xae9bea628c4ce503dcfd7e305cab4e29e7476592", + "cumulativeGasUsed": "0xcf50", + "effectiveGasPrice": "0x2db16291", + "from": "0x703c4b2bd70c169f5717101caee543299fc946c7", + "gasUsed": "0xcf50", + "logs": [], + "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "status": "0x1", + "to": null, + "transactionHash": "0x340e58cda5086495010b571fe25067fecc9954dc4ee3cedece00691fa3f5904a", + "transactionIndex": "0x0", + "type": "0x0" +} \ No newline at end of file
diff --git ethereum/go-ethereum/internal/ethapi/testdata/eth_getTransactionReceipt-create-contract-with-access-list.json taikoxyz/taiko-geth/internal/ethapi/testdata/eth_getTransactionReceipt-create-contract-with-access-list.json new file mode 100644 index 0000000000000000000000000000000000000000..b3362260a0a95c31d6d6997e5629c6e37cbc7bd9 --- /dev/null +++ taikoxyz/taiko-geth/internal/ethapi/testdata/eth_getTransactionReceipt-create-contract-with-access-list.json @@ -0,0 +1,16 @@ +{ + "blockHash": "0x3fadc5bc916018a326732be829a2565b3acb960a8406f0f151a5e1fa971ea7dd", + "blockNumber": "0x5", + "contractAddress": "0xfdaa97661a584d977b4d3abb5370766ff5b86a18", + "cumulativeGasUsed": "0xe01c", + "effectiveGasPrice": "0x1ecb3fb4", + "from": "0x703c4b2bd70c169f5717101caee543299fc946c7", + "gasUsed": "0xe01c", + "logs": [], + "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "status": "0x1", + "to": null, + "transactionHash": "0xb5a1148819cfdfff9bfe70035524fec940eb735d89b76960b97751d01ae2a9f2", + "transactionIndex": "0x0", + "type": "0x1" +} \ No newline at end of file
diff --git ethereum/go-ethereum/internal/ethapi/testdata/eth_getTransactionReceipt-dynamic-tx-with-logs.json taikoxyz/taiko-geth/internal/ethapi/testdata/eth_getTransactionReceipt-dynamic-tx-with-logs.json new file mode 100644 index 0000000000000000000000000000000000000000..cc0be1809e7f2ee9aa143d92d4793dce7578fe40 --- /dev/null +++ taikoxyz/taiko-geth/internal/ethapi/testdata/eth_getTransactionReceipt-dynamic-tx-with-logs.json @@ -0,0 +1,16 @@ +{ + "blockHash": "0xffa737e6ce9a9162ffd411dd06169114b3ed5ee9fc1474a2625c92548e4455e0", + "blockNumber": "0x4", + "contractAddress": null, + "cumulativeGasUsed": "0x538d", + "effectiveGasPrice": "0x2325c42f", + "from": "0x703c4b2bd70c169f5717101caee543299fc946c7", + "gasUsed": "0x538d", + "logs": [], + "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "status": "0x0", + "to": "0x0000000000000000000000000000000000031ec7", + "transactionHash": "0xdcde2574628c9d7dff22b9afa19f235959a924ceec65a9df903a517ae91f5c84", + "transactionIndex": "0x0", + "type": "0x2" +} \ No newline at end of file
diff --git ethereum/go-ethereum/internal/ethapi/testdata/eth_getTransactionReceipt-normal-transfer-tx.json taikoxyz/taiko-geth/internal/ethapi/testdata/eth_getTransactionReceipt-normal-transfer-tx.json new file mode 100644 index 0000000000000000000000000000000000000000..d3b6ef1c912a5e826fa69edc91c876510285d43f --- /dev/null +++ taikoxyz/taiko-geth/internal/ethapi/testdata/eth_getTransactionReceipt-normal-transfer-tx.json @@ -0,0 +1,16 @@ +{ + "blockHash": "0xa8a067b3cb3b9ddc6cfb8317bfd08b266fcf9994fc870c1f7ed394acecfadf39", + "blockNumber": "0x1", + "contractAddress": null, + "cumulativeGasUsed": "0x5208", + "effectiveGasPrice": "0x342770c0", + "from": "0x703c4b2bd70c169f5717101caee543299fc946c7", + "gasUsed": "0x5208", + "logs": [], + "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "status": "0x1", + "to": "0x0d3ab14bbad3d99f4203bd7a11acb94882050e7e", + "transactionHash": "0x644a31c354391520d00e95b9affbbb010fc79ac268144ab8e28207f4cf51097e", + "transactionIndex": "0x0", + "type": "0x0" +} \ No newline at end of file
diff --git ethereum/go-ethereum/internal/ethapi/testdata/eth_getTransactionReceipt-txhash-empty.json taikoxyz/taiko-geth/internal/ethapi/testdata/eth_getTransactionReceipt-txhash-empty.json new file mode 100644 index 0000000000000000000000000000000000000000..ec747fa47ddb81e9bf2d282011ed32aa4c59f932 --- /dev/null +++ taikoxyz/taiko-geth/internal/ethapi/testdata/eth_getTransactionReceipt-txhash-empty.json @@ -0,0 +1 @@ +null \ No newline at end of file
diff --git ethereum/go-ethereum/internal/ethapi/testdata/eth_getTransactionReceipt-txhash-notfound.json taikoxyz/taiko-geth/internal/ethapi/testdata/eth_getTransactionReceipt-txhash-notfound.json new file mode 100644 index 0000000000000000000000000000000000000000..ec747fa47ddb81e9bf2d282011ed32aa4c59f932 --- /dev/null +++ taikoxyz/taiko-geth/internal/ethapi/testdata/eth_getTransactionReceipt-txhash-notfound.json @@ -0,0 +1 @@ +null \ No newline at end of file
diff --git ethereum/go-ethereum/internal/ethapi/testdata/eth_getTransactionReceipt-with-logs.json taikoxyz/taiko-geth/internal/ethapi/testdata/eth_getTransactionReceipt-with-logs.json new file mode 100644 index 0000000000000000000000000000000000000000..45a4f6d670313693e2bcafd4ecca9776314daacd --- /dev/null +++ taikoxyz/taiko-geth/internal/ethapi/testdata/eth_getTransactionReceipt-with-logs.json @@ -0,0 +1,32 @@ +{ + "blockHash": "0x173dcd9d22ce71929cd17e84ea88702a0f84d6244c6898d2a4f48722e494fe9c", + "blockNumber": "0x3", + "contractAddress": null, + "cumulativeGasUsed": "0x5e28", + "effectiveGasPrice": "0x281c2585", + "from": "0x703c4b2bd70c169f5717101caee543299fc946c7", + "gasUsed": "0x5e28", + "logs": [ + { + "address": "0x0000000000000000000000000000000000031ec7", + "topics": [ + "0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef", + "0x000000000000000000000000703c4b2bd70c169f5717101caee543299fc946c7", + "0x0000000000000000000000000000000000000000000000000000000000000003" + ], + "data": "0x000000000000000000000000000000000000000000000000000000000000000d", + "blockNumber": "0x3", + "transactionHash": "0xeaf3921cbf03ba45bad4e6ab807b196ce3b2a0b5bacc355b6272fa96b11b4287", + "transactionIndex": "0x0", + "blockHash": "0x173dcd9d22ce71929cd17e84ea88702a0f84d6244c6898d2a4f48722e494fe9c", + "logIndex": "0x0", + "removed": false + } + ], + "logsBloom": "0x00000000000000000000008000000000000000000000000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000800000000000000008000000000000000000000000000000000020000000080000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000800000000000000000400000000002000000000000800000000000000000000000000000000000000000000000000000000000000000000000000000000020000000000000000000000000", + "status": "0x1", + "to": "0x0000000000000000000000000000000000031ec7", + "transactionHash": "0xeaf3921cbf03ba45bad4e6ab807b196ce3b2a0b5bacc355b6272fa96b11b4287", + "transactionIndex": "0x0", + "type": "0x0" +} \ No newline at end of file
diff --git ethereum/go-ethereum/tests/gen_btheader.go taikoxyz/taiko-geth/tests/gen_btheader.go index 985ea692d751dad36132ef52bb8036d5794c528a..80ad89e03bf548393b01102e0687c11940b8f268 100644 --- ethereum/go-ethereum/tests/gen_btheader.go +++ taikoxyz/taiko-geth/tests/gen_btheader.go @@ -17,24 +17,27 @@ // MarshalJSON marshals as JSON. func (b btHeader) MarshalJSON() ([]byte, error) { type btHeader struct { - Bloom types.Bloom - Coinbase common.Address - MixHash common.Hash - Nonce types.BlockNonce - Number *math.HexOrDecimal256 - Hash common.Hash - ParentHash common.Hash - ReceiptTrie common.Hash - StateRoot common.Hash - TransactionsTrie common.Hash - UncleHash common.Hash - ExtraData hexutil.Bytes - Difficulty *math.HexOrDecimal256 - GasLimit math.HexOrDecimal64 - GasUsed math.HexOrDecimal64 - Timestamp math.HexOrDecimal64 - BaseFeePerGas *math.HexOrDecimal256 - WithdrawalsRoot *common.Hash + Bloom types.Bloom + Coinbase common.Address + MixHash common.Hash + Nonce types.BlockNonce + Number *math.HexOrDecimal256 + Hash common.Hash + ParentHash common.Hash + ReceiptTrie common.Hash + StateRoot common.Hash + TransactionsTrie common.Hash + UncleHash common.Hash + ExtraData hexutil.Bytes + Difficulty *math.HexOrDecimal256 + GasLimit math.HexOrDecimal64 + GasUsed math.HexOrDecimal64 + Timestamp math.HexOrDecimal64 + BaseFeePerGas *math.HexOrDecimal256 + WithdrawalsRoot *common.Hash + BlobGasUsed *math.HexOrDecimal64 + ExcessBlobGas *math.HexOrDecimal64 + ParentBeaconBlockRoot *common.Hash } var enc btHeader enc.Bloom = b.Bloom @@ -55,30 +58,36 @@ enc.GasUsed = math.HexOrDecimal64(b.GasUsed) enc.Timestamp = math.HexOrDecimal64(b.Timestamp) enc.BaseFeePerGas = (*math.HexOrDecimal256)(b.BaseFeePerGas) enc.WithdrawalsRoot = b.WithdrawalsRoot + enc.BlobGasUsed = (*math.HexOrDecimal64)(b.BlobGasUsed) + enc.ExcessBlobGas = (*math.HexOrDecimal64)(b.ExcessBlobGas) + enc.ParentBeaconBlockRoot = b.ParentBeaconBlockRoot return json.Marshal(&enc) }   // UnmarshalJSON unmarshals from JSON. func (b *btHeader) UnmarshalJSON(input []byte) error { type btHeader struct { - Bloom *types.Bloom - Coinbase *common.Address - MixHash *common.Hash - Nonce *types.BlockNonce - Number *math.HexOrDecimal256 - Hash *common.Hash - ParentHash *common.Hash - ReceiptTrie *common.Hash - StateRoot *common.Hash - TransactionsTrie *common.Hash - UncleHash *common.Hash - ExtraData *hexutil.Bytes - Difficulty *math.HexOrDecimal256 - GasLimit *math.HexOrDecimal64 - GasUsed *math.HexOrDecimal64 - Timestamp *math.HexOrDecimal64 - BaseFeePerGas *math.HexOrDecimal256 - WithdrawalsRoot *common.Hash + Bloom *types.Bloom + Coinbase *common.Address + MixHash *common.Hash + Nonce *types.BlockNonce + Number *math.HexOrDecimal256 + Hash *common.Hash + ParentHash *common.Hash + ReceiptTrie *common.Hash + StateRoot *common.Hash + TransactionsTrie *common.Hash + UncleHash *common.Hash + ExtraData *hexutil.Bytes + Difficulty *math.HexOrDecimal256 + GasLimit *math.HexOrDecimal64 + GasUsed *math.HexOrDecimal64 + Timestamp *math.HexOrDecimal64 + BaseFeePerGas *math.HexOrDecimal256 + WithdrawalsRoot *common.Hash + BlobGasUsed *math.HexOrDecimal64 + ExcessBlobGas *math.HexOrDecimal64 + ParentBeaconBlockRoot *common.Hash } var dec btHeader if err := json.Unmarshal(input, &dec); err != nil { @@ -137,6 +146,15 @@ b.BaseFeePerGas = (*big.Int)(dec.BaseFeePerGas) } if dec.WithdrawalsRoot != nil { b.WithdrawalsRoot = dec.WithdrawalsRoot + } + if dec.BlobGasUsed != nil { + b.BlobGasUsed = (*uint64)(dec.BlobGasUsed) + } + if dec.ExcessBlobGas != nil { + b.ExcessBlobGas = (*uint64)(dec.ExcessBlobGas) + } + if dec.ParentBeaconBlockRoot != nil { + b.ParentBeaconBlockRoot = dec.ParentBeaconBlockRoot } return nil }
diff --git ethereum/go-ethereum/tests/gen_sttransaction.go taikoxyz/taiko-geth/tests/gen_sttransaction.go index f47da494fa812425a0da266f82eff651d68239ae..9b5aecbfe6b81db8c4eb73f366729c077293114c 100644 --- ethereum/go-ethereum/tests/gen_sttransaction.go +++ taikoxyz/taiko-geth/tests/gen_sttransaction.go @@ -27,6 +27,7 @@ AccessLists []*types.AccessList `json:"accessLists,omitempty"` GasLimit []math.HexOrDecimal64 `json:"gasLimit"` Value []string `json:"value"` PrivateKey hexutil.Bytes `json:"secretKey"` + Sender *common.Address `json:"sender"` BlobVersionedHashes []common.Hash `json:"blobVersionedHashes,omitempty"` BlobGasFeeCap *math.HexOrDecimal256 `json:"maxFeePerBlobGas,omitempty"` } @@ -46,6 +47,7 @@ } } enc.Value = s.Value enc.PrivateKey = s.PrivateKey + enc.Sender = s.Sender enc.BlobVersionedHashes = s.BlobVersionedHashes enc.BlobGasFeeCap = (*math.HexOrDecimal256)(s.BlobGasFeeCap) return json.Marshal(&enc) @@ -64,6 +66,7 @@ AccessLists []*types.AccessList `json:"accessLists,omitempty"` GasLimit []math.HexOrDecimal64 `json:"gasLimit"` Value []string `json:"value"` PrivateKey *hexutil.Bytes `json:"secretKey"` + Sender *common.Address `json:"sender"` BlobVersionedHashes []common.Hash `json:"blobVersionedHashes,omitempty"` BlobGasFeeCap *math.HexOrDecimal256 `json:"maxFeePerBlobGas,omitempty"` } @@ -103,6 +106,9 @@ s.Value = dec.Value } if dec.PrivateKey != nil { s.PrivateKey = *dec.PrivateKey + } + if dec.Sender != nil { + s.Sender = dec.Sender } if dec.BlobVersionedHashes != nil { s.BlobVersionedHashes = dec.BlobVersionedHashes